Sessions API
The Session serves as the primary entry point for the CCG UI (Convenient Checkout Gateway User Interface). It determines the payment modes and channels requested by a merchant and specifies the options available to the merchant. The Session encompasses language preferences, features such as Pay and Save, Pay with wallet, and one-time payment modes, as well as the Payment Method Selector and wallet management options for the merchant.
Integration Details
- Prerequisite: Merchant account onboarded to the CCG Platform. See Getting Started.
- API Endpoint:
POST /v2/sessions— creates a checkout session - API Spec: Create Session
- Scope:
merchant - Session Modes:
PAYMENT,PAYMENT_METHOD_ENTRY,PAYMENT_WITH_WALLET,WALLET,PAYMENT_METHOD_SELECT,PAYMENT_METHOD_DISPLAY - Widget Integration: Pass the
checkoutSessionId(Embedded) orhostedUrl(Hosted) returned in the response to the widget - Error Handling: See Session Error Codes for session-specific errors
Sessions Processing Flow
The session is a central orchestration object. When created, it validates the merchant, customer, and payment details, then generates a transient session token used by the widget to fetch configuration and submit payment.
Session Creation Flow
Processing Steps:
- Request received — CCG validates the incoming session request (merchantId, JWT, required fields)
- Customer resolution — CCG determines wallet vs guest experience based on customer identifiers (
hsid,enterpriseId) - Session created — CCG persists the session with status
ACCEPTED→CREATED - Token generation — A short-lived
checkoutSessionIdis returned; the merchant passes this to the widget - Widget loads — Widget fetches session state and renders the correct mode/experience
- Action completion — Widget submits the payment or wallet action; session transitions to
COMPLETEDorFAILED
API Request
For complete field definitions, constraints, and validations, refer to the OpenAPI Spec.
The request body has three top-level objects: customer, payment, and config. The config.modes array determines which widget capability is activated.
Session Modes
| Mode | Description |
|---|---|
PAYMENT | One-time payment via card, bank, or digital wallet |
PAYMENT_METHOD_ENTRY | Add a new card or bank account to wallet |
PAYMENT_WITH_WALLET | Pay using a saved method from the wallet |
WALLET | Manage (add/edit/remove) wallet payment methods |
PAYMENT_METHOD_SELECT | Display and select from saved payment methods |
PAYMENT_METHOD_DISPLAY | Display a specific payment method for review |
See Widget Capabilities for full mode support matrix.
Payment Method Channels
| Channel | Values | Description |
|---|---|---|
card | WEBFORM, TEXT, EMAIL, GOOGLE_PAY, APPLE_PAY | Card entry/payment channels |
bankAccount | WEBFORM | Bank account entry channel |
Sample Request — PAYMENT (One-Time Payment)
curl -X POST "https://api-stg.uhg.com/api/financial/commerce/nonprodcheckout/v1/sessions" \
-H "Authorization: Bearer <token>" \
-H "X-Merchant-Id: <merchant-id>" \
-H "X-Upstream-Env: dev" \
-H "Content-Type: application/json" \
-d '{
"customer": {
"firstName": "Jane",
"lastName": "Doe",
"email": "jane.doe@example.com",
"hsid": "<customer-hsid>",
"phoneNumber": { "number": "9876543210", "countryCode": "1" },
"zip5": "54321"
},
"payment": {
"merchantTransactionId": "<unique-id>",
"amount": 1500,
"authorizeCard": false
},
"config": {
"modes": ["PAYMENT"],
"paymentMethodChannel": {
"card": ["WEBFORM", "GOOGLE_PAY", "APPLE_PAY"],
"bankAccount": ["WEBFORM"]
}
}
}'
Sample Request — PAYMENT_METHOD_ENTRY (Add Payment Method)
curl -X POST "https://api-stg.uhg.com/api/financial/commerce/nonprodcheckout/v1/sessions" \
-H "Authorization: Bearer <token>" \
-H "X-Merchant-Id: <merchant-id>" \
-H "X-Upstream-Env: dev" \
-H "Content-Type: application/json" \
-d '{
"customer": {
"firstName": "Jane",
"lastName": "Doe",
"email": "jane.doe@example.com",
"hsid": "<customer-hsid>"
},
"config": {
"modes": ["PAYMENT_METHOD_ENTRY"],
"paymentMethodChannel": {
"card": ["WEBFORM", "TEXT", "EMAIL"],
"bankAccount": ["WEBFORM"]
},
"privacyPolicyUrl": "https://merchant.com/privacy"
}
}'
Sample Request — PAYMENT_WITH_WALLET (Pay with Saved Method)
curl -X POST "https://api-stg.uhg.com/api/financial/commerce/nonprodcheckout/v1/sessions" \
-H "Authorization: Bearer <token>" \
-H "X-Merchant-Id: <merchant-id>" \
-H "X-Upstream-Env: dev" \
-H "Content-Type: application/json" \
-d '{
"customer": {
"hsid": "<customer-hsid>"
},
"payment": {
"merchantTransactionId": "<unique-id>",
"amount": 1500,
"authorizeCard": false
},
"config": {
"modes": ["PAYMENT_WITH_WALLET"],
"paymentMethodChannel": {
"card": ["WEBFORM", "GOOGLE_PAY", "APPLE_PAY"],
"bankAccount": ["WEBFORM"]
}
}
}'
Sample Request — Express Checkout (PAYMENT with digital wallets)
curl -X POST "https://api-stg.uhg.com/api/financial/commerce/nonprodcheckout/v1/sessions" \
-H "Authorization: Bearer <token>" \
-H "X-Merchant-Id: <merchant-id>" \
-H "X-Upstream-Env: dev" \
-H "Content-Type: application/json" \
-d '{
"customer": {
"name": "John Smith",
"email": "john.smith@example.com",
"ssnLastFour": "1001",
"dateOfBirth": "2000-09-21",
"zip5": "10003",
"phoneNumber": { "number": "9175553352", "countryCode": "1" }
},
"payment": {
"merchantTransactionId": "ORDER-12345",
"statementDescriptorSuffix": "Test Order",
"amount": 15000,
"authorizeCard": false
},
"config": {
"modes": ["PAYMENT"],
"paymentMethodChannel": {
"card": ["WEBFORM", "GOOGLE_PAY", "APPLE_PAY"],
"bankAccount": ["WEBFORM"]
}
}
}'
API Response
Sample responses show key fields only. For the complete schema, refer to the OpenAPI Spec.
The response data object contains:
| Field | Type | Description |
|---|---|---|
checkoutSessionId | string | UUID; pass to the embedded widget as checkoutSessionId |
hostedUrl | string | Full URL; open as a popup for the hosted experience |
url | string | Session status polling endpoint |
Sample Response — Session Created (200)
{
"data": {
"checkoutSessionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"hostedUrl": "https://walletprod.healthsafepay.com/wallet/v2/checkout?session=a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"url": "https://api-stg.uhg.com/api/financial/commerce/nonprodcheckout/v1/sessions/a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
}
Status Handling
After session creation, the widget drives the session through its lifecycle. Poll the session url (returned in the response) to detect the final state, or use the widget's onSuccess / onError callbacks.
Session Lifecycle
| Status | Description |
|---|---|
ACCEPTED | Session created, initialization in progress |
CREATED | Session ready; widget can be loaded |
COMPLETED | Transaction succeeded (payment processed, method added, etc.) |
FAILED | Transaction failed or an unrecoverable error occurred |
EXPIRED | Session timed out before the user completed the flow |
CANCELED | Session was explicitly canceled |
Polling
- Poll the
urlfield from the session response - Recommended interval: every 2–3 seconds
- Stop polling when status is
COMPLETED,FAILED,EXPIRED, orCANCELED - Prefer widget callbacks (
onSuccess,onError) over polling when using the Embedded Experience
Internal Session Statuses
Internally, sessions transition through additional states not exposed to merchants. The merchant-facing statuses above are derived from these internal states.
| Internal Status | Merchant-Visible Status | Description |
|---|---|---|
PENDING_INITIALIZATION | ACCEPTED | Session record created, not yet validated |
INITIALIZED | CREATED | Session validated and ready for widget |
PAYMENT_PENDING | CREATED | Widget loaded, payment in progress |
PAYMENT_COMPLETED | COMPLETED | Payment processor confirmed success |
PAYMENT_FAILED | FAILED | Processor returned failure |
TIMED_OUT | EXPIRED | Session exceeded TTL without completion |
Error Handling
For session-specific error codes and remediation steps, see Session Error Codes.
Common session errors:
| Error Title | HTTP Status | Cause | Action |
|---|---|---|---|
INVALID_REQUEST | 400 | Missing required field or invalid value | Check request body against the API Spec |
UNAUTHORIZED | 401 | Invalid or expired JWT token | Refresh your token and retry |
MERCHANT_NOT_FOUND | 404 | X-Merchant-Id does not match an active merchant | Verify merchant onboarding is complete |
SESSION_TIMEOUT | 410 | Session expired before user completed the flow | Create a new session and retry |
SESSION_ALREADY_PROCESSED | 409 | Session has already reached a terminal state | Create a new session for the next transaction |
FAQ
Q: Where should I create the session — frontend or backend?
A: Always create sessions from your backend. The JWT token used to authorize the request must never be exposed to the browser.
Q: What is the checkoutSessionId vs hostedUrl?
A: Use checkoutSessionId for the Embedded Experience (pass to OptumCCGWidgetInitializer). Use hostedUrl for the Hosted Experience (open as a popup window).
Q: How long is a session valid?
A: Sessions expire after a period of inactivity (typically 15 minutes). If a session expires, create a new one.
Q: Can I create a session without a customer object?
A: No — the customer object is required. For guest users, include at least basic identifying fields. For wallet users, include hsid or enterpriseId to trigger the wallet experience.
Q: What determines wallet vs guest experience?
A: If customer.hsid, customer.enterpriseId, or another valid merchant-specific identifier is present and matches an existing wallet, the wallet experience is shown. Otherwise, the guest experience is shown. See Widget Experience for details.
Q: Can I pass a pre-selected payment method?
A: Yes — include paymentMethod.id in the request body to pre-select a specific saved payment method (used with PAYMENT_METHOD_SELECT and PAYMENT_METHOD_DISPLAY modes).
Q: How do I support digital wallets (Apple Pay / Google Pay)?
A: Include GOOGLE_PAY and/or APPLE_PAY in config.paymentMethodChannel.card. Domain registration and feature activation are required during onboarding. See Express Checkout for details.
Integration Checklist
- Merchant account onboarded to the CCG Platform
- Session creation always performed server-side (JWT never exposed to browser)
-
customerobject includes the appropriate identifier (hsid,enterpriseId) for wallet users -
payment.merchantTransactionIdis unique per transaction -
config.modesset to the correct capability for your use case -
config.paymentMethodChannelincludes only the channels you have enabled - For Apple Pay / Google Pay: domain registered and feature activation confirmed
- Session
urlpolling or widget callbacks implemented to detect completion - Error handling implemented for
INVALID_REQUEST,UNAUTHORIZED, and session timeout scenarios - Tested with sandbox/staging environment before going live
Related Documentation
- Widget Capabilities — Mode support matrix and configuration details
- Hosted Experience — Using
hostedUrlwith a popup - Embedded Experience — Using
checkoutSessionIdwith the embedded widget - Express Checkout — Apple Pay / Google Pay configuration
- Widget Experience — Session lifecycle, guest vs wallet experience
- Session Error Codes — Full error reference
- OpenAPI Spec — Complete field definitions and constraints