Checking access…

Skip to main content
Version: v2

Confirming a Payment Allocation (3DS)

When a payment allocation requires 3D Secure (3DS) authentication, it enters either the AUTH_REQUIRED or CONFIRMATION_REQUIRED status. The customer must complete the 3DS challenge in their browser or app before the allocation can proceed. Once the challenge is complete, the merchant calls the Confirm Allocation endpoint to continue the payment flow for that specific allocation.

Business Context

For business rules and lifecycle details, see Split Tender Payments β€” Business Guide.


Integration Details
  • Prerequisites: Merchant account must be configured for split-tender payments. The allocation must be in AUTH_REQUIRED or CONFIRMATION_REQUIRED status.
  • API Endpoint: PATCH /v2/payments/{paymentId}/allocations/{allocationId}/confirm
  • API Spec: Confirm Payment Allocation
  • Scope: merchant
  • API Version: v2
  • Required Headers: X-Merchant-Id (UUID), X-Checkout-Id (UUID)
  • Request Body: None
  • Response: 202 Accepted β€” updated transaction with the confirmed allocation in CONFIRMATION_INITIALIZED
  • Error Handling: See Payment Error Codes for applicable error codes.

When to Call This Endpoint​

Call this endpoint when polled or webhook-notified that an allocation has transitioned to:

StatusMeaning
AUTH_REQUIRED3DS authentication is required before authorization can proceed
CONFIRMATION_REQUIREDAuthorization is complete but explicit confirmation is needed before capture

Do not call this endpoint for allocations in any other status. The service will reject the request if the allocation is not in a confirmable state.

Sibling Failure Check

If another allocation in the same transaction is already in FAILED, PAYMENT_METHOD_FAILED, CANCELED, CANCEL_INITIALIZED, or CANCEL_FAILED, the confirm call will be rejected with 422. The transaction is already heading toward cancellation β€” completing a 3DS challenge would only result in an immediate rollback of the confirmed leg.

πŸ”’ InternalInternal information β€” not visible in the public (merchant) site.

Confirm Allocation Processing Flow​

Confirm Allocation Sequence

Processing Steps​

  1. Receive request β€” PATCH with paymentId, allocationId, X-Merchant-Id, and X-Checkout-Id
  2. Merchant ownership β€” Verify X-Merchant-Id matches the transaction's merchant
  3. Sibling abort check β€” Reject if any sibling allocation is in FAILED, PAYMENT_METHOD_FAILED, CANCELED, CANCEL_INITIALIZED, or CANCEL_FAILED; the transaction is already heading toward cancellation
  4. Allocation membership β€” Verify allocationId belongs to this transaction
  5. Checkout ID match β€” Compare X-Checkout-Id against the checkoutId stored in the allocation's metadata
  6. Status check β€” Verify the allocation is in AUTH_REQUIRED or CONFIRMATION_REQUIRED
  7. Checkout session validation β€” Auth service confirms the session is active and non-agent
  8. Transition β€” Allocation moves to CONFIRMATION_INITIALIZED; event published (dataVersion: "0.1")
  9. Stripe processing β€” Stripe adapter processes the PaymentIntent; allocation eventually transitions to AUTHORIZED or COMPLETED

Processor-Specifics​

  • V1 delegation: The endpoint delegates to V1 ConfirmPaymentCommandHandler. Stripe-facing logic is unchanged β€” one PaymentIntent per allocation.
  • Event version: Published event carries dataVersion: "0.1" β€” the existing stripe adapter PaymentConsumer handles it; no new consumer is required.
  • Advisory lock: An advisory lock is acquired per allocation to prevent concurrent confirm calls.
  • Agent sessions: Checkout session validation rejects agent-initiated sessions β€” agents cannot complete 3DS challenges.

API Request​

Path Parameters​

ParameterTypeDescription
paymentIdUUIDThe V2 transaction ID (id from the create payment response)
allocationIdUUIDThe specific allocation ID (paymentAllocations[n].id) to confirm

Required Headers​

HeaderTypeDescription
AuthorizationstringBearer token
X-Merchant-IdUUIDMerchant identifier β€” must match the merchant that owns the transaction
X-Checkout-IdUUIDCheckout session ID β€” must match the checkout session under which the payment was created

Request Body​

None β€” this is a PATCH with no body.

Sample Request
curl -X PATCH "https://api-stg.uhg.com/api/financial/commerce/nonprodcheckout/v2/payments/{paymentId}/allocations/{allocationId}/confirm" \
-H "Authorization: Bearer <token>" \
-H "X-Merchant-Id: b955db5e-aef2-47de-bbb9-c80b9cc16e8f" \
-H "X-Checkout-Id: f3a1c2d4-e5f6-7890-ab12-cd34ef567890" \
-H "X-Upstream-Env: dev" \
-H "Accept: application/json"

Validation​

The endpoint performs the following checks in order. The first failure short-circuits and returns an error.

OrderCheckFailure
1Transaction exists404 Not Found
2X-Merchant-Id matches the transaction's merchant403 Forbidden
3Payment legs exist for the transaction404 Not Found
4All payment legs belong to X-Merchant-Id403 Forbidden
5No sibling allocation is in an abort state (FAILED, PAYMENT_METHOD_FAILED, CANCELED, CANCEL_INITIALIZED, CANCEL_FAILED)422 Unprocessable Entity
6The target allocation ID exists within this transaction422 Unprocessable Entity
7X-Checkout-Id matches the checkout ID stored in the allocation's metadata422 Unprocessable Entity
8The allocation status is AUTH_REQUIRED or CONFIRMATION_REQUIRED422 Unprocessable Entity
9Checkout session is active (not expired or in a terminal state)422 Unprocessable Entity

API Response​

Success β€” 202 Accepted​

Returns the full updated transaction. The confirmed allocation transitions to CONFIRMATION_INITIALIZED. The transaction-level status reflects the combined state of all allocations.

Response Structure

The complex object is trimmed for brevity. Refer to the API Spec for the full response structure.

Sample Response β€” Allocation CONFIRMATION_INITIALIZED
{
"url": "https://api-stg.uhg.com/v2/payments/3222ac8a-c8fa-4426-bd99-e96a909569b0",
"data": {
"id": "3222ac8a-c8fa-4426-bd99-e96a909569b0",
"merchantTransactionId": "c407ecc7-25f0-4fd9-844b-e9baca53707a",
"amount": 100,
"status": "AUTH_REQUIRED",
"paymentAllocations": [
{
"id": "8cd647c5-f9ff-42a0-b7d9-084c7f5d7d47",
"amount": 60,
"status": "CONFIRMATION_INITIALIZED",
"paymentMethod": {
"// ... see API Spec for full paymentMethod object ...": "..."
}
},
{
"id": "777373ac-dccf-499f-8c77-1d5e198508ad",
"amount": 40,
"status": "AUTH_REQUIRED",
"paymentMethod": {
"// ... see API Spec for full paymentMethod object ...": "..."
}
}
]
}
}
Sample Response β€” Validation Failure (422)
{
"title": "UNPROCESSABLE_ENTITY",
"detail": "Payment cannot be confirmed",
"status": 422
}

Status Handling​

After confirming an allocation, track the overall transaction status by polling GET /v2/payments/{paymentId} or listening to webhooks. The parent transaction status is derived from the combined statuses of all allocations.

Recommended Strategy

Use webhooks as the primary mechanism for status updates (PAYMENT_SUCCEEDED, PAYMENT_FAILED). Fall back to polling only if webhooks are unavailable.

Post-Confirm Status Progression​

Allocation Status After ConfirmMeaning
CONFIRMATION_INITIALIZEDConfirm accepted; processing with Stripe underway
AUTHORIZEDStripe confirms the PaymentIntent; awaiting capture
COMPLETEDAllocation fully captured and complete
FAILEDConfirmation processing failed at the processor

Status Mapping Table​

The parent transaction's status reflects the lowest-ranked allocation status across all legs (i.e., the allocation that is furthest behind drives the parent). If one allocation has been confirmed but another still requires 3DS, the parent remains in AUTH_REQUIRED.

Allocation 1Allocation 2Parent StatusDescription
⏳ CONFIRMATION_INITIALIZED⏳ AUTH_REQUIRED⏳ AUTH_REQUIREDOne confirmed, one still pending 3DS
⏳ CONFIRMATION_INITIALIZED⏳ CONFIRMATION_INITIALIZED⏳ CONFIRMATION_INITIALIZEDBoth confirmed, awaiting Stripe processing
βœ… COMPLETEDβœ… COMPLETEDβœ… COMPLETEDBoth complete β€” final state
❌ FAILED⏳ CONFIRMATION_INITIALIZED❌ FAILEDOne failed β€” parent immediately reflects failure
❌ PAYMENT_METHOD_FAILED⏳ AUTH_REQUIRED❌ PAYMENT_METHOD_FAILEDPayment method failure β€” cancel proceeds; no need to wait for 3DS
πŸ”„ ROLLED_BACK❌ FAILED❌ FAILEDRollback complete β€” final state
Capture Gating

When any allocation is in AUTH_REQUIRED, the orchestrator pauses the capture pipeline for the entire transaction. No allocation will be captured until all pending 3DS challenges are resolved. This prevents partial captures across a split-tender transaction.

πŸ”’ InternalInternal information β€” not visible in the public (merchant) site.

Internal Statuses​

important

Merchants see abstracted statuses (AUTH_REQUIRED, COMPLETED, FAILED). Internally, CCG uses finer-grained statuses. The confirm call transitions a single allocation from AUTH_REQUIRED/CONFIRMATION_REQUIRED β†’ CONFIRMATION_INITIALIZED.

AUTH_REQUIRED is a publishable split-payment status. When all allocations share AUTH_REQUIRED, CCG publishes a transaction event. Mixed statuses (e.g., one AUTH_REQUIRED, one CONFIRMATION_INITIALIZED) do not trigger an event publish β€” the transaction waits for all legs to align.

Internal Status Combinations After Confirm
Allocation Internal StatusMerchant-Visible StatusDescription
AUTH_REQUIREDAUTH_REQUIRED3DS challenge pending β€” no capture until resolved
CONFIRMATION_REQUIREDPENDING3DS complete; awaiting merchant confirm call
CONFIRMATION_INITIALIZEDPENDINGConfirm accepted; awaiting Stripe processing
AUTHORIZEDPENDINGStripe PaymentIntent authorized (SALE flow)
CAPTURE_INITIALIZEDPENDINGCapture in progress
COMPLETEDCOMPLETEDCaptured β€” terminal
FAILEDFAILEDProcessing failed β€” terminal
PAYMENT_METHOD_FAILEDFAILEDPayment method rejected β€” terminal; maps same as FAILED
CANCEL_INITIALIZEDPENDINGRollback initiated for sibling allocation
CANCELEDCANCELEDRolled back β€” terminal

Error Handling​

Error Code References

For the complete list of error codes and remediation steps, see Payment Error Codes.

Confirm-Specific Error Scenarios​

ScenarioHTTP StatusDescription
Missing X-Checkout-Id header400Required header not present in the request
Merchant mismatch403X-Merchant-Id does not own the transaction
Transaction not found404paymentId does not exist
Allocation not found422allocationId is not part of this transaction
Checkout ID mismatch422X-Checkout-Id does not match the checkout session in the allocation's metadata
Sibling allocation in abort state422A sibling is in FAILED, PAYMENT_METHOD_FAILED, CANCELED, CANCEL_INITIALIZED, or CANCEL_FAILED β€” completing 3DS would trigger an immediate rollback
Ineligible allocation status422Allocation is not in AUTH_REQUIRED or CONFIRMATION_REQUIRED
Checkout session invalid422Checkout session has expired, completed, or is agent-initiated
3DS in Agent Sessions

If a split-tender allocation requires 3DS authentication during an agent-assisted session, the entire payment fails. Agents cannot complete 3DS challenges. The confirm endpoint will reject requests from agent checkout sessions.


FAQ​

Q: Can I call this endpoint for both allocations at the same time?
A: Yes, but each allocation requires a separate PATCH call. The service applies an advisory lock per allocation to prevent duplicate concurrent confirms.

Q: What if the customer doesn't complete the 3DS challenge?
A: The allocation stays in AUTH_REQUIRED or CONFIRMATION_REQUIRED. No automatic timeout is applied β€” the allocation remains in that status until confirmed or the checkout session expires.

Q: What happens if the checkout session expires before I call confirm?
A: The endpoint will return a 422 at validation step 8 (checkout session active check). Initiate a new checkout session and payment.

Q: Will the other allocation be affected if one confirm fails?
A: If one allocation's confirm fails after the other has already progressed, CCG automatically rolls back the successful allocation (cancellation). The parent transaction moves to FAILED.

Q: Does the confirm endpoint publish a new event to the stripe adapter?
A: The event is published with dataVersion: "0.1". The existing stripe adapter PaymentConsumer handles it β€” no new consumer or routing is required.


Integration Checklist​

Before going live with the confirm allocation flow, verify:

  • Your integration polls or subscribes to webhooks to detect AUTH_REQUIRED / CONFIRMATION_REQUIRED status on individual allocations
  • You store the allocationId from the create payment response for each payment leg
  • You store the X-Checkout-Id used during the original payment creation β€” the same value must be passed to the confirm call
  • Your 3DS challenge flow returns control to your application before calling confirm
  • You handle 422 responses gracefully β€” log the detail field for diagnostic context
  • You do not call confirm from an agent-assisted session (agent flows will always result in a 422)
  • You test against staging using the Payment Error Codes test card scenarios for 3DS flows