Expected Behavior Changes After V1 to V2 Migration
This page describes behaviors that may appear unexpected after a V1 to V2 migration but are correct by design. Use this as a first reference before filing a support ticket.
For the migration guide and pre-launch checklist, see:
API response errorsβ
409 VERSION_CONFLICTβ
| |
|---|
| Symptom | A V1 operation returns 409 with error code VERSION_CONFLICT |
| Why it happens | A V1 API operation was attempted on a resource that was created by a V2 operation. V1 operations cannot manage V2-native resources. |
| What to do | Use the equivalent V2 operation instead. Check the Capability Parity Matrix to confirm the V2 operation for each V1 path. |
| Is this a bug? | No. This is the expected response when a version boundary is crossed in the wrong direction. |
409 CROSS_VERSION_NOT_ENABLEDβ
| |
|---|
| Symptom | A V2 write operation on a V1-origin resource returns 409 with error code CROSS_VERSION_NOT_ENABLED |
| Why it happens | Backward compatibility is not enabled for your merchant. V2 cannot write to V1-origin resources until compatibility is activated. |
| What to do | Contact your CCG representative to enable backward compatibility for your merchant in the target environment. Do not retry until you have written confirmation that it has been activated. |
| Is this a bug? | No. Backward compatibility requires an explicit CCG internal admin action β it is not enabled by default. |
404 for a V1-origin resource retrieved through V2β
| |
|---|
| Symptom | GET /v2/payments/{paymentId} returns 404 for a payment that was created through V1 |
| Why it happens | Backward compatibility is not enabled, or the resource ID or merchant ID does not match the target environment. Without compatibility, a V1-origin GET through V2 normally returns 404. |
| What to do | Confirm backward compatibility is enabled for your merchant. Confirm the resource ID, merchant ID, and environment are correct. |
| Is this a bug? | No. This is the documented behavior when compatibility is not enabled. |
Webhook behaviorβ
V1 and V2 webhooks during coexistenceβ
During migration, your webhook handler will receive payloads in both V1 and V2 formats. The webhook shape depends on resource origin and migration phase β not solely on the triggering operation. The following diagram shows two distinct operations on a V1-origin payment during the coexistence phase:
| |
|---|
| Symptom | Your webhook handler receives both V1-shaped and V2-shaped payloads during the migration period |
| Why it happens | Webhook shape depends on resource origin and migration phase: during coexistence, capture and cancel on V1-origin payments via the V2 API emit V1-shaped webhooks; V2-native payment actions emit V2-shaped webhooks; refunds created through the V2 API emit V2-shaped webhooks. After merchant-level webhook migration is activated, all subsequent webhooks switch to V2 shape regardless of resource origin. See Backward Compatibility for the full operation-to-shape mapping by phase. |
| What to do | Select the V1 or V2 parser based on resource origin, triggering operation, and your current migration phase β not by arrival order. Defer to the Backward Compatibility operation-to-shape table for the exact parser-selection rules. Retrieve the resource before any irreversible action. |
| Is this a bug? | No. Mixed webhook shapes during coexistence are expected and documented. |
Webhook arrives before the API GET responseβ
| |
|---|
| Symptom | A webhook for a payment or refund arrives before your application finishes processing the API response |
| Why it happens | V2 webhooks fire asynchronously and delivery order is not guaranteed relative to the API response. |
| What to do | Do not take irreversible actions based solely on a webhook without first retrieving the resource via the GET endpoint to confirm its state. Implement deduplication to handle retries and out-of-order delivery. |
| Is this a bug? | No. Async delivery is by design. |
| |
|---|
| Symptom | After updating the <script> src to a v3 URL, the browser still loads the old v2 widget |
| Why it happens | Because the version segment (v3.6.0 or v3) is part of the URL, a cached /wallet/v2/ bundle cannot be returned for a /wallet/v3/ request. If v2 still loads after a URL change, the most likely causes are: (1) a second <script> tag or loader elsewhere in the page still referencing a v2 URL; (2) the src attribute was not actually saved and deployed; (3) the major-version alias (wallet/v3/) is propagating a recent CDN update β allow a few minutes and hard-refresh. |
| What to do | First, verify the exact URL being requested in the browser Network tab and confirm no other loader is active. If a confirmed v3 URL is serving v2 content, escalate to your CCG representative β this is not expected caching behavior. If the URL in the Network tab is still a v2 URL, locate and update the remaining reference. |
| Is this a bug? | Not if the URL in the Network tab is still a v2 address β update the reference. If a confirmed v3 URL returns v2 content, escalate. |
| |
|---|
| Symptom | The widget does not show the split-tender option even after migrating to v3 |
| Why it happens | One or more of the following conditions is not met: (1) the session mode is not exclusively PAYMENT_WITH_WALLET; (2) the session's resolved payment-method types do not include CARD β a customer may have a saved card but the session may be configured for BANK_ACCOUNT only, which blocks split tender regardless; (3) split tender is not enabled at the merchant level β this is a hard gate that requires CCG to activate; (4) the session's resolved splitTender configuration is effectively disabled. |
| What to do | Confirm all of the following: (1) the session mode is PAYMENT_WITH_WALLET; (2) the session's resolved payment-method configuration includes CARD β check the session response, not just the customer's saved payment methods; (3) split tender is enabled for your merchant by CCG; (4) config.splitTender.enabled is not explicitly set to false in the session request β omitting it inherits the merchant default; (5) payment.authorizeCard is not true in the session request β authorize-only sessions suppress the split-tender toggle. If all conditions are met, contact your CCG representative. |
| Is this a bug? | No. Split tender is card-only and requires explicit enablement. |
HSA balance not visible in the walletβ
| |
|---|
| Symptom | The HSA balance display is absent in the widget for a customer who should have HSA context |
| Why it happens | HSA-aware wallet capabilities are optional and depend on approved merchant and release configuration. The HSA context may not be available for every merchant, session, or customer. |
| What to do | Confirm HSA display is enabled for your merchant. If it should be available and is not appearing, contact your CCG representative with merchant ID, session ID, and environment. |
| Is this a bug? | No. Unavailable optional HSA context must not prevent access to stored payment methods or payment completion β other payment methods remain available. |
Reconciliation and reportingβ
Payment amounts appear split across two line itemsβ
| |
|---|
| Symptom | A single customer-facing split-tender payment appears as two separate charge records in your reporting extract |
| Why it happens | Each allocation (card leg) of a split-tender payment is charged separately. Both charges appear in the merchant reporting extract. |
| What to do | Reconcile by the referenceId field in your reporting extract β when ccg_paymentAllocationId is present, referenceId is the parent transaction identifier that groups all payment legs together. See Report Metadata and the Capability Parity Matrix for reporting considerations. |
| Is this a bug? | No. This is the expected V2 split-tender reporting behavior. |
Still seeing unexpected behavior?β
If your symptom is not listed here or the recommended action did not resolve it, contact your CCG representative.