Skip to main content
Version: v2

Sessions API

DRAFT VERSION

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

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) or hostedUrl (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:

  1. Request received — CCG validates the incoming session request (merchantId, JWT, required fields)
  2. Customer resolution — CCG determines wallet vs guest experience based on customer identifiers (hsid, enterpriseId)
  3. Session created — CCG persists the session with status ACCEPTEDCREATED
  4. Token generation — A short-lived checkoutSessionId is returned; the merchant passes this to the widget
  5. Widget loads — Widget fetches session state and renders the correct mode/experience
  6. Action completion — Widget submits the payment or wallet action; session transitions to COMPLETED or FAILED

API Request

API Specification

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

ModeDescription
PAYMENTOne-time payment via card, bank, or digital wallet
PAYMENT_METHOD_ENTRYAdd a new card or bank account to wallet
PAYMENT_WITH_WALLETPay using a saved method from the wallet
WALLETManage (add/edit/remove) wallet payment methods
PAYMENT_METHOD_SELECTDisplay and select from saved payment methods
PAYMENT_METHOD_DISPLAYDisplay a specific payment method for review

See Widget Capabilities for full mode support matrix.

Payment Method Channels

ChannelValuesDescription
cardWEBFORM, TEXT, EMAIL, GOOGLE_PAY, APPLE_PAYCard entry/payment channels
bankAccountWEBFORMBank 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

Response Structure

Sample responses show key fields only. For the complete schema, refer to the OpenAPI Spec.

The response data object contains:

FieldTypeDescription
checkoutSessionIdstringUUID; pass to the embedded widget as checkoutSessionId
hostedUrlstringFull URL; open as a popup for the hosted experience
urlstringSession 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

StatusDescription
ACCEPTEDSession created, initialization in progress
CREATEDSession ready; widget can be loaded
COMPLETEDTransaction succeeded (payment processed, method added, etc.)
FAILEDTransaction failed or an unrecoverable error occurred
EXPIREDSession timed out before the user completed the flow
CANCELEDSession was explicitly canceled

Polling

  • Poll the url field from the session response
  • Recommended interval: every 2–3 seconds
  • Stop polling when status is COMPLETED, FAILED, EXPIRED, or CANCELED
  • Prefer widget callbacks (onSuccess, onError) over polling when using the Embedded Experience

Internal Session Statuses

important

Internally, sessions transition through additional states not exposed to merchants. The merchant-facing statuses above are derived from these internal states.

Internal StatusMerchant-Visible StatusDescription
PENDING_INITIALIZATIONACCEPTEDSession record created, not yet validated
INITIALIZEDCREATEDSession validated and ready for widget
PAYMENT_PENDINGCREATEDWidget loaded, payment in progress
PAYMENT_COMPLETEDCOMPLETEDPayment processor confirmed success
PAYMENT_FAILEDFAILEDProcessor returned failure
TIMED_OUTEXPIREDSession exceeded TTL without completion

Error Handling

For session-specific error codes and remediation steps, see Session Error Codes.

Common session errors:

Error TitleHTTP StatusCauseAction
INVALID_REQUEST400Missing required field or invalid valueCheck request body against the API Spec
UNAUTHORIZED401Invalid or expired JWT tokenRefresh your token and retry
MERCHANT_NOT_FOUND404X-Merchant-Id does not match an active merchantVerify merchant onboarding is complete
SESSION_TIMEOUT410Session expired before user completed the flowCreate a new session and retry
SESSION_ALREADY_PROCESSED409Session has already reached a terminal stateCreate 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)
  • customer object includes the appropriate identifier (hsid, enterpriseId) for wallet users
  • payment.merchantTransactionId is unique per transaction
  • config.modes set to the correct capability for your use case
  • config.paymentMethodChannel includes only the channels you have enabled
  • For Apple Pay / Google Pay: domain registered and feature activation confirmed
  • Session url polling 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