Skip to main content

Flow documentation

Single Trip Quote & Purchase

Partner implementation guide for quoting, purchasing, paying for, and binding a single-trip policy.

AudiencePartner developers and solution architects implementing single-trip quote-to-purchase flowsLast updatedOctober 2, 2026Flows1Operations3

This guide explains every GraphQL operation required to quote and issue a single-trip policy. It covers both supported completion patterns:

  • Streamlined purchase: quote -> purchasePolicy for partners approved to submit accounts receivable (AR) or provider tokens directly.
  • Deferred purchase: quote -> stagePolicyPurchase -> embedded payment session -> hosted PCI card form -> automatic backend binding.

Choose one completion pattern for each purchase. After purchasePolicy succeeds, do not stage or bind the same purchase again.

Before You Start

Send GraphQL requests from your backend, not directly from browser code. Every request uses:

HTTP
Content-Type: application/json
Authorization: ApiKey {apiToken}
x-api-key: {accessKey}

Keep both credentials server-side. Use ISO dates in YYYY-MM-DD format and decimal JSON numbers for monetary values.

Operation Summary

StepOperationWhy you call itValue to retain
1quoteRate the trip and return eligible products and coverage choicesquoteNumber, selected productCode, selected coverage IDs, quoted amount
2ApurchasePolicyComplete an approved AR or token purchase in one mutationplanNumber, transactionId, document links
2BstagePolicyPurchaseCreate the pending policy used by deferred paymentplanGuid
3BEmbedded payment appSecurely capture card data, process payment, and automatically bind the staged policypaymentSessionId; reconciled planNumber and policy result

planGuid is temporary workflow state. planNumber is the issued policy identifier used for later search and servicing.

Flow

MERMAID
sequenceDiagram
    autonumber
    actor Traveler
    participant App as Partner app
    participant Backend as Partner backend
    participant API as Travel Insured GraphQL API
    participant Payment as Approved payment flow

    Traveler->>App: Enter trip and traveler details
    App->>Backend: Request eligible products
    Backend->>API: quote
    API-->>Backend: quoteNumber and products
    Backend-->>App: Display products, coverages, and prices
    Traveler->>App: Select product and purchase
    alt Streamlined AR or provider-token purchase
        Backend->>API: purchasePolicy
        API-->>Backend: success, planNumber, transactionId, documents
    else Deferred hosted-payment purchase
        Backend->>API: stagePolicyPurchase
        API-->>Backend: planGuid
      Backend->>Payment: Create payment session for planGuid
      Payment-->>Backend: paymentSessionId, embedToken, expiresAt
      Backend-->>App: Short-lived widget configuration
      App->>Payment: Mount widget and submit card in hosted PCI form
      Payment->>Payment: Process payment and bind policy
      Payment-->>App: Payment or policy UX event
      Backend->>Backend: Reconcile authoritative policy status
    end
    Backend-->>App: Return issued policy confirmation
    App-->>Traveler: Display policy number and document links

Step 1: Request a Quote

quote is a mutation because it creates resumable quote context. It returns a quoteNumber and the products currently available for the submitted agency, residency, dates, destinations, travelers, and trip costs.

Request

GraphQL
mutation QuoteSingleTrip($quoteRequest: QuoteRequestInput!) {
  quote(quoteRequest: $quoteRequest) {
    quoteNumber
    products {
      productId
      productCode
      productName
      productDescription
      availablePaymentMethod {
        paymentMethod
      }
      coverages {
        productCoverageId
        productCoverageType
        productCoverageTypeCode
        coverageLimits {
          productCoverageLimitId
          totalPrice
          available
        }
      }
    }
    emailQuoteMessages {
      title
      message
    }
  }
}

Request example variables:

JSON
{
  "quoteRequest": {
    "agencyNumber": "<assigned-agency-number>",
    "residencyCountryIsoCode": "US",
    "residencyStateIsoCode": "CT",
    "trip": {
      "departureDate": "2027-06-10",
      "returnDate": "2027-06-22",
      "depositDate": "2027-02-15",
      "destinations": [
        { "countryIsoCode": "FR" }
      ],
      "travelers": [
        {
          "id": 1,
          "primaryTraveler": true,
          "dateOfBirth": "1985-06-15",
          "tripCost": 2500.00
        }
      ]
    }
  }
}

Use the Quote Response

  1. Store quoteNumber with the current checkout session.
  2. Display only products returned by this response. Availability can vary by agency, jurisdiction, dates, destination, and traveler details.
  3. Carry the selected productCode into purchase unchanged.
  4. For each optional coverage, carry both productCoverageTypeCode and productCoverageLimitId from the selected returned limit.
  5. Use the current response price to populate the payment amount. Do not calculate premium from display text or hardcoded rate tables.

Re-run quote when pricing inputs change. Treat the new quoteNumber and product response as authoritative.

Choose a Purchase Pattern

PatternWhen it appliesCompletion operation
Streamlined ARYour partner agreement permits accounts-receivable issuancepurchasePolicy with paymentMethod: AR
Streamlined tokenYour integration supplies an approved payment tokenpurchasePolicy with token and billingParty
Deferred hosted paymentCard entry occurs in the Travel Insured payment experiencestagePolicyPurchase, embedded payment session, hosted payment, then server-side reconciliation

Partner enablement determines which pattern is available. Schema visibility does not grant payment or issuance permissions.

Pattern A: Streamlined Purchase

purchasePolicy validates the selected quote and product, applies payment, and issues the policy as one operation.

GraphQL
mutation PurchaseSingleTrip($policyPurchaseInput: PolicyPurchaseInput!) {
  purchasePolicy(policyPurchaseInput: $policyPurchaseInput) {
    success
    errorCode
    errorMessage
    amountCharged
    planNumber
    transactionId
    stagedPolicyId
    cobDownloadLink
    eobDownloadLink
  }
}

Request example variables:

JSON
{
  "policyPurchaseInput": {
    "agencyNumber": "<assigned-agency-number>",
    "quoteNumber": "<quote-number>",
    "deliveryMethods": [
      { "deliveryType": "Email" }
    ],
    "product": {
      "effectiveDate": "2027-06-10",
      "productCode": "<selected-product-code>",
      "optionalCoverages": []
    },
    "trip": {
      "departureDate": "2027-06-10",
      "returnDate": "2027-06-22",
      "depositDate": "2027-02-15",
      "destinations": [
        { "countryIsoCode": "FR" }
      ],
      "primaryTraveler": {
        "firstName": "<traveler-first-name>",
        "lastName": "<traveler-last-name>",
        "dateOfBirth": "1985-06-15",
        "tripCost": 2500.00,
        "email": "traveler@example.com",
        "phoneNumbers": ["+1-555-010-0200"],
        "address": {
          "addressLine1": "123 Example Street",
          "city": "Hartford",
          "stateIsoCode": "CT",
          "zipCode": "06103",
          "countryIsoCode": "US"
        }
      },
      "additionalTravelers": []
    },
    "payment": {
      "amount": 184.50,
      "paymentMethod": "AR",
      "idempotencyKey": "<unique-key-for-this-intended-purchase>"
    }
  }
}

The payment amount must match the current authoritative quoted total. 184.50 is illustrative only; replace it with the total for the selected product and coverages from the current quote state.

The purchase input includes:

InputSource
quoteNumberQuote response
agencyNumber and optional agentIdPartner configuration
product.productCodeTraveler's selected quote product
product.optionalCoverages[]Selected type and limit IDs from the quote
tripConfirmed dates, destinations, costs, and purchaser details
deliveryMethods[]Requested document delivery methods
payment.amountCurrent quoted total
payment branchAR or approved provider-token details

Optional Coverage Selection

Use an empty array when the customer selects no optional coverage:

JSON
"optionalCoverages": []

When the customer selects an optional coverage, carry both identifiers from the selected quote response limit:

JSON
"optionalCoverages": [
  {
    "productCoverageTypeCode": "<type-code-from-quote>",
    "productCoverageLimitId": 301
  }
]

productCoverageTypeCode identifies the coverage and productCoverageLimitId identifies its selected limit. The SDL permits multiple entries and optional startDate and endDate values. Include dates only when the selected coverage contract requires them. Re-run quote after a coverage selection changes, then carry the refreshed selection and authoritative total into either purchase path.

AR Payment

JSON
"payment": {
  "amount": 184.50,
  "paymentMethod": "AR",
  "idempotencyKey": "<unique-key-for-this-intended-purchase>"
}

Omit token and billingParty for AR.

Provider-Token Payment

JSON
"payment": {
  "amount": 184.50,
  "billingParty": {
    "firstName": "<billing-first-name>",
    "lastName": "<billing-last-name>",
    "zipCode": "<billing-postal-code>"
  },
  "idempotencyKey": "<unique-key-for-this-intended-purchase>",
  "token": {
    "token": "<approved-provider-token>",
    "expirationDate": "2028-09",
    "tokenProvider": "approved-token-provider"
  }
}

For token payment, omit paymentMethod.

Use one idempotency key for one intended purchase. Reuse it only when retrying the same purchase after an uncertain result.

  • When success is true, retain planNumber, transactionId, and document links. The policy is complete.
  • When success is false, use errorCode for program logic and errorMessage for support context. Do not automatically retry payment declines.
  • Do not call staging or bind operations after a successful streamlined purchase.

Pattern B: Deferred Purchase with Automatic Binding

Step 2: Stage the Purchase

GraphQL
mutation StageSingleTrip($policyPurchaseStage: PolicyPurchaseStageInput!) {
  stagePolicyPurchase(policyPurchaseStage: $policyPurchaseStage) {
    planGuid
  }
}

Request example variables:

JSON
{
  "policyPurchaseStage": {
    "agencyNumber": "<assigned-agency-number>",
    "quoteNumber": "<quote-number>",
    "deliveryTypes": [
      { "deliveryType": "Email" }
    ],
    "product": {
      "effectiveDate": "2027-06-10",
      "productCode": "<selected-product-code>",
      "optionalCoverages": []
    },
    "trip": {
      "departureDate": "2027-06-10",
      "returnDate": "2027-06-22",
      "depositDate": "2027-02-15",
      "destinations": [
        { "countryIsoCode": "FR" }
      ],
      "primaryTraveler": {
        "firstName": "<traveler-first-name>",
        "lastName": "<traveler-last-name>",
        "dateOfBirth": "1985-06-15",
        "tripCost": 2500.00,
        "email": "traveler@example.com",
        "phoneNumbers": ["+1-555-010-0200"],
        "address": {
          "addressLine1": "123 Example Street",
          "city": "Hartford",
          "stateIsoCode": "CT",
          "zipCode": "06103",
          "countryIsoCode": "US"
        }
      },
      "additionalTravelers": []
    }
  }
}

Repeat the confirmed purchase data. Use quoteNumber, productCode, and optional coverage identifiers from the same quote response. The primary traveler must include the contact and address fields required by PrimaryTravelerInput.

The response contains only planGuid. It does not return the quote number, amount due, transaction ID, or bind status. Keep those values in server-side checkout state.

Step 3: Complete Payment

From your backend, create an embedded payment session with the staged planGuid, current approved amount, billing contact, and billing address. The session response supplies a short-lived paymentSessionId, embedToken, and expiry for the widget. Do not call processPayment; session creation replaces that partner-orchestrated mutation.

Mount the approved tii-payment-widget in the browser. Card number, expiration, and security code must be entered only in the Travel Insured-hosted PCI form loaded by the widget. Keep partner API credentials on the backend and never include them in widget configuration.

After successful card capture, the embedded payment app processes payment and automatically binds the policy on the backend. Widget events such as tii.payment.verified or tii.policy.bound can update the checkout UI but are not authoritative proof of issuance. Poll the session status from the partner backend and require both status and bindStatus to be Bound before confirming success or releasing documents.

Do not call processPayment or policyBindRequest. The embedded payment app owns both operations behind the scenes so the partner does not orchestrate another API call. See the Payment Integration Guide for the session request, widget values, event handling, and security boundary.

Confirmation and Persistence

After successful issuance:

  1. Persist planNumber as the policy identifier.
  2. Associate it with the authenticated customer using server-side authorization checks.
  3. Present document links only to an authorized user and account for their time-limited nature.
  4. Retain reconciliation identifiers according to your approved retention policy.
  5. Remove temporary plan GUID, token, and hosted-payment state when no longer required.

Failure and Retry Rules

Failure pointRecommended action
Quote validation failsCorrect the invalid input and request a new quote
Quote inputs changeRe-run quote; replace the earlier quote and selection
Streamlined result is uncertainCheck existing state, then retry with the same idempotency key
Staging failsCorrect the request; do not start payment without planGuid
Payment or binding is pending or unknownPoll the payment-session status with bounded backoff; do not call payment or bind mutations
Final policy result is uncertainReconcile the existing session before retrying session creation

Never log raw payment tokens, card data, API credentials, or full traveler records. Treat quote numbers, plan GUIDs, plan numbers, and browser payment events as untrusted until authorized and verified on the backend.

Still need help?

Reach out to your account manager for support.