Integrate secure embedded card capture and automatic backend purchase binding while keeping browser signals and credentials within secure boundaries.
Audience: Partner development, security, QA, and architecture teamsLast Updated: October 6, 2026
Use the environment configuration, embedded-payment integration package, and test data supplied during onboarding.
The partner backend authenticates to Travel Insured with the API Token (apiToken) and Access Key (accessKey). Both are sensitive and must remain server-side. The browser receives only short-lived client-safe values supported by the hosted payment contract.
Embedded Payment App
The Travel Insured Embedded Payment App gives partners a secure, hosted payment experience for staged policy purchases. It presents the PCI-compliant card form, keeps raw card data outside the partner application, processes the payment, and automatically binds the staged policy after successful capture. Partners create short-lived payment sessions from their backend, mount the supplied widget in the checkout experience, and reconcile the authoritative payment and binding status before confirming issuance.
Token payment is an optional path for partners that already capture card details within their own PCI-compliant payment environment. The partner tokenizes the card through its approved tokenization setup and submits only the resulting token and required payment details from its trusted backend. Travel Insured's token proxy service securely routes that token through the configured payment-processing path without requiring raw card data in the Travel Insured API request.
Capture the card within the partner's PCI-compliant environment.
Tokenize the card using the account-approved tokenization setup, and keep the token server-side.
Submit the token, account-approved token-provider value, billing party, amount, and idempotency key through the enabled purchase or modification contract.
Validate the authoritative API result before confirming payment or policy completion, and reconcile an uncertain response before retrying.
This option is not enabled by default. It requires additional onboarding, token-proxy and payment-processing configuration, and certification with Travel Insured. Confirm account eligibility, supported transaction types, token requirements, and the approved provider value with your integration contact before implementation. Never submit raw card numbers or security codes through the Travel Insured APIs, and do not expose or log payment tokens.
Payment and Finalization Options
Option
Verified contract
Payment experience
Finalization owner
Streamlined purchase
purchasePolicy
Approved AR or provider-token payment
GraphQL purchase mutation
Streamlined single-trip modification
modifyPlan
Approved AR or provider-token charge/refund
GraphQL modification mutation
Staged embedded purchase
stagePolicyPurchase or stageAnnualPolicyPurchase, then POST /api/embedded-payment-sessions
Travel Insured-hosted PCI-compliant card form
Embedded payment app automatically binds after successful payment capture
The embedded payment app orchestrates payment processing and policy binding on the backend. Partners must not call processPayment or policyBindRequest for this journey. Do not treat a browser callback as proof that payment or binding succeeded.
The verified embedded-payment contract accepts a planGuid from a staged purchase. It does not document paid policy modifications or refunds. Use only the separately approved modification contract for those journeys; do not infer modification support from the session request shape.
Streamlined Purchase
Use purchasePolicy when Travel Insured has approved your partner account to submit AR or approved provider-token payment directly. This path does not require an embedded payment session.
When provider-token payment is enabled, follow the Token Payment Process above. Do not submit raw card data through purchasePolicy.
MERMAID
sequenceDiagram
participant P as Partner server
participant G as Travel Insured GraphQL
P->>G: quote
G-->>P: quoteNumber and products
P->>G: purchasePolicy
G-->>P: purchase result
Text equivalent: the partner server requests a quote, selects a returned product, and sends the approved purchasePolicy input. The server validates the returned purchase result before confirming success.
Staged Embedded Payment
Use the staged flow when payment is completed after a policy purchase has been staged.
Request the applicable purchase quote.
Stage the approved purchase.
Persist the returned planGuid on the trusted server.
From the partner backend, create an embedded payment session for the staged planGuid and current quoted amount.
Return only the short-lived paymentSessionId, embedToken, expiry, and payment-app URL needed to mount the widget.
Capture card data only inside the Travel Insured-hosted PCI-compliant form.
After successful card capture, allow the embedded payment app to process payment and bind the purchase on the backend.
Treat widget events as UX signals and poll the authoritative session status from the partner backend before confirming success.
MERMAID
sequenceDiagram
participant B as Partner browser
participant P as Partner server
participant G as Travel Insured GraphQL
participant H as Embedded payment app
P->>G: Stage approved purchase
G-->>P: staged planGuid
P->>H: POST /api/embedded-payment-sessions
H-->>P: paymentSessionId, embedToken, expiresAt
P-->>B: Short-lived widget configuration
B->>H: Mount widget and load hosted PCI form
B->>H: Customer submits card data in hosted form
H->>H: Process payment and bind staged policy
H-->>B: Payment or binding UX event
B->>P: Untrusted completion signal
P->>H: GET session status
H-->>P: Bound status, planNumber, document links
Text equivalent: the partner server stages the purchase and creates a short-lived embedded payment session. The browser mounts the widget and the customer enters card data only in the Travel Insured-hosted PCI form. After successful capture, the embedded payment app processes payment and automatically binds the purchase on the backend. The partner polls the session status from its backend and makes no separate payment or binding API call.
The embedded payment session replaces partner-orchestrated processPayment and policyBindRequest. Do not call those mutations before or after creating an embedded payment session.
Create the Payment Session
Create the session from the partner backend. The request mirrors the integration harness contract:
HTTP
POST https://embeddedpaymentapp-devtii.azurewebsites.net/api/embedded-payment-sessions
Authorization: ApiKey {apiToken}
x-api-key: {accessKey}
Content-Type: application/json
JSON
{"planGuid":"11111111-2222-3333-4444-555555555555","quoteNumber":"<quote-number>","agencyNumber":"<assigned-agency-number>","agentId":"<optional-agent-id>","billingPartyInformation":{"totalAmount":184.50,"billingAddress":{"addressLine1":"123 Example Street","city":"Hartford","stateIsoCode":"CT","zipCode":"06103","countryIsoCode":"US"},"email":"billing@example.com","firstName":"<billing-first-name>","lastName":"<billing-last-name>"}}
Use the exact staged purchase planGuid and the current approved quoted total. The partner credentials authorize session creation and must never be returned to the browser. A successful session response contains the values needed by the widget:
Load the approved widget module from the supplied payment-app origin. Keep application logic in an external script so the partner site can enforce a Content Security Policy without allowing inline scripts.
The partner backend endpoint in this example creates the payment session and returns only paymentSessionId, embedToken, expiresAt, and paymentAppBaseUrl. It must not return the API Token, Access Key, billing payload, or card data.
JavaScript
const container = document.querySelector('#payment-container');
const status = document.querySelector('#payment-status');
// Implement these functions against authenticated, CSRF-protected partner routes.const session = await partnerCheckout.createPaymentSession();
const widget = document.createElement('tii-payment-widget');
widget.setAttribute('payment-session-id', session.paymentSessionId);
widget.setAttribute('embed-token', session.embedToken);
widget.setAttribute('payment-app-base-url', session.paymentAppBaseUrl);
widget.setAttribute('mode', 'inline');
widget.setAttribute('auto-open', 'true');
widget.setAttribute('button-label', 'Pay now');
container.replaceChildren(widget);
constupdateStatus = (message) => {
status.textContent = message;
};
window.addEventListener('tii.payment.loaded', (event) => {
if (event.detail?.paymentSessionId !== session.paymentSessionId) return;
container.setAttribute('aria-busy', 'false');
updateStatus('Secure payment form loaded.');
});
window.addEventListener('tii.payment.started', (event) => {
if (event.detail?.paymentSessionId !== session.paymentSessionId) return;
updateStatus('Payment is in progress.');
});
window.addEventListener('tii.policy.bound', async (event) => {
if (event.detail?.paymentSessionId !== session.paymentSessionId) return;
updateStatus('Payment received. Confirming policy status...');
// This partner endpoint checks the authoritative session status server-side.const result = await partnerCheckout.getPaymentSessionStatus(
session.paymentSessionId
);
if (result.status === 'Bound' && result.bindStatus === 'Bound') {
updateStatus('Policy confirmed.');
}
});
The example uses inline mode with automatic opening. For the approved modal experience, set mode to modal and use button-label for the launch button text. Validate every event payload and correlate it to the active session, but never use an event alone to confirm payment or policy issuance.
Mount the approved tii-payment-widget with payment-session-id, embed-token, payment-app-base-url, and the configured display mode. Do not add card-number, expiration, or security-code fields to the partner application; those inputs belong to the hosted PCI form loaded by the widget.
Treat embedToken as a short-lived launch credential. Render it only into the approved widget attribute or direct iframe URL, do not log or persist it, and do not include it in analytics or unrelated client state. The payment page removes it from the iframe URL after validation.
Browser Events Are UX Signals
Browser events and iframe messages can drive loading, pending, cancellation, and error presentation. Treat every message as untrusted input:
Validate the sender origin against an exact allowlist.
Validate the message schema and expected session correlation.
Do not accept credentials, card data, or authoritative transaction state through the browser.
Do not show final success or release documents until the backend status response is Bound.
Make status changes accessible with focus management and programmatic announcements.
Automatic Backend Binding
The embedded payment app owns payment processing and purchase binding. Successful secure card capture starts that backend orchestration; the partner does not call a separate payment or binding mutation. Verify the final authoritative session state before confirming success to the customer.
Modification Refund Boundary
For an entitled direct single-trip refund, modifyPlan performs the approved change and refund in one operation and supports AR or an approved provider token. The SDL does not define whether its payment.amount uses a signed or absolute refund value, so follow the account-specific contract and do not infer the convention. Annual refunds use only the annual-capable direct contract assigned during onboarding; the public SDL does not name that operation.
Authoritative Session Status
Poll the payment session from the partner backend. Send the API Token in the Authorization header and the same registered request origin used to create the session. Never call this endpoint from the browser.
HTTP
GET https://embeddedpaymentapp-devtii.azurewebsites.net/api/embedded-payment-sessions/{paymentSessionId}/status
Authorization: ApiKey {apiToken}
Origin: {registeredPartnerOrigin}
The response contains only the safe session model. A bound response includes the issued plan identifier and available document links:
Only status: "Bound" with bindStatus: "Bound" is completion success. BindFailed, Failed, Cancelled, and Expired are terminal non-success states. Other statuses are in progress. Use bounded polling and stop at the session expiry; do not ask the customer to pay again until an ambiguous result has been reconciled. A 410 response means the session expired, while 429 requires honoring a bounded backoff before polling again.
Widget events, iframe messages, and browser-carried identifiers remain UX signals only. The partner backend status response is authoritative for this embedded flow.
Testing with Test Credit Cards
Use these test credit card numbers only in the sandbox environment to verify payment flows without processing real transactions.
Card type
Card number
Visa
4007000000027
Visa
4012888818888
Visa
4111111111111111
Mastercard
5424000000000015
Mastercard
2223000010309703
Mastercard
2223000010309711
For all test cards, use any future expiration date, any three-digit CVV, and any cardholder name. For example, use expiration date 12/27 and CVV 123.
To test a declined transaction, use ZIP code 46282 with any test card listed above. Other sandbox transactions using these cards process successfully.
Credential and Card-Data Boundary
Name
Purpose
Secret
Browser safe
Provided by
apiToken
Partner API authentication
Yes
No
Travel Insured
accessKey
Partner/API access credential
Yes
No
Travel Insured
Do
Do not
Keep apiToken and accessKey in an approved server-side secret store
Include either credential in HTML, browser JavaScript, client-visible component configuration, mobile apps, logs, analytics, or source control
Use only a Travel Insured-approved hosted card-entry experience
Build card-number or security-code fields unless separately approved for that compliance scope
Correlate server records with non-sensitive identifiers
Log card data, access tokens, hosted-payment capabilities, or full customer payloads
Poll the authoritative session status server-side
Trust client state, redirects, query strings, or browser events as final authority
Reconcile ambiguous outcomes before retrying
Call processPayment or policyBindRequest, or blindly replay session creation
Implementation Checklist
The embedded payment app is the sole owner of payment processing and purchase binding.