Split-Tender Payment Flow
Overview
A split-tender payment distributes a single transaction across exactly 2 payment allocations (currently CARD + CARD only). The system treats the two allocations as an atomic unit — if one fails, the successful allocation is automatically rolled back.
Key characteristics:
- Exactly 2 entries in
paymentAllocations - Only
CARD+CARDcombinations supported - Only
SALEtransactions (not pre-auth) - Automatic rollback (cancel/reverse) if any allocation fails
ROLLED_BACKstatus andremediationobject on reversed allocations
Sequence Diagram
API Request
Sample Request — Split-Tender (2 Cards)
curl -X POST "https://api-stg.uhg.com/api/financial/commerce/nonprodcheckout/v2/payments" \
-H "Authorization: Bearer <token>" \
-H "X-Merchant-Id: b955db5e-aef2-47de-bbb9-c80b9cc16e8f" \
-H "X-Upstream-Env: dev" \
-H "Content-Type: application/json" \
-d '{
"merchantTransactionId": "split-20260404-001",
"amount": 20000,
"currencyCode": "USD",
"authorizeCard": false,
"partialAuthorization": false,
"customer": {
"hsid": "b313c1d1-b5b6-4ec7-8b5a-3a9cf7755060"
},
"paymentAllocations": [
{
"amount": 12000,
"paymentMethodId": "b0b3c48d-4cf6-404a-a554-e14640a51c5b"
},
{
"amount": 8000,
"paymentMethodId": "c1d4e5f6-7890-1234-5678-90abcdef1234"
}
],
"metadata": {
"orderId": "split-order-789"
}
}'
Validation Rules (Split-Tender Specific)
| Rule | HTTP Status | Error |
|---|---|---|
paymentAllocations must have exactly 2 items | 400 | INVALID_REQUEST |
alloc[0].amount + alloc[1].amount must equal top-level amount | 400 | INVALID_REQUEST |
Both allocations must use CARD payment methods | 400 | INVALID_REQUEST |
authorizeCard must be false (pre-auth not supported for split-tender) | 400 | INVALID_REQUEST |
Each allocation amount must be ≥ 1 | 400 | INVALID_REQUEST |
API Response — Both Succeed (GET 200)
{
"url": "https://api-stg.uhg.com/.../v2/payments/660e8400-e29b-41d4-a716-446655440000",
"data": {
"id": "660e8400-e29b-41d4-a716-446655440000",
"merchantTransactionId": "split-20260404-001",
"amount": 20000,
"authorizedAmount": 20000,
"capturedAmount": 20000,
"currencyCode": "USD",
"status": "COMPLETED",
"paymentAllocations": [
{
"id": "aaaa1111-2222-3333-4444-555566667777",
"amount": 12000,
"authorizedAmount": 12000,
"capturedAmount": 12000,
"status": "COMPLETED",
"paymentMethod": {
"id": "b0b3c48d-4cf6-404a-a554-e14640a51c5b",
"type": "CARD",
"card": { "lastFour": "4242", "brand": "visa", "expMonth": 12, "expYear": 2028 }
},
"vendor": { "name": "STRIPE", "transactionId": "pi_alloc1_abc" }
},
{
"id": "bbbb1111-2222-3333-4444-555566667777",
"amount": 8000,
"authorizedAmount": 8000,
"capturedAmount": 8000,
"status": "COMPLETED",
"paymentMethod": {
"id": "c1d4e5f6-7890-1234-5678-90abcdef1234",
"type": "CARD",
"card": { "lastFour": "1234", "brand": "mastercard", "expMonth": 6, "expYear": 2027 }
},
"vendor": { "name": "STRIPE", "transactionId": "pi_alloc2_def" }
}
]
}
}
API Response — One Fails + Rollback (422)
When allocation[1] fails, allocation[0] is automatically rolled back:
{
"title": "PAYMENT_ERROR",
"status": 422,
"detail": "Payment processing failed for all records. Check individual records for error details",
"data": {
"id": "660e8400-e29b-41d4-a716-446655440000",
"merchantTransactionId": "split-20260404-001",
"amount": 20000,
"status": "FAILED",
"paymentAllocations": [
{
"id": "aaaa1111-2222-3333-4444-555566667777",
"amount": 12000,
"status": "ROLLED_BACK",
"remediation": {
"action": "CANCEL",
"reason": "CCG_AUTOMATED_CANCEL",
"vendorTransactionId": "pi_cancel_abc"
},
"paymentMethod": {
"type": "CARD",
"card": { "lastFour": "4242", "brand": "visa" }
}
},
{
"id": "bbbb1111-2222-3333-4444-555566667777",
"amount": 8000,
"status": "FAILED",
"error": {
"code": "card_declined",
"message": "Your card was declined."
},
"paymentMethod": {
"type": "CARD",
"card": { "lastFour": "1234", "brand": "mastercard" }
}
}
]
}
}
Rollback Logic
Operational Risk
If rollback (cancel of allocation[0]) fails, the allocation enters CANCEL_FAILED state. This requires manual intervention — see Incident Playbooks (coming soon).
Webhook — Split-Tender PAYMENT_FAILED (with rollback)
{
"name": "PAYMENT_FAILED",
"source": "merchant-portal",
"payload": {
"id": "660e8400-e29b-41d4-a716-446655440000",
"merchantTransactionId": "split-20260404-001",
"amount": 20000,
"status": "FAILED",
"paymentAllocations": [
{
"id": "aaaa1111-2222-3333-4444-555566667777",
"amount": 12000,
"status": "ROLLED_BACK"
},
{
"id": "bbbb1111-2222-3333-4444-555566667777",
"amount": 8000,
"status": "FAILED"
}
]
}
}
Comparison: Single vs Split-Tender
| Aspect | Single Allocation | Split-Tender |
|---|---|---|
| Cards | 1 | 2 |
paymentAllocations | 1 entry | Exactly 2 entries |
| Rollback | N/A | Automatic (cancel successful if sibling fails) |
ROLLED_BACK status | Never | Yes, on the cancelled allocation |
remediation object | Never present | Present on rolled-back allocation |
| Retry scope | Retry the single card | All-or-nothing — both retried together |
| Pre-auth support | Yes | No (authorizeCard must be false) |