API Path
If you use your own payment form, you offer insurance to your buyer in your own interface. You get eligibility and quotes from the API and create an order with the option the buyer selected. The policy is issued after the premium is collected.
If you use the Lunixi payment form, use the Checkout Form path instead of this section. If you take the payment outside Lunixi, step-by-step guide: Insurance-Only Integration.
Before you start
- Insurance and the API path must be enabled on your account. Your API key must have access to the insurance product. The insurance-only flow does not require the payment product.
- Connect your provider in the panel. On the POS Center > Insurance page, add a connection for the provider you have an agreement with and enable the product you will offer in that connection.
- Turn insurance on and choose the type to offer. In the Insurance product in the panel's left menu, on the General screen, turn on Insurance on and select at least one API usage mode: API — linked to a Lunixi payment if you take the payment through Lunixi, API — external collection if you take it outside Lunixi. On the Insurance Types screen, enable the type you will offer and save. Details: Insurance Menu › General, Insurance Menu › Insurance Types.
- Choose who collects the premium. When enabling the product, answer Who collects the premium according to your agreement with your provider. The two flows below are for orders whose premium you collect (You collect). If the provider collects the premium (Provider collects): Provider Collection. Collection methods: Insurance › Who collects the premium.
Test connection and test key: Testing.
Two flows
You use one of two flows depending on how you collect the premium:
| Flow | When | Premium |
|---|---|---|
| Linked to a Lunixi payment | You take the payment with Lunixi | You add the premium to your payment's basket as a separate item. The buyer pays for the product and the insurance in one payment. |
| Insurance only | You take the payment outside Lunixi, or you sell insurance only | You collect the premium through your own channel and report the payment to the API. Guide: Insurance-Only Integration. |
The quote and order steps are the same in both flows. They differ in how the premium is collected: Premium and Payment.
For insurance types not linked to a basket item, the quote is obtained without a basket item; steps and collection: Selling Without a Basket Item.
Insurance types that do not return a quote have no quote or order; you pass the buyer's details to your provider as a lead: Leads.
Flow linked to a Lunixi payment
… stands for /api/v1/insurance. The ID of the premium item in the basket is the order ID; you do not call issue-policy in this flow.Check eligibility
Find out which insurance types are offered for the basket items you will send in the payment: Eligibility.
Get a quote
Get a quote with the buyer's details and the basket items. Show the buyer the options, the premium, the coverage summary and the terms: Quotes.
Create an order
When the buyer confirms an option, create an order with that option and report the buyer's consent: Orders and Payment Binding.
Create the payment with the premium item
Create the payment with the insured items and a premium item carrying the order ID, then bind the order to the payment: Premium and Payment.
Track the policy
When the payment is captured, the policy is requested automatically. Track the order status through the order endpoint; when the policy is issued, get its document: Policy Document.
Insurance-only flow
… stands for /api/v1/insurance. Lunixi forwards your payment notification to your provider through your connection; then you request the policy.In this flow you report the payment to Lunixi; Lunixi forwards the notification to your provider through your connection. Then you request the policy. Details: Premium and Payment › Premium collected outside Lunixi. Every step including documents, cancellation, refunds and webhooks, with an end-to-end example: Insurance-Only Integration.
If you already have the buyer's details
You can send the details the quote needs (insured person, IMEI, booking code, plate and so on) in the basket item's insuranceData field, and the non-personal details in its insuranceContext field: Basket Items › Insurance pre-fill data.
- The eligibility response shows, per offer, which fields were provided (
providedFields, personal values masked), what was filled from the context (prefill) and whether the quote can be obtained without further fields (quoteReady): Eligibility › Pre-fill data and the automatic quote. - In the quote request you send only the missing fields; the body is completed from the items' details. In a quote taken with
paymentIntentIdthe body may even be empty: Quote › Quote with pre-fill data. insuranceDataincontext.itemsis not stored; it is used only in that request.
Endpoints
The base address is https://api-gateway.lunixi.com. Authentication, request and response fields, errors and webhook events of each endpoint: Endpoint Reference.
| Method | Path | Idempotency-Key |
|---|---|---|
GET | /api/v1/insurance/products | — |
POST | /api/v1/insurance/products | — |
GET | /api/v1/insurance/reference/{kind} | — |
POST | /api/v1/insurance/quotes | Optional |
GET | /api/v1/insurance/quotes/{quoteId} | — |
GET | /api/v1/insurance/quotes/{quoteId}/facilities | — |
POST | /api/v1/insurance/orders | Required |
GET | /api/v1/insurance/orders | — |
GET | /api/v1/insurance/orders/{orderId} | — |
POST | /api/v1/insurance/orders/{orderId}/bind-payment | Optional |
POST | /api/v1/insurance/orders/{orderId}/confirm-payment | Required |
POST | /api/v1/insurance/orders/{orderId}/issue-policy | Required |
POST | /api/v1/insurance/orders/{orderId}/pay | Required |
POST | /api/v1/insurance/orders/{orderId}/cancel | Required |
POST | /api/v1/insurance/orders/{orderId}/refund-premium | Required |
GET | /api/v1/insurance/policies/{policyId}/document | — |
GET | /api/v1/insurance/policies/{policyId}/receipt | — |
GET | /api/v1/insurance/policies/{policyId}/certificate | — |
POST | /api/v1/insurance/policies/{policyId}/claims | Required |
GET | /api/v1/insurance/claims | — |
GET | /api/v1/insurance/claims/{claimId} | — |
GET | /api/v1/insurance/claims/{claimId}/document | — |
POST | /api/v1/insurance/leads | Required |
GET | /api/v1/insurance/leads | — |
GET | /api/v1/insurance/leads/{leadId} | — |
GET | /api/v1/insurance/reconciliation/summary | — |
GET | /api/v1/insurance/reconciliation/orders | — |
GET | /api/v1/insurance/reconciliation/export | — |
Authentication
The insurance endpoints accept only requests signed with your API key. No Authorization header is needed; a Bearer access token or a panel session does not authenticate these endpoints. A request without the signature headers gets 401 AUTH_HEADERS_MISSING.
The only exception is the provider collection endpoint (/pay): because it can carry card data, it also requires a Bearer access token in addition to the signature. See Provider Collection › Authentication.
| Header | Value | Required |
|---|---|---|
X-Key-Id | Your key ID (kid) | Yes |
X-Date | ISO 8601 timestamp; within ±5 minutes of server time | Yes |
X-Nonce | A unique value per request; single use | Yes |
Digest | SHA-256=<base64> digest of the body | On requests with a body |
X-Signature | Base64 Ed25519 signature of the canonical string | Yes |
Canonical string and signing rules: Authentication. The second signed line is the full request path including the query string, if any. Send the body as compact JSON and compute Digest from the body you send.
The cURL examples in this section use the following shell helper:
# lunixi-sign.sh — requires OpenSSL 3.0+.
# Usage: source lunixi-sign.sh
# lunixi_sign GET "/api/v1/insurance/orders?limit=25"
# lunixi_sign POST "/api/v1/insurance/quotes" "$BODY"
LUNIXI_KEY_ID="mk_test_..."
LUNIXI_KEY_FILE="lunixi-signing.key"
lunixi_sign() {
local method="$1" req_path="$2" body="${3-}"
DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
NONCE=$(openssl rand -hex 16)
if [ -n "$body" ]; then
DIGEST="SHA-256=$(printf '%s' "$body" | openssl dgst -sha256 -binary | base64)"
printf '%s\n%s\nX-Date:%s\nX-Nonce:%s\nDigest:%s' "$method" "$req_path" "$DATE" "$NONCE" "$DIGEST" > canonical.txt
else
DIGEST=""
printf '%s\n%s\nX-Date:%s\nX-Nonce:%s' "$method" "$req_path" "$DATE" "$NONCE" > canonical.txt
fi
SIGNATURE=$(openssl pkeyutl -sign -inkey "$LUNIXI_KEY_FILE" -rawin -in canonical.txt | base64 | tr -d '\n')
}Authentication and access errors:
| HTTP | code | What to do |
|---|---|---|
401 | AUTH_HEADERS_MISSING, INVALID_DATE, NONCE_REPLAY, INVALID_KID, DIGEST_MISSING, INVALID_DIGEST, INVALID_SIGNATURE | Check the signature headers and the canonical string. |
403 | PRODUCT_NOT_ENABLED | The insurance product is not enabled on your account or key; see PRODUCT_NOT_ENABLED. |
Idempotency-Key
The endpoints that create an order or change its state make the Idempotency-Key header required: orders, confirm-payment, issue-policy, pay, cancel, refund-premium. The endpoint that files a claim (policies/{policyId}/claims) and the endpoint that submits a lead (leads) also require the key. quotes and bind-payment accept the header as optional.
- The key is a printable ASCII value of 8-200 characters without spaces. A missing or malformed key returns
400 VALIDATION_ERROR. - Derive the key from your operation and, after a timeout or a
5xx, repeat the request with the same key and the same body. If the order was created on the first attempt, no second order is created; the recorded order is returned. - If you use the same key with a different order request, you get
409 insurance.idempotency.conflict. Generate a new key for a new order. - Operations on an order are also naturally repeatable: binding the same payment again, reporting the same payment ID again, or requesting the policy, the cancellation or the refund again returns the order as it is.
Responses and errors
A successful response body is under data. On list endpoints the pagination information is in pageInfo; see Pagination.
An error response carries status: "failure", code, message, requestId and details. Branch in your code on code, not on message; message depends on the language. Envelope details: Errors.
Codes that can be returned by every insurance endpoint:
| HTTP | code | Meaning and what to do |
|---|---|---|
400 | VALIDATION_ERROR | The request format is invalid or an undefined field was sent. Fix the fields in details.errors. |
422 | insurance.validation.invalid | The request does not satisfy the rules. details.errors[] carries field and reason for each violation; all violations are returned in one response. |
409 | insurance.idempotency.conflict | The same Idempotency-Key was used with a different request. |
503 | insurance.dependency.unavailable | The request cannot be completed right now. Retry later with the same request and the same Idempotency-Key. |
500 | insurance.internal.integrity | The request cannot be completed right now. Retry later; if it persists, contact support with the requestId. |
Endpoint-specific codes are listed on each endpoint page. 4xx errors do not resolve by retrying the same request; fix the request first.
Personal data you send is not written to error responses. Responses contain only Lunixi IDs; the provider's references and error codes are not included.