Single Payments API
A single allocation payment charges one card for the full transaction amount. This is the standard payment flow — the paymentAllocations array contains exactly one entry. There is no rollback logic since only one card is involved.
- Processing: One card charged for the full amount
- No rollback: Only one allocation — nothing to roll back
- Idempotent: Same
merchantTransactionIdcan be retried up to 5 times
For business rules and lifecycle details, see the Payments — Business Guide.
- API Endpoint:
- Use
POST v2/paymentsfor API - Use
POST v2/sessionsfor widget flows. See Widget Integration Guide
- Use
- Scope: All operations are at the
merchantscope. - Specs: Payment API Reference | Payment Events & Webhooks
- API:
v2| Widget:v3 - Testing: Use Test Cards to simulate the flow. See Test Cards
- ⚠️ Error Handling: See Payment Error Codes for error codes and resolution steps
How It Differs from Multi-Allocation (Split Tender)
| Aspect | Single Allocation | Multi-Allocation (Split Tender) |
|---|---|---|
| Cards | 1 | 2 |
paymentAllocations | 1 entry | Exactly 2 entries |
| Rollback | N/A — nothing to roll back | Automatic — successful card cancelled if other 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 allocations retried together |
| Webhook | PAYMENT_SUCCEEDED or PAYMENT_FAILED | Same events, but payload includes per-allocation status |
For multi-allocation (split tender) integration, see Multi-Allocation Payments.
API Request
For complete field definitions, constraints, and validations, refer to the Create Payment API Spec.
Stored Payment Method (v2/payments)
Submit a single allocation payment using a saved card. The paymentAllocations array contains exactly 1 entry with the paymentMethodId and the full amount.
Sample Request — Single Allocation
curl -X POST "https://api-stg.uhg.com/api/financial/commerce/nonprodcheckout/v2/payments" \
-H "Authorization: <token>" \
-H "X-Merchant-Id: b955db5e-aef2-47de-bbb9-c80b9cc16e8f" \
-H "X-Upstream-Env: dev" \
-H "Accept: */*" \
-H "Content-Type: application/json" \
-d '{
"merchantTransactionId": "c407ecc7-25f0-4fd9-844b-e9baca53707a",
"amount": 100,
"authorizeCard": false,
"customer": {
"hsid": "b313c1d1-b5b6-4ec7-8b5a-3a9cf7755060",
"metadata": {}
},
"metadata": null,
"paymentAllocations": [
{
"paymentMethodId": "7b30960f-8a19-4ae0-8d73-46849365f81d",
"amount": 100
}
]
}'
Session-Based (v2/sessions)
For widget-based (v3) flows, the customer selects a card through the PAYMENT_WITH_WALLET UI. Refer to the Widget Integration Guide for session setup.
API Response
The complex object is trimmed for brevity. Refer to the API Spec for the full response structure.
Key Points
- The
paymentAllocationsarray contains one entry — the single card. - The parent status directly mirrors the allocation status (
COMPLETEDorFAILED). - No
remediationobject is ever present (no rollback needed). - The
paymentMethodobject is trimmed for brevity (onlyid,type,last4,cardBrandshown).
Successful Response
Sample Response — COMPLETED
{
"url": "http://api-stg.uhg.com:443/v2/payments/3222ac8a-c8fa-4426-bd99-e96a909569b0",
"data": {
"id": "3222ac8a-c8fa-4426-bd99-e96a909569b0",
"merchantTransactionId": "30d279fa-9d7d-48c9-8e61-c3783eecf18c",
"amount": 100,
"description": "Single Allocation Payment",
"currencyCode": "USD",
"status": "COMPLETED",
"vendor": {
// ... see API Spec for full vendor object ...
},
"paymentDateUtc": "2026-03-21T00:24:01.741688Z",
"metadata": {
"orderId": "123",
"orderType": "prescription"
},
"merchant": {
// ... see API Spec for full merchant object ...
},
"paymentAllocations": [
{
"id": "8cd647c5-f9ff-42a0-b7d9-084c7f5d7d47",
"amount": 100,
"status": "COMPLETED",
"paymentMethod": {
"id": "7b30960f-8a19-4ae0-8d73-46849365f81d",
"type": "CARD",
"last4": "4242",
"cardBrand": "VISA"
}
}
],
"customer": {
"id": "fa6dcef4-6400-467b-aa28-0f02a7afd724"
}
}
}
Failure Response
Sample Response — FAILED
{
"title": "PAYMENT_ERROR",
"detail": "Your card was declined.",
"status": 422,
"data": {
"id": "9cbecc7b-6401-4f1b-bc1d-c2769d466e7f",
"merchantTransactionId": "95b8da69-cf36-49cb-8dbe-1f0948cd38ed",
"amount": 100,
"currencyCode": "USD",
"status": "FAILED",
"vendor": { "name": "STRIPE" },
"paymentDateUtc": "2026-03-21T00:25:45.206679Z",
"merchant": {
"id": "b955db5e-aef2-47de-bbb9-c80b9cc16e8f",
"groupId": "3cf34cba-ffec-48fb-b7ca-09977db1077a",
"name": "ccg-optum-rx"
},
"paymentAllocations": [
{
"id": "99407904-f239-4a50-9968-c75fa4d99623",
"amount": 100,
"status": "FAILED",
"paymentMethod": {
"id": "7b30960f-8a19-4ae0-8d73-46849365f81d",
"type": "CARD",
"last4": "4242",
"cardBrand": "VISA"
},
"error": {
"title": "PAYMENT_ERROR",
"detail": "Your card was declined.",
"errorDetails": {
"code": "card_declined",
"message": "Your card was declined.",
"declineCode": "generic_decline",
"networkAdviceCode": null,
"networkDeclineCode": "01"
}
}
}
],
"customer": {
"id": "5e395f2d-d000-4e79-9f33-ca68280bd2b6"
}
}
}
Status Handling
Polling Guidelines
- ✅ Supported:
- Poll the parent transaction using
paymentIdormerchantTransactionId. - Get the allocation status in a single response.
- Poll the parent transaction using
- ❌ Not Supported:
- Polling individual allocation (child) payment IDs.
Always use the parent transaction identifier for polling. Using child payment IDs will result in API errors.
Status Mapping
| Allocation Status | Parent Status | Description |
|---|---|---|
| ⏳ PENDING | ⏳ PENDING | Card is processing |
| ✅ COMPLETED | ✅ COMPLETED | Payment captured successfully |
| ❌ FAILED | ❌ FAILED | Card declined or error |
Note: There is no
ROLLED_BACKorPARTIAL_SUCCESSstatus for single allocation payments. The parent status directly mirrors the single allocation.
Error Handling
For the complete list of error codes, status codes, and error details, see Payment Error Codes.
- Card declined: The
errorobject in the allocation contains the processor decline reason and error code. - Business rule violations: The response may not include a
paymentAllocationsarray — the error is at the top level. - No rollback errors: Since only one card is involved, there are no
remediationobjects or rollback-related errors.
Retry Handling
Single allocation payments follow the same retry logic as multi-allocation:
- Up to 5 attempts per
merchantTransactionId(1 initial + 4 retries). - Only retry if the parent payment status is
FAILED. - All retries must use the same
merchantTransactionId. - On retry, you may change the card or keep the same one.
- After the 5th failure, no further retries are allowed for that
merchantTransactionId.
Webhooks
CCG emits one webhook per transaction. Subscribe to these events for real-time status updates.
To configure webhooks, see the Configuration Guide.
| Event | When Triggered |
|---|---|
PAYMENT_SUCCEEDED | Card completed |
PAYMENT_FAILED | Card failed |
PAYMENT_FAILED is not final if retries remain. It becomes final only after the 5th failure or when the merchant stops retrying.
FAQ
Q: How is this different from a multi-allocation (split tender) payment?
- Single allocation uses one card. There is no rollback, no
ROLLED_BACKstatus, and noremediationobject. See the comparison table above.
Q: Can I use the same merchantTransactionId to retry with a different card?
- Yes. On retry, you may change the
paymentMethodIdand amount.
Q: Is there a PARTIAL_SUCCESS or ROLLED_BACK status?
- No. Those statuses only apply when multiple allocations are involved.
Q: Can I poll individual allocation IDs?
- No. Always use the parent
paymentIdormerchantTransactionId.
Integration Checklist
- API endpoints and authentication are set up
- Payment request includes exactly one
paymentAllocationwith the correct amount - Error handling logic is implemented for card declines and business rule violations
- Webhook endpoint is configured and returns
2xx - Webhook handler is idempotent and logs all payloads
- Retry logic follows documented rules (max 5 attempts)
- All error codes are handled
- Integration tested with test cards and simulated failures