Skip to main content

Flow documentation

Single Trip Policy Modification

End-to-end sequence and GraphQL examples for searching, pricing, staging, paying for, and finalizing a single-trip plan modification.

AudiencePartner developers and solution architects implementing single-trip modification flowsLast updatedOctober 2, 2026Flows1Operations5

Use this flow to modify an issued single-trip plan: find the plan, quote the change, process any premium charge or refund, and finalize the modification.

The GraphQL schema also exposes input families for destination, traveler, and primary-traveler changes. Enable those scenarios only when the corresponding product rules and request shapes are included in your account configuration.

Before You Start

You need:

  • The GraphQL endpoint assigned to your environment.
  • Server-side Authorization: ApiKey {apiToken} and x-api-key: {accessKey} header values.
  • The issued planNumber and authorization to service that plan.
  • A customer-approved change supported by the plan and product configuration.
  • The approved direct payment contract when a premium charge or refund is due.

Send all GraphQL operations from your backend. Do not expose API credentials in browser code or use real customer identifiers in examples, logs, tickets, or screenshots.

Flow Summary

StepOperationTypeCarry forward
1searchPlanQueryCandidate plan record and current plan context
2planModificationQuoteQueryQuoted coverage identifiers and totalAmountDue
3Choose the amount branch; stage with planModifyRequest when requiredDecision and conditional mutationStaged paths: modificationPlanGuid; streamlined path: approved change input
4Positive or negative: modifyPlanProcess the premium change using AR or an approved provider tokenBound result and document links
5planModifyFinalize an enabled zero-amount staged pathCurrent planNumber and document links returned by finalization

Sequence Diagram

MERMAID
sequenceDiagram
    autonumber
    actor Traveler as Traveler
    participant PartnerApp as "Partner app"
    participant PartnerBackend as "Partner backend"
    participant TiiGraphQL as "Travel Insured GraphQL API"

    Traveler->>PartnerApp: Request a change to an issued plan
    PartnerApp->>PartnerBackend: Submit plan number and search context
    PartnerBackend->>PartnerBackend: Authorize servicing access independently
    PartnerBackend->>TiiGraphQL: searchPlan(planNumber)
    TiiGraphQL-->>PartnerBackend: Plan, trip, traveler, product, and coverage context
    PartnerBackend-->>PartnerApp: Show current plan details
    Traveler->>PartnerApp: Select a coverage change
    PartnerApp->>PartnerBackend: Submit proposed change
    PartnerBackend->>TiiGraphQL: planModificationQuote(change)
    TiiGraphQL-->>PartnerBackend: Quoted coverage IDs and totalAmountDue
    PartnerBackend-->>PartnerApp: Show priced change
    Traveler->>PartnerApp: Approve the quoted change
    PartnerApp->>PartnerBackend: Confirm approval
    alt totalAmountDue is greater than zero
        PartnerBackend->>TiiGraphQL: modifyPlan(approved change, AR or token)
        TiiGraphQL-->>PartnerBackend: Bound plan and document links
    else totalAmountDue equals zero and no-payment path is enabled
        PartnerBackend->>TiiGraphQL: planModifyRequest(approved change)
        TiiGraphQL-->>PartnerBackend: planGuid (store as modificationPlanGuid)
        PartnerBackend->>TiiGraphQL: planModify(modificationPlanGuid)
        TiiGraphQL-->>PartnerBackend: Current plan number and document links
    else totalAmountDue is less than zero
        PartnerBackend->>TiiGraphQL: modifyPlan(approved change, AR or token refund details)
        TiiGraphQL-->>PartnerBackend: Bound plan and document links
    else Amount is missing or stale
        PartnerBackend->>TiiGraphQL: Re-quote complete change
    end
    PartnerBackend-->>PartnerApp: Return confirmed modification
    PartnerApp-->>Traveler: Show updated plan confirmation

Text Sequence Equivalent

StepInitiatorRequest or eventResult
1TravelerRequests a change to an issued single-trip planPartner app collects the plan number and requested change
2Partner backendAuthorizes servicing access independently and calls searchPlanA candidate plan record and current policy context are available for review
3TravelerSelects a supported coverage changePartner backend can request modification pricing
4Partner backendCalls planModificationQuote with a valid coverage identifier pairQuoted coverage details and totalAmountDue are returned
5TravelerApproves the priced changePartner backend can stage exactly what was approved
6Partner backendUses the sign of the current totalAmountDue to choose additional payment, enabled no-payment, direct refund, or re-quoteExactly one completion pattern is used
7aPartner backendCalls modifyPlan with AR or an approved payment token for a charge or refundThe change, premium transaction, and bind complete in one API request
7bPartner backendFor an enabled no-payment staged path, calls planModifyRequest and then planModifyUpdated plan and document details are returned
8Partner appDisplays the authoritative confirmed resultTraveler sees the updated single-trip plan confirmation

GraphQL Request Format

Send each operation to graphqlBaseUrl with these headers:

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

The examples below separate the GraphQL document from its variables. Replace all sample values with environment-valid, server-side values.

Step 1: Find the Issued Plan

Use searchPlan to locate a candidate plan record and retrieve the current values needed to build a modification. A successful lookup does not prove that the caller is authorized to view or modify the plan. Enforce servicing entitlement independently on the backend. searchAllTravelers is required by the schema. Use true when the servicing experience must return all travelers; use false when the workflow needs only the primary traveler.

The selection below includes every PlanSearchResult field that maps to ModifyPlanQuoteRequestInput or helps select a valid modification. It intentionally excludes unrelated claims, payment history, notes, and document history.

GraphQL
query FindSingleTripPlan(
    $planSearchRequest: PlanSearchRequestInput!
    $first: Int
    $after: String
) {
    searchPlan(
        planSearchRequest: $planSearchRequest
        first: $first
        after: $after
    ) {
        totalCount
        pageInfo {
            hasNextPage
            endCursor
        }
        edges {
            node {
                planNumber
                planStatus
                planType
                isActive
                isAnnual
                effectiveDate
                expirationDate
                planPrimaryTraveler {
                    travelerId
                    firstName
                    lastName
                    middleName
                    dateOfBirth
                    email
                    tripCost
                    phoneNumbers {
                        phoneNumber
                        type
                    }
                    address {
                        addressLine1
                        addressLine2
                        city
                        stateIsoCode
                        countryIsoCode
                        zipCode
                    }
                    beneficiaries {
                        beneficiaryId
                        firstName
                        lastName
                        middleInitial
                        percentage
                    }
                }
                planAdditionalTravelers {
                    travelerId
                    firstName
                    lastName
                    middleName
                    dateOfBirth
                    tripCost
                    beneficiaries {
                        beneficiaryId
                        firstName
                        lastName
                        middleInitial
                        percentage
                    }
                }
                planTripDetails {
                    departureDate
                    depositDate
                    returnDate
                    destinations {
                        countryIsoCode
                        stateIsoCode
                        destinationName
                    }
                    coverages {
                        productCoverageTypeCode
                        startDate
                        endDate
                        coverageLimits {
                            productCoverageLimitId
                        }
                    }
                }
                planProduct {
                    productId
                    productCode
                    availableCoverages {
                        productCoverageTypeCode
                        startDate
                        endDate
                        pricingCoverageLimits {
                            productCoverageLimitId
                            totalPrice
                        }
                    }
                    upsellProduct {
                        productId
                        productCode
                        productName
                    }
                }
                pricingDetail {
                    totalPrice
                }
            }
        }
    }
}

Request example variables:

JSON
{
    "planSearchRequest": {
        "planNumber": "PLAN-EXAMPLE-001",
        "searchAllTravelers": true,
        "strictSearch": true
    },
    "first": 10
}

Before returning plan data to the browser, enforce agency or tenant-scoped authorization and verify that exactly one expected active, non-annual plan was returned. Use generic responses for unauthorized or missing records, rate-limit searches, and audit servicing access. Treat names, email addresses, dates, and plan numbers as sensitive customer data.

Field Provenance and Carry-Forward Rules

Do not copy the entire searchPlan result into a mutation. Build an explicit allowlisted input object containing only the customer-approved changes.

Modification inputSourceHow to use it
planNumberedges[].node.planNumberCarry forward unchanged to quote and staging.
primaryTraveler.travelerIdplanPrimaryTraveler.travelerIdCarry forward unchanged whenever primaryTraveler is included.
primaryTraveler editable fieldsplanPrimaryTravelerPrefill the UI; submit only approved changes. Convert one selected phoneNumbers[].phoneNumber value to singular phoneNumber.
primaryTraveler.beneficiaries[]planPrimaryTraveler.beneficiaries[]Preserve beneficiaryId for existing beneficiaries and submit the complete approved allocation.
additionalTravelers[].travelerIdplanAdditionalTravelers[].travelerIdCarry forward the ID for an existing traveler being updated.
additionalTravelers[] editable fieldsplanAdditionalTravelers[]Prefill and submit only approved changes. Date of birth is returned for display but is not accepted by ModifyAdditionalTravelerInput.
additionalTravelersToRemove[]planAdditionalTravelers[].travelerIdSubmit only IDs explicitly selected for removal.
additionalTravelersToAdd[]Customer-provided traveler detailsNew travelers have no searchPlan source. Collect required name, date of birth, and trip cost values.
departureDate, returnDateplanTripDetails[].departureDate and returnDatePrefill current dates; submit the newly approved values when changing them.
destinations[]planTripDetails[].destinations[]Prefill current destinations; submit the complete approved destination list. destinationId is not returned by searchPlan.
coveragesToAdd[]planProduct.availableCoverages[]Select an available productCoverageTypeCode and nested productCoverageLimitId; carry the approved pair into staging.
upSellProductIdplanProduct.upsellProduct.productIdInclude only when the customer selects the offered upsell product.
deliveryTypeCodes[]Partner configuration or customer delivery choiceRequired only by planModifyRequest; not returned by searchPlan. The verified example uses Email.

planTripDetails.coverages describes coverage already on the plan. Do not send an existing coverage through coveragesToAdd unless the API explicitly identifies it as addable. Use planProduct.availableCoverages for new coverage choices.

Step 2: Quote the Modification

Use planModificationQuote to price the complete proposed change. This primary example adds one optional coverage selected from planProduct.availableCoverages. Send only the properties needed for the customer-approved change.

GraphQL
query GetPlanModificationQuote(
    $modifyPlanQuoteRequest: ModifyPlanQuoteRequestInput!
) {
    planModificationQuote(
        modifyPlanQuoteRequest: $modifyPlanQuoteRequest
    ) {
        planNumber
        availableCoverages {
            productCoverageTypeCode
            pricingCoverageLimits {
                productCoverageLimitId
                totalPrice
            }
        }
        pricingDetail {
            totalAmountDue
        }
    }
}

Primary request variables:

JSON
{
    "modifyPlanQuoteRequest": {
        "planNumber": "PLAN-EXAMPLE-001",
        "coveragesToAdd": [
            {
                "productCoverageLimitId": 301,
                "productCoverageTypeCode": "CFAR"
            }
        ]
    }
}

Source both coverage identifiers from the current plan response. The values above are synthetic and align with the representative response below; do not hardcode them in production.

Advanced Reference — Do not copy wholesale

The following payload shows the broader schema-supported change families in one place. It is not a recommended combined customer request. Include only fields supported by the current product and partner configuration, and do not add, update, and remove the same traveler in one request.

JSON
{
    "modifyPlanQuoteRequest": {
        "planNumber": "PLAN-EXAMPLE-001",
        "primaryTraveler": {
            "travelerId": 101,
            "firstName": "Alex",
            "lastName": "Example",
            "middleName": "J",
            "email": "alex@example.com",
            "phoneNumber": "+1-860-555-0100",
            "tripCost": 2500.0,
            "address": {
                "addressLine1": "123 Example Street",
                "addressLine2": "Suite 200",
                "city": "Hartford",
                "zipCode": "06103"
            },
            "beneficiaries": [
                {
                    "beneficiaryId": 501,
                    "firstName": "Jordan",
                    "lastName": "Example",
                    "middleInitial": "R",
                    "percentage": 100.0
                }
            ]
        },
        "additionalTravelers": [
            {
                "travelerId": 102,
                "firstName": "Taylor",
                "lastName": "Example",
                "middleName": "M",
                "tripCost": 1800.0,
                "beneficiaries": [
                    {
                        "beneficiaryId": 502,
                        "firstName": "Morgan",
                        "lastName": "Example",
                        "middleInitial": "K",
                        "percentage": 100.0
                    }
                ]
            }
        ],
        "additionalTravelersToAdd": [
            {
                "firstName": "Casey",
                "lastName": "Example",
                "middleName": "L",
                "dateOfBirth": "1990-06-15",
                "tripCost": 1600.0,
                "beneficiaries": [
                    {
                        "firstName": "Riley",
                        "lastName": "Example",
                        "middleInitial": "A",
                        "percentage": 100.0
                    }
                ]
            }
        ],
        "additionalTravelersToRemove": [103],
        "departureDate": "<future-departure-date: YYYY-MM-DD>",
        "returnDate": "<future-return-date: YYYY-MM-DD>",
        "destinations": [
            {
                "countryIsoCode": "FR",
                "destinationName": "France"
            }
        ],
        "coveragesToAdd": [
            {
                "productCoverageLimitId": 301,
                "productCoverageTypeCode": "CFAR",
                "startDate": "<coverage-start-date: YYYY-MM-DD>",
                "endDate": "<coverage-end-date: YYYY-MM-DD>"
            }
        ],
        "upSellProductId": 2001
    }
}

All values are illustrative. Source existing traveler IDs and current values from searchPlan, source coverage choices from planProduct.availableCoverages, and source the upsell ID from planProduct.upsellProduct. New traveler data and changed values come from validated customer input.

Representative response excerpt:

JSON
{
    "data": {
        "planModificationQuote": {
            "planNumber": "PLAN-EXAMPLE-001",
            "availableCoverages": [
                {
                    "productCoverageTypeCode": "CFAR",
                    "pricingCoverageLimits": [
                        {
                            "productCoverageLimitId": 301,
                            "totalPrice": 75.0
                        }
                    ]
                }
            ],
            "pricingDetail": {
                "totalAmountDue": 75.0
            }
        }
    }
}

totalAmountDue is the price difference calculated as:

new premium - existing premium

A positive result is additional premium, zero is no price change, and a negative result is a premium reduction. Use the account-approved AR or provider-token payment shape for a refund; server-side validation determines whether the transaction is eligible.

Validate that the response corresponds to the complete requested change, show the customer the complete pricing impact, and obtain explicit approval before staging. Preserve an immutable server-side snapshot of the approved quote input for the next step.

Step 3: Choose the Completion Path

After the customer approves the complete quoted change and amount, use this decision table. Do not infer refund behavior from schema nullability.

totalAmountDueRequired pathStep 3 actionContinue to
Greater than 0Additional paymentUse approved direct modifyPlan completionStep 4
Equal to 0Enabled no-payment pathStage with planModifyRequest and retain modificationPlanGuidStep 5, Option A
Less than 0Direct refundUse modifyPlan with AR or an approved provider tokenStep 4, Option B
Missing or staleStop and re-quoteDo not stage, pay, refund, or finalizeStep 2

Use exactly one path for a modification. Do not stage first and then submit the same change through modifyPlan.

modifyPlan is the streamlined operation that accepts the full change and optional payment details. planModify is the staged finalization operation that accepts a previously returned planGuid. They are different mutations and are not interchangeable.

Staged Path: Stage the Approved Modification

Call planModifyRequest with the same approved change object and add deliveryTypeCodes. deliveryTypeCodes is required by the schema; the verified example uses Email.

GraphQL
mutation InitiatePlanModification(
    $modifyPlanRequest: ModifyPlanRequestInput!
) {
    planModifyRequest(modifyPlanRequest: $modifyPlanRequest) {
        planGuid
    }
}

Request example variables:

JSON
{
    "modifyPlanRequest": {
        "planNumber": "PLAN-EXAMPLE-001",
        "coveragesToAdd": [
            {
                "productCoverageLimitId": 301,
                "productCoverageTypeCode": "CFAR"
            }
        ],
        "deliveryTypeCodes": [
            {
                "deliveryType": "Email"
            }
        ]
    }
}

Representative response:

JSON
{
    "data": {
        "planModifyRequest": {
            "planGuid": "11111111-2222-3333-4444-555555555555"
        }
    }
}

Store this returned planGuid as modificationPlanGuid. It identifies the staged modification and is not the original purchase-stage planGuid.

Step 4: Complete a Direct Premium Change

The verified embedded-payment session contract is for staged purchases and does not document paid modifications. For a positive or negative totalAmountDue, use modifyPlan only when your integration is approved for direct completion with AR or an approved provider token. Do not send a modification-stage GUID to the purchase payment-session endpoint.

modifyPlan API Request

When your integration is approved for direct completion, call modifyPlan with the exact customer-approved ModifyPlanRequestInput. This single request stages the change, processes any required premium charge or refund, and binds the modification. Do not call planModifyRequest, create an embedded payment session, or call planModify for the same change.

GraphQL
mutation CompleteModification(
    $modifyRequest: ModifyPlanRequestInput!
    $payment: PaymentDetailsInput
) {
    modifyPlan(
        modifyRequest: $modifyRequest
        payment: $payment
    ) {
        planNumber
        cobDownloadLink
        eobDownloadLink
    }
}

Use the same approved modification shape shown in Step 3 as modifyRequest, but send it directly to this mutation. Supply payment details when the modification changes the premium.

Request example variables:

JSON
{
    "modifyRequest": {
        "planNumber": "PLAN-EXAMPLE-001",
        "coveragesToAdd": [
            {
                "productCoverageLimitId": 301,
                "productCoverageTypeCode": "CFAR",
                "startDate": "<coverage-start-date: YYYY-MM-DD>",
                "endDate": "<coverage-end-date: YYYY-MM-DD>"
            }
        ],
        "deliveryTypeCodes": [
            {
                "deliveryType": "Email"
            }
        ]
    },
    "payment": {
        "amount": 125.0,
        "paymentMethod": "AR",
        "idempotencyKey": "<unique-modification-attempt-key>"
    }
}

The example uses accounts receivable. To use an approved provider token, replace the payment value with the provider-token shape below; keep the same approved modifyRequest.

Accounts receivable (AR):

JSON
{
    "amount": 125.0,
    "paymentMethod": "AR",
    "idempotencyKey": "<unique-modification-attempt-key>"
}

Approved provider token:

JSON
{
    "amount": 125.0,
    "billingParty": {
        "firstName": "Alex",
        "lastName": "Example",
        "zipCode": "06103"
    },
    "token": {
        "token": "<approved-provider-token>",
        "tokenProvider": "VISA",
        "expirationDate": "<provider-required-expiration-value>"
    },
    "idempotencyKey": "<unique-modification-attempt-key>"
}

For an AR charge or refund, set paymentMethod to AR and omit token. For a provider-token charge or refund, supply the provider-discriminated token and required billing party, and omit paymentMethod. Use the refund amount representation supplied for your account because the SDL does not define whether payment.amount is signed or absolute for refunds. Keep tokens and billing data server-side, never log them, and reconcile an uncertain response before retrying. Omit payment only when the approved direct contract supports a no-cost modification.

Step 5: Finalize an Enabled Zero-Amount Modification

Call planModify directly only when totalAmountDue = 0 and the no-payment staged path is enabled for your account.

GraphQL
mutation FinalizeNoPaymentModification($planGuid: UUID!) {
    planModify(planGuid: $planGuid) {
        planNumber
        cobDownloadLink
        eobDownloadLink
    }
}

Request example variables:

JSON
{
    "planGuid": "11111111-2222-3333-4444-555555555555"
}

Representative response:

JSON
{
    "data": {
        "planModify": {
            "planNumber": "PLAN-EXAMPLE-001",
            "cobDownloadLink": "https://documents.example/coverage.pdf",
            "eobDownloadLink": "https://documents.example/benefits.pdf"
        }
    }
}

Treat returned document links as sensitive. Deliver them only to the authorized customer and follow the URL expiry and caching controls defined for your environment.

Modification Is Not Cancellation

The public schema does not expose a general paid retail cancellation mutation. Do not recommend or use modifyPlan, planModifyRequest, or a zero-value modification as a cancellation workaround; use the separately authorized cancellation servicing route supplied for the account.

Other Schema-Supported Change Inputs

The schema exposes the following optional change families on both ModifyPlanQuoteRequestInput and ModifyPlanRequestInput:

Change familyQuote inputStaging inputCurrent contract evidence
Add coveragecoveragesToAddcoveragesToAddDemonstrated
Update existing traveleradditionalTravelersadditionalTravelersSchema only
Add traveleradditionalTravelersToAddadditionalTravelersToAddSchema only
Remove traveleradditionalTravelersToRemoveadditionalTravelersToRemoveSchema only
Update primary travelerprimaryTravelerprimaryTravelerSchema only
Update trip datesdepartureDate, returnDatedepartureDate, returnDateSchema only
Update destinationdestinationsdestinationsSchema only
Select upsell productupSellProductIdupSellProductIdSchema only

Do not assume that every schema-valid shape is enabled for every product or partner. Validate business rules, required nested fields, price behavior, and the matching staging contract before exposing a change type.

Failure and Recovery Rules

  • Treat a GraphQL HTTP 200 response containing an errors array as a failed operation.
  • Do not stage a modification when quote pricing is missing, stale, or no longer matches the customer-approved change.
  • Do not retry staging or no-payment planModify blindly. Use an idempotency or reconciliation strategy approved by Travel Insured.
  • Reconcile any unknown modifyPlan charge or refund outcome before retrying.
  • If direct payment or finalization is uncertain, preserve the modification identifiers and reconcile server-side before asking the customer to pay again.
  • Do not show success until authoritative reconciliation confirms the updated plan, or no-payment planModify returns the updated plan result.
  • Mask plan numbers, transaction IDs, traveler details, and document links in application logs.

Implementation Checklist

  • Authorize access to the issued plan before returning plan details.
  • Confirm isAnnual is false and the plan is eligible for modification.
  • Use response-derived coverage identifiers from the current environment.
  • Stage exactly the change and price the customer approved.
  • Store the staged planGuid as modificationPlanGuid.
  • Apply the amount decision table: positive is additional payment, zero is enabled no-payment, negative is a direct refund, and missing or stale means stop and re-quote.
  • Use exactly one completion path: direct modifyPlan or enabled zero-amount staged finalization.
  • Use the account-approved AR or provider-token payment shape for a direct modifyPlan refund.
  • Do not use the staged-purchase payment-session endpoint for a policy modification.
  • For streamlined completion, keep payment tokens and billing data server-side and use a unique idempotency key.
  • Treat browser events as UX signals and reconcile the authoritative updated-policy state server-side.
  • Keep modification refunds distinct from cancellation.
  • Protect customer data, identifiers, payment metadata, and document links.

Still need help?

Reach out to your account manager for support.