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.
| Field | Type | Required | Description |
|---|---|---|---|
insuranceType | string | Yes | Insurance type; the insuranceType from the Eligibility response. |
schemaVersion | integer | No | Schema version of the type. If omitted, the current version is used. |
currency | string | Yes | Currency, ISO 4217. Must equal the payment's currency. |
context.items | array | Basket source | The basket items you will send in the payment; the format is the same as Basket Items, insuranceData included. |
paymentIntentId | string (UUID) | Basket source | ID of a Lunixi payment you created earlier. |
merchantOrderId | string | No | Your own order number, up to 128 characters. For reconciliation; the order inherits this value. |
policyholder | object | By type | The policyholder. Can be completed from the items' pre-fill data: Quote with pre-fill data. |
insured | array | By type | The insured persons. Can be completed from the items' pre-fill data. |
| Type object | array or object | By type | Its 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.itemsorpaymentIntentIdas 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,insuredand 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 withpaymentIntentId,basketItemIdis required. In a quote taken withcontext.items, ifbasketItemIdis omitted the type covers all items it is offered for. - If the items carry
insuranceContextorinsuranceData, the body is completed from these details andbasketItemIdcan 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:
| Field | Type | Description |
|---|---|---|
insuranceType | string | Insurance type. |
schemaVersion | integer | Schema version used in the quote. |
options | array | The options. Their fields are in the option table below. |
excludedOptions | array | Options 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 source | Where the details come from |
|---|---|
paymentIntentId | The 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.items | The 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;
basketItemIdis the item'sid. 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'sbasketItemId. - Type object that is an array (
tickets): if you send it, the quote covers only the tickets you send. A ticket whosebasketItemIdmatches an item is completed with that item's details. - Types with a single object (
device,vehicleand so on): thebasketItemIdin 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 sameidentityTypeandidentityNumberis not repeated and the type's maximum is not exceeded. Each entry of theinsuredlist 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.invalidwith 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_availableis 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:
provideris the provider connection the quote came from.underwriteris the insurance company that issues the policy. The same insurance company can come from different providers;underwriter.codeis the same for the same company whichever provider it comes from.- If the product does not state an insurance company,
underwriterisnull. underwriter.disclosureTextis the insurance company's information text to show to the buyer. It is returned in the language of the request (x-langorAccept-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:
| Field | Type | Description |
|---|---|---|
underwriter | object or null | The option's insurance company; its fields are as in the option table. |
provider.code | string | The provider's code in the Lunixi catalog. |
provider.name | string | The provider's name. |
provider.logoUrl | string or null | The provider's logo. |
provider.connectionId | string | ID of the provider connection of the option. |
errorCode | string | Why the option was excluded; a Lunixi error code (Error Codes). |
errors | array | If 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. excludedOptionsis 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
| Field | Type | Description |
|---|---|---|
quoteId | string | ID of the option (prefixed insq_). You send this ID when creating the order. |
insuranceType | string | Insurance type. |
schemaVersion | integer | Schema version. |
title | string or null | The provider's product name. If null, show the type's name. |
premiumAmount | integer | Premium, in minor units. |
currency | string | Currency, ISO 4217. |
premiumCollectedBy | string | Who collects the premium: MERCHANT when you collect it, PROVIDER when your provider collects it (Provider Collection). |
provider.code | string | The provider's code in the Lunixi catalog. |
provider.name | string | The provider's name; shown to the buyer. |
provider.logoUrl | string or null | The provider's logo. |
provider.connectionId | string | ID of your provider connection the quote came from. |
basketItemIds | string[] | Basket items the option covers. A separate policy is issued for each item. An empty array on a quote obtained without a basket item. |
coverageSummary | string[] | Coverage summary; shown to the buyer. |
terms.version | string | Version of the terms. |
terms.sha256 | string | SHA-256 digest of the terms text (64 lowercase hex characters). |
underwriter | object or null | The insurance company that issues the policy; see Provider and insurance company. null if the product does not state a company. |
underwriter.code | string | The insurance company's Lunixi code. |
underwriter.name | string | The insurance company's name; shown to the buyer. |
underwriter.logoUrl | string or null | The insurance company's logo. |
underwriter.disclosureText | string or null | The insurance company's information text to show to the buyer, in the language of the request. |
underwriterName | string or null | Name of the insurance company. Kept for earlier integrations; in a new integration use underwriter.name. |
expiresAt | string | End of the option's validity, ISO 8601. |
status | string | QUOTED: valid. EXPIRED: expired. |
paymentIntentId | string or null | ID of the payment if the quote was taken with a payment. |
createdAt | string | Creation 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.versionandterms.sha256values 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.staleis 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.
| Parameter | In | Required | Description |
|---|---|---|---|
quoteId | Path | Yes | The option's quoteId. |
cityCode | Query | Yes | Province 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:
| Field | Type | Description |
|---|---|---|
name | string | The facility's name; shown to the buyer. |
cityCode | string | The 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_supportedis returned without sending a request to the provider. - If the ID is not found or belongs to another account,
404 insurance.quote.not_foundis returned. - If
cityCodeis missing or not two digits,400 VALIDATION_ERRORis returned; if it is outside01-81,422 insurance.validation.invalidis returned with the field pathcityCode.
Errors
| HTTP | code | What to do |
|---|---|---|
400 | VALIDATION_ERROR | Fix the request format; a root field that is not in the schema also gets this error. |
422 | insurance.validation.invalid | The 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. |
422 | insurance.reference.unknown | A reference code is not recognized; take a valid code from the reference list. |
412 | insurance.type.not_available | This 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. |
412 | insurance.provider.not_integrated | The integration of the provider in your connection is not available right now. |
422 | insurance.quote.declined | The provider gave no quote for these details. Retrying with the same details does not change the result. |
503 | insurance.provider.unavailable | The provider cannot be reached right now. Retry later. |
404 | insurance.quote.not_found | The quote was not found. |
412 | insurance.facility.not_supported | The option has no contracted facility list: Contracted facilities. |
Common codes: Flows › Responses and errors.
Related
- Orders and Payment Binding: creating an order with an option
- Insurance Types and Schemas: type fields and stages
- Selling Without a Basket Item: quotes without a basket source
- Data Formats: amount, time and identity formats