Checking access…

Skip to main content
Version: v2

Vendor Configuration — Session Contract

🔒 InternalInternal information — not visible in the public (merchant) site.

Overview

V2 checkout sessions support scoping to a specific payment processor, payment method type, and set of channels via config.vendors[]. At creation time the platform resolves the merchant’s processor configuration and embeds a client-safe snapshot — vendorConfigs — directly in the session. This snapshot drives SDK initialization on the frontend and is the authoritative record of which processor handles the transaction.

Key characteristics:

  • vendorConfigs is resolved once at session creation and never changes
  • Vendor-incompatible channels (TEXT, EMAIL) are stripped from vendorConfigs for non-agent sessions; WEBFORM is always added for non-agent sessions
  • Legacy sessions (V1 or pre-migration V2) have vendorConfigs: null — they use paymentMethodChannel instead
  • config.vendors[] is stored internally for child session inheritance but is not returned in the API response

Session Scoping (config.vendors[])

The vendors filter is optional. When present, only the specified processors, payment method types, and channels are active for the session. All scoping decisions are final at creation time.

InputResult
vendors omittedFull merchant configuration used — all enabled processors and channels
vendors: [] (empty array)Same as omitted
Vendor not in merchant configSilently excluded from vendorConfigs; session still created
Channel not supported by vendorSilently excluded; no error
TEXT or EMAIL in channel listNon-agent: stripped; WEBFORM added as fallback. Agent: TEXT/EMAIL may appear in vendorConfigs for both CARD and BANK_ACCOUNT
Filter leaves no valid channelsSession created; vendorConfigs: [] (empty, not null)
vendor field missing on an entry400 Bad Request — rejected at validation
Unrecognized vendor value400 Bad Request — rejected at deserialization

WEBFORM Default

WEBFORM is always included in vendorConfigs for a payment method type when the processor supports it — even if not explicitly listed in config.vendors[].channels. This applies to non-agent sessions only.

Vendor-compatible channels per payment method type:

TypeVendor SDK channels
CARDWEBFORM, GOOGLE_PAY, APPLE_PAY
BANK_ACCOUNTWEBFORM

Agent sessions do not get WEBFORM force-added. Agent-restricted channels (GOOGLE_PAY, APPLE_PAY) are always removed. Agents receive exactly the channels they are authorized for.


Sample Request

Restrict to STRIPE CARD — APPLE_PAY only
curl -X POST "https://api-stg.uhg.com/api/financial/commerce/nonprodcheckout/v2/sessions" \
-H "Authorization: Bearer <token>" \
-H "X-Merchant-Id: <merchant-id>" \
-H "Content-Type: application/json" \
-d '{
"customer": { "hsid": "<customer-hsid>" },
"payment": {
"merchantTransactionId": "<unique-id>",
"amount": 1500,
"authorizeCard": false
},
"config": {
"modes": ["PAYMENT"],
"vendors": [
{
"vendor": "STRIPE",
"paymentMethods": [
{ "type": "CARD", "channels": ["APPLE_PAY"] }
]
}
]
}
}'
Restrict to STRIPE BANK_ACCOUNT
curl -X POST "https://api-stg.uhg.com/api/financial/commerce/nonprodcheckout/v2/sessions" \
-H "Authorization: Bearer <token>" \
-H "X-Merchant-Id: <merchant-id>" \
-H "Content-Type: application/json" \
-d '{
"customer": { "hsid": "<customer-hsid>" },
"payment": {
"merchantTransactionId": "<unique-id>",
"amount": 1500,
"authorizeCard": false
},
"config": {
"modes": ["PAYMENT"],
"vendors": [
{
"vendor": "STRIPE",
"paymentMethods": [
{ "type": "BANK_ACCOUNT", "channels": ["WEBFORM", "TEXT"] }
]
}
]
}
}'

Sample Response

vendorConfigs is embedded in checkoutRequest.config. WEBFORM is always present for non-agent sessions when supported by the processor.

{
"data": {
"checkoutSession": {
"id": "d561f8bf-d569-4db4-b3b2-1470a04df874",
"checkoutRequest": {
"config": {
"modes": ["PAYMENT"],
"paymentMethodChannel": {
"cardChannels": [
{ "type": "APPLE_PAY", "order": 0, "enabled": true },
{ "type": "WEBFORM", "order": 1, "enabled": true }
],
"card": ["APPLE_PAY", "WEBFORM"]
},
"vendorConfigs": [
{
"vendor": "STRIPE",
"vendorMerchantId": "acct_xxxxxxxxxxxx",
"clientConfig": { "publicKey": "pk_live_xxxxxxxxxxxx" },
"paymentMethods": [
{
"type": "CARD",
"channels": [
{ "type": "APPLE_PAY", "order": 0, "enabled": true },
{ "type": "WEBFORM", "order": 1, "enabled": true }
]
}
]
}
]
}
},
"checkoutSessionStatus": "INITIATED"
}
}
}
note

vendorConfigs contains only client-safe fields. Secret keys, requestedVendorConfigs, and internal storage fields are never returned.


Legacy Sessions (vendorConfigs: null)

Sessions created before V2 vendor config support, or on pre-migration merchant accounts, have vendorConfigs absent from the response. The paymentMethodChannel field applies instead.

vendorConfigs valueMeaning
Absent (null)V1 or pre-migration session — use paymentMethodChannel
[] (empty array)V2 session — vendor filter applied, no processor matched
[...] (non-empty)V2 session — processor resolved successfully

A V2 session with vendorConfigs: [] does not fall back to paymentMethodChannel. The empty result is authoritative — no payment can proceed.


Client-Safe Fields in vendorConfigs

All fields in vendorConfigs are safe to pass to the frontend. Nothing server-only is included.

FieldDescription
vendorProcessor identifier (STRIPE, OPTUM_BANK)
vendorMerchantIdMerchant’s account ID with the processor
clientConfig.publicKeyProcessor’s publishable API key for SDK initialization
paymentMethods[].typePayment method type (CARD, BANK_ACCOUNT)
paymentMethods[].channels[].typeChannel (WEBFORM, APPLE_PAY, GOOGLE_PAY)
paymentMethods[].channels[].enabledWhether the channel is active
paymentMethods[].channels[].orderDisplay order

Deterministic Processor Routing

  • The processor is selected once at session creation and does not change
  • CARD routes to STRIPE; BANK_ACCOUNT routes to STRIPE (ACH) or OPTUM_BANK (FSA/HSA); HEALTH_SAVINGS_ACCOUNT routes to OPTUM_BANK exclusively
  • If the processor is unavailable at payment time, the transaction fails — there is no automatic fallback or re-routing
  • Create a new session to retry with a different scope

Child Session Inheritance

Child sessions (TEXT_TO_PAY, EMAIL_TO_PAY, TEXT_TO_ADD, EMAIL_TO_ADD) start from the parent’s vendorConfigs and apply additional filtering.

Child modeChannels permitted in vendorConfigs
TEXT_TO_PAY / EMAIL_TO_PAYWEBFORM, GOOGLE_PAY, APPLE_PAY
TEXT_TO_ADD / EMAIL_TO_ADDWEBFORM only

Payment method types are further restricted to those for which the merchant has the delivery channel (TEXT or EMAIL) configured.

Agent sessions: When a parent agent session’s vendorConfigs contains only WEBFORM (because APPLE_PAY was agent-restricted), child sessions can still surface APPLE_PAY for the customer. The original config.vendors[] is stored internally on the parent session and is used to recover the originally-requested wallet channels during child session creation.


Error Reference

These errors are returned by GET /v2/checkout-sessions/{id} when the session has no usable payment methods. All return 422 Unprocessable Entity.

ScenarioError message
None of the requested vendors are configured for this merchant"The requested vendor is not configured or supported for this merchant"
Vendor matched but payment method type not supported"Payment method type is not configured."
Vendor + type matched but no channels survived the filter"No supported channels remain after applying the requested vendor filter"
General — no capture methods available"You have no capture methods available."
Sample — 422 No capture methods
{
"title": "UNPROCESSABLE_ENTITY",
"status": 422,
"detail": "You have no capture methods available."
}

  • wallet-auth-serviceCreateSessionCommandHandler, VendorConfigResolver, CreateChildCheckoutSessionCommandHandler, GetCheckoutSessionCommandHandler
  • CheckoutSessionConfig — API-visible DTO containing vendorConfigs
  • SessionConfig — Internal DTO storing requestedVendorConfigs in the request_config JSONB column