Insurance
API Path
Quotes

Quotes

A quote is the price given for a specific basket and insured details. A quote request returns one or more options; each option has its own ID (quoteId), premium and validity. You create an order with the option the buyer confirms.

A quote is not a money movement and does not issue a policy. Your provider connections, not your request, decide which provider gives the quote. A single request can return options from several products and insurance companies in your connections: Multiple options.

Authentication and signing: Flows › Authentication.

Getting a quote: POST /api/v1/insurance/quotes

Idempotency-Key is optional. Each request returns a new, time-limited price.

FieldTypeRequiredDescription
insuranceTypestringYesInsurance type; the insuranceType from the Eligibility response.
schemaVersionintegerNoSchema version of the type. If omitted, the current version is used.
currencystringYesCurrency, ISO 4217. Must equal the payment's currency.
context.itemsarrayBasket sourceThe basket items you will send in the payment; the format is the same as Basket Items, insuranceData included.
paymentIntentIdstring (UUID)Basket sourceID of a Lunixi payment you created earlier.
merchantOrderIdstringNoYour own order number, up to 128 characters. For reconciliation; the order inherits this value.
policyholderobjectBy typeThe policyholder. Can be completed from the items' pre-fill data: Quote with pre-fill data.
insuredarrayBy typeThe insured persons. Can be completed from the items' pre-fill data.
Type objectarray or objectBy typeIts name is the type's typeObject value; for example tickets for TICKET_CANCELLATION. Can be completed from the items' context and pre-fill data.
  • Send context.items or paymentIntentId as the basket source; if both are sent, the request is rejected.
  • If you send neither, the quote is obtained without a basket item. This applies only to types sold without a basket item: Selling Without a Basket Item.
  • The fields of policyholder, insured and the type object, and when they are required, are in the type's schema: Insurance Types and Schemas. A field that is not in the schema is rejected.
  • Link each entry of the type object to the insured basket item with basketItemId. In a quote taken with paymentIntentId, basketItemId is required. In a quote taken with context.items, if basketItemId is omitted the type covers all items it is offered for.
  • If the items carry insuranceContext or insuranceData, the body is completed from these details and basketItemId can be taken from the item; the rules: Quote with pre-fill data.
🚫

Send the fields needed for the policy in the quote request as well. Fields the schema requires at the POLICY stage (for TICKET_CANCELLATION, the booking reference, the ticket number, the insured person's email and phone, among others) are not required for the quote, but the policy is issued with this quote's details. The order and policy requests carry no additional fields. If these fields are missing, the policy cannot be issued after the premium is collected and the premium has to be refunded.

⚠️

If you will add the premium to your payment's basket, get the quote with context.items. The premium item must be in the payment's basket and its ID is the order ID; so you create the payment after the order. The basket of a payment that was already created does not change: an order created from a quote taken with paymentIntentId is rejected with 409 insurance.order.premium_item_mismatch because the payment's basket has no premium item. See Premium and Payment.

A quote request with two tickets for TICKET_CANCELLATION. The values are examples; replace the values in angle brackets with your buyer's details:

{
  "insuranceType": "TICKET_CANCELLATION",
  "currency": "TRY",
  "merchantOrderId": "order-1001",
  "context": {
    "items": [
      {
        "id": "ticket-1",
        "name": "Izmir-Ankara train ticket",
        "price": 50000,
        "category1": "ticket",
        "itemType": "VIRTUAL",
        "insuranceCategory": "TICKET",
        "insuranceTypes": ["TICKET_CANCELLATION"]
      },
      {
        "id": "ticket-2",
        "name": "Izmir-Ankara train ticket",
        "price": 50000,
        "category1": "ticket",
        "itemType": "VIRTUAL",
        "insuranceCategory": "TICKET",
        "insuranceTypes": ["TICKET_CANCELLATION"]
      }
    ]
  },
  "insured": [
    {
      "identityType": "TCKN",
      "identityNumber": "<identity number>",
      "birthDate": "<YYYY-MM-DD>",
      "email": "<email>",
      "phone": "<E.164 phone>"
    }
  ],
  "tickets": [
    {
      "basketItemId": "ticket-1",
      "transportMode": "TRAIN",
      "carrier": "Example Carrier",
      "priceAmount": 50000,
      "departureAt": "2025-12-23T12:50:00+03:00",
      "originCity": "Izmir",
      "destinationCity": "Ankara",
      "pnr": "<booking reference>",
      "ticketNumber": "<ticket number>"
    },
    {
      "basketItemId": "ticket-2",
      "transportMode": "TRAIN",
      "carrier": "Example Carrier",
      "priceAmount": 50000,
      "departureAt": "2025-12-23T12:50:00+03:00",
      "originCity": "Izmir",
      "destinationCity": "Ankara",
      "pnr": "<booking reference>",
      "ticketNumber": "<ticket number>"
    }
  ]
}
source lunixi-sign.sh
BODY='<quote request, compact JSON>'
lunixi_sign POST "/api/v1/insurance/quotes" "$BODY"
 
curl -X POST "https://api-gateway.lunixi.com/api/v1/insurance/quotes" \
  -H "Content-Type: application/json" \
  -H "X-Key-Id: $LUNIXI_KEY_ID" \
  -H "X-Date: $DATE" \
  -H "X-Nonce: $NONCE" \
  -H "Digest: $DIGEST" \
  -H "X-Signature: $SIGNATURE" \
  --data-raw "$BODY"

Response

A successful request returns 201. data carries these fields:

FieldTypeDescription
insuranceTypestringInsurance type.
schemaVersionintegerSchema version used in the quote.
optionsarrayThe options. Their fields are in the option table below.
excludedOptionsarrayOptions of the products that could not quote. Their fields are in the Excluded options section. An empty array if no option was excluded.

If no option can be obtained from any of your connections, the request returns an error; an empty option list is not returned.

Quote with pre-fill data

If the basket items carry insuranceContext or insuranceData, the quote body is completed from these details. In the request you send only the missing fields or the ones you want to change. The format of the pre-fill data: Basket Items › Insurance pre-fill data.

Basket sourceWhere the details come from
paymentIntentIdThe insuranceContext and insuranceData you sent in the items when the payment was created. The body may be empty or partial. The pre-fill data is deleted once the payment is 24 hours old; for a quote taken after that, send the details in the request.
context.itemsThe insuranceContext and insuranceData of the items in the same request. The pre-fill data is not stored; it is used only in this request.

Whether the items carry everything the quote needs is shown by quoteReady in the Eligibility response. If the items carry everything, you can get the quote with only the type, the currency and the payment ID:

{
  "insuranceType": "TICKET_CANCELLATION",
  "currency": "TRY",
  "paymentIntentId": "<payment ID>"
}

If something is missing, send only the missing fields. In the example the booking code and ticket number needed for the policy are added; the trip, the passenger and the ticket amount come from the item:

{
  "insuranceType": "TICKET_CANCELLATION",
  "currency": "TRY",
  "paymentIntentId": "<payment ID>",
  "tickets": [
    {
      "basketItemId": "ticket-1",
      "pnr": "<booking code>",
      "ticketNumber": "<ticket number>"
    }
  ]
}

Merge rules

  • The request wins. The base is the items' context and pre-fill data; the request body is written over the base. For the same field the value you send in the request applies. If the context and the pre-fill data have the same field, the pre-fill data applies.
  • If you do not send the type object, it is built from the items that carry context or pre-fill data; basketItemId is the item's id. An item that carries neither is not part of the quote. To cover that item too, send an entry in the type object with that item's basketItemId.
  • Type object that is an array (tickets): if you send it, the quote covers only the tickets you send. A ticket whose basketItemId matches an item is completed with that item's details.
  • Types with a single object (device, vehicle and so on): the basketItemId in the object selects whose details are used. If you do not send it, the first item carrying context or pre-fill data is used and the quote is tied to that item.
  • insured: the items' insured persons are merged into one list in item order; the same identityType and identityNumber is not repeated and the type's maximum is not exceeded. Each entry of the insured list you send in the request is written over the insured person in the same position.
  • policyholder: taken from the first item whose pre-fill data gives a policyholder; the fields you send in the request are written over it.

Validation:

  • The merged body is fully validated against the type's schema. A field in the pre-fill data or in the request that breaks a rule gets 422 insurance.validation.invalid with its field path.
  • A value from the context that does not fit the type is not used; it does not block the quote.
  • If the items carry context or pre-fill data, it is first checked whether the type is offered for this basket; if not, 412 insurance.type.not_available is returned.
  • If the items carry no context and no pre-fill data, the quote is taken with the request body only, as today.

Multiple options

The quote request is sent at the same time to every product in your connections for which the type is enabled. Each product returns its own option.

  • Several options can come from the same insurance company; for example different plans of the same product.
  • If the same insurance company's quote comes from two different provider connections of yours, two separate options are returned. Lunixi does not pick one of them for you.
  • Options are returned in the order of your connections.
  • The response waits for the connections up to a set time. The option of a connection that does not answer within that time is excluded with insurance.provider.unavailable; the other options are returned. Do not set your client timeout below 30 seconds.

Provider and insurance company

In an option, the provider and the insurance company are separate fields:

  • provider is the provider connection the quote came from.
  • underwriter is the insurance company that issues the policy. The same insurance company can come from different providers; underwriter.code is the same for the same company whichever provider it comes from.
  • If the product does not state an insurance company, underwriter is null.
  • underwriter.disclosureText is the insurance company's information text to show to the buyer. It is returned in the language of the request (x-lang or Accept-Language: tr, en); if there is no text in that language, the text in the other language is returned.

Excluded options

If a product cannot quote, only that product's option is excluded; the other options are not affected. Excluded options are in the excludedOptions array:

FieldTypeDescription
underwriterobject or nullThe option's insurance company; its fields are as in the option table.
provider.codestringThe provider's code in the Lunixi catalog.
provider.namestringThe provider's name.
provider.logoUrlstring or nullThe provider's logo.
provider.connectionIdstringID of the provider connection of the option.
errorCodestringWhy the option was excluded; a Lunixi error code (Error Codes).
errorsarrayIf errorCode is insurance.validation.invalid, the missing fields the product needs: each entry carries field (the field path, e.g. insured[0].birthDate) and reason (e.g. required). May be empty for other codes.
  • The most common reason is a field the product needs at the quote stage being missing. If you add the missing fields and get a new quote, that product's option is returned too. Product requirements: Eligibility › Product requirements.
  • An excluded option has no quoteId; no order can be created with it.
  • excludedOptions is only in the response of getting a quote; it is not in the retrieve response.
  • The values you sent and the provider's own error codes are not written to this array.
  • If every option is excluded, the request returns an error: 422 insurance.validation.invalid (with every missing field path) if fields the products need are missing, otherwise the providers' decline or availability error.

Option

FieldTypeDescription
quoteIdstringID of the option (prefixed insq_). You send this ID when creating the order.
insuranceTypestringInsurance type.
schemaVersionintegerSchema version.
titlestring or nullThe provider's product name. If null, show the type's name.
premiumAmountintegerPremium, in minor units.
currencystringCurrency, ISO 4217.
premiumCollectedBystringWho collects the premium: MERCHANT when you collect it, PROVIDER when your provider collects it (Provider Collection).
provider.codestringThe provider's code in the Lunixi catalog.
provider.namestringThe provider's name; shown to the buyer.
provider.logoUrlstring or nullThe provider's logo.
provider.connectionIdstringID of your provider connection the quote came from.
basketItemIdsstring[]Basket items the option covers. A separate policy is issued for each item. An empty array on a quote obtained without a basket item.
coverageSummarystring[]Coverage summary; shown to the buyer.
terms.versionstringVersion of the terms.
terms.sha256stringSHA-256 digest of the terms text (64 lowercase hex characters).
underwriterobject or nullThe insurance company that issues the policy; see Provider and insurance company. null if the product does not state a company.
underwriter.codestringThe insurance company's Lunixi code.
underwriter.namestringThe insurance company's name; shown to the buyer.
underwriter.logoUrlstring or nullThe insurance company's logo.
underwriter.disclosureTextstring or nullThe insurance company's information text to show to the buyer, in the language of the request.
underwriterNamestring or nullName of the insurance company. Kept for earlier integrations; in a new integration use underwriter.name.
expiresAtstringEnd of the option's validity, ISO 8601.
statusstringQUOTED: valid. EXPIRED: expired.
paymentIntentIdstring or nullID of the payment if the quote was taken with a payment.
createdAtstringCreation time, ISO 8601.

Showing the options and consent

  • For each option, show the buyer the provider's name, the premium, the coverage summary, the insurance company's name (underwriter.name) and, if present, its information text (underwriter.disclosureText), and the terms version.
  • Do not preselect insurance. The buyer must explicitly confirm that they accept the terms and consent to their details being shared with the provider for the insurance.
  • When creating the order, you send back the terms.version and terms.sha256 values of the option the buyer confirmed exactly as received: Orders › Consent.

Validity

  • Each option is valid until expiresAt. The validity depends on the provider's product.
  • An order cannot be created with an expired option (409 insurance.quote.expired); get a new quote.
  • If the basket or the insured details change, get a new quote. When the order is bound to a payment, the payment's basket is compared with the quoted basket; if they differ, 409 insurance.quote.stale is returned.
  • Only one order can be created from an option.

Retrieving a quote: GET /api/v1/insurance/quotes/{quoteId}

Returns a single option. data is the option object above. An expired option is returned with status: EXPIRED.

source lunixi-sign.sh
REQ_PATH="/api/v1/insurance/quotes/<quoteId>"
lunixi_sign GET "$REQ_PATH"
 
curl "https://api-gateway.lunixi.com$REQ_PATH" \
  -H "X-Key-Id: $LUNIXI_KEY_ID" \
  -H "X-Date: $DATE" \
  -H "X-Nonce: $NONCE" \
  -H "X-Signature: $SIGNATURE"

If the ID is not found or belongs to another account, 404 insurance.quote.not_found is returned.

Contracted facilities: GET /api/v1/insurance/quotes/{quoteId}/facilities

For some insurance types, an option comes with a network of contracted health facilities; for example supplementary health insurance (SUPPLEMENTARY_HEALTH). This endpoint returns an option's contracted facilities in a given province. You can show the facilities to the buyer when they compare plans.

ParameterInRequiredDescription
quoteIdPathYesThe option's quoteId.
cityCodeQueryYesProvince plate code, 01-81.
source lunixi-sign.sh
REQ_PATH="/api/v1/insurance/quotes/<quoteId>/facilities?cityCode=06"
lunixi_sign GET "$REQ_PATH"
 
curl "https://api-gateway.lunixi.com$REQ_PATH" \
  -H "X-Key-Id: $LUNIXI_KEY_ID" \
  -H "X-Date: $DATE" \
  -H "X-Nonce: $NONCE" \
  -H "X-Signature: $SIGNATURE"

The facilities are in the data.items array of the response:

FieldTypeDescription
namestringThe facility's name; shown to the buyer.
cityCodestringThe facility's province, plate code.
{
  "data": {
    "items": [
      { "name": "<facility name>", "cityCode": "06" }
    ]
  }
}
  • The list is read from the option's provider connection on every request and is not stored; it can change over time. Facilities are sorted by name; at most 500 facilities are returned per request. There is no paging.
  • The list can be read even if the option's validity period has ended.
  • If the option has no contracted facility list, 412 insurance.facility.not_supported is returned without sending a request to the provider.
  • If the ID is not found or belongs to another account, 404 insurance.quote.not_found is returned.
  • If cityCode is missing or not two digits, 400 VALIDATION_ERROR is returned; if it is outside 01-81, 422 insurance.validation.invalid is returned with the field path cityCode.

Errors

HTTPcodeWhat to do
400VALIDATION_ERRORFix the request format; a root field that is not in the schema also gets this error.
422insurance.validation.invalidThe type fields, the items or the basket source do not satisfy the rules; the body merged with the items' pre-fill data is validated against the same rules. details.errors[] gives the path (such as tickets[0].departureAt) and the reason of each violation.
422insurance.reference.unknownA reference code is not recognized; take a valid code from the reference list.
412insurance.type.not_availableThis type cannot be offered for this basket. Also returned when a type sold only with a basket item is requested without one. Check the Eligibility list.
412insurance.provider.not_integratedThe integration of the provider in your connection is not available right now.
422insurance.quote.declinedThe provider gave no quote for these details. Retrying with the same details does not change the result.
503insurance.provider.unavailableThe provider cannot be reached right now. Retry later.
404insurance.quote.not_foundThe quote was not found.
412insurance.facility.not_supportedThe option has no contracted facility list: Contracted facilities.

Common codes: Flows › Responses and errors.

Related