Insurance
Reference
Webhook Events

Webhook Events

When the outcome of your insurance orders changes, Lunixi sends insurance.* events to your endpoint: the policy was issued, could not be issued, its document is ready, it was cancelled, a premium refund is required or completed; a claim was passed to the provider or could not be passed; a lead was passed to the provider. The events are the same on the Checkout Form path and on the API path.

Delivery, signature verification and retries are the same for all products: Webhooks.

Events

EventWhen it is sent
insurance.policy.issuedThe order's policies were issued by the provider.
insurance.policy.failedThe policy could not be issued, finally, or the policy was not requested because the premium could not be collected. The reason is in data.errorCode.
insurance.refund.requiredThe premium was collected but the policy could not be issued, finally; the premium has to be refunded to the buyer.
insurance.policy.document_readyThe documents of the order's issued policies can be retrieved.
insurance.policy.cancelledThe provider finalized the cancellation of all policies of the order.
insurance.refund.completedThe premium refund was completed.
insurance.claim.submittedA claim was passed to the provider and the provider recorded it.
insurance.claim.failedA claim was not accepted by the provider or did not reach the provider. The reason is in data.claim.errorCode.
insurance.lead.submittedA lead was passed to the provider and the provider received it.

insurance.policy.issued

Sent when the order's policies are issued. data.policyStatus becomes ISSUED; the policy numbers are in data.policies[].policyNumber.

The document may not be ready yet at this point (documentStatus: PENDING). When it is ready, insurance.policy.document_ready is sent as well.

The policy outcome may be finalized late. If insurance.policy.failed (and insurance.refund.required) was sent for an order first and the refund has not started yet, insurance.policy.issued is also sent when the policy is issued later. In that case data.refundStatus is NONE; the premium refund is no longer required.

insurance.policy.failed

Sent in three cases:

Casedata
The policy could not be issued, finally.policyStatus: FAILED_FINAL. errorCode carries the reason, e.g. insurance.policy.issue_failed or insurance.policy.issue_deadline_passed.
The payment was cancelled, expired or finally failed before it was captured.collectionStatus: FAILED, policyStatus: NOT_REQUESTED, errorCode: insurance.premium.not_captured. No refund is needed because no premium was taken.
The provider collects the premium and declined the charge.collectionStatus: FAILED, policyStatus: NOT_REQUESTED, errorCode: insurance.payment.declined. Your payment stays valid. See Provider Collection.

If the premium was collected, insurance.refund.required is sent at the same time.

insurance.refund.required

Sent when the premium was collected but the policy could not be issued, finally. On the order, the policy becomes FAILED_FINAL and the refund REQUIRED. errorCode shows why the policy could not be issued.

When you receive the event, read the order from the order endpoint:

  • If refundStatus is PENDING or REFUNDED, the refund has started; insurance.refund.completed is sent when it completes.
  • If refundStatus is REQUIRED, refund the premium with the premium refund endpoint. If you collected the premium outside Lunixi, make the refund through your own channel and report it with the same endpoint.

The premium refund request can be repeated: if the refund has already started, the order is returned as is.

insurance.policy.document_ready

Sent when the documents of the order's issued policies are verified with the provider. data.documentStatus becomes AVAILABLE.

Download the document from data.policies[].documentUrl. This address is the Policy Document endpoint; you sign the request with your API key like your other API requests. The address does not carry any authorization by itself, and the document is not stored at Lunixi.

insurance.policy.cancelled

Sent when the provider finalizes the cancellation of all policies of the order. data.policyStatus becomes CANCELLED. The document of a cancelled policy cannot be retrieved; documentUrl is an empty string.

Cancelling the policy does not refund the premium. The premium refund is a separate step, and insurance.refund.completed is sent when it completes. See Cancellation and Premium Refund.

insurance.refund.completed

Sent when the premium refund is completed. data.refundStatus becomes REFUNDED.

  • If the premium was collected in a Lunixi payment, the event is sent when the refund is made from the payment.
  • If you collected the premium outside Lunixi, the event is sent when you report the refund with the premium refund endpoint.

insurance.claim.submitted

Sent when a claim reaches the provider and the provider records it. The claim is in data.claim; data.claim.status becomes SUBMITTED. You can get the provider's claim document from the claim document endpoint.

The event does not carry the assessment result of the claim; the assessment is done by the insurance company.

insurance.claim.failed

Sent when a claim is not accepted by the provider or does not reach the provider. data.claim.status becomes FAILED; the reason is in data.claim.errorCode:

data.claim.errorCodeMeaning
insurance.claim.rejectedThe provider rejected the claim.
insurance.provider.unavailableThe claim did not reach the provider.

If needed, you can file a new claim for the same policy: Claims.

insurance.lead.submitted

Sent when a lead reaches the provider and the provider receives it. The lead is in data.lead; data.lead.status becomes SUBMITTED. Because a lead is not linked to an order, the data of this event does not carry order fields: Lead event payload.

The event does not carry the provider's steps after the lead (contacting the buyer, an offer).

Cases without an event

No event is sent for the following cases. Track them on the order endpoint:

CaseOn the order
A quote or an order was createdThe order appears in the order list.
The provider rejected the cancellation requestThe policy stays in force; errorCode: insurance.policy.cancel_failed.
The premium refund was rejectedrefundStatus: FAILED, refundErrorCode: insurance.refund.rejected.
The policy document could not be verifieddocumentStatus: FAILED. The issued policy stays valid; you can still request the document from the Policy Document endpoint.
The outcome of a claim is not finalThe claim shows status: UNKNOWN on the claim endpoint. When the outcome is final, insurance.claim.submitted or insurance.claim.failed arrives.
The outcome of a lead is not known or the lead failedThe lead shows status: UNKNOWN or FAILED on the lead endpoint. The outcome is also returned in the response to the lead request.

Delivery structure

The delivery body is an envelope; the order's fields are under data.

Envelope

FieldMeaning
idEvent ID; the same value as the x-lunixi-event-id header and data.eventId.
typeEvent type, e.g. insurance.policy.issued.
organizationIdYour organization.
productCodeINSURANCE_SERVICE
environmentTEST or LIVE; the environment of the order's provider connection. See Subscription.
eventVersionEvent version; 1 today.
schemaVersionVersion of the data schema; v1 today.
createdAtWhen the event occurred.
dataThe order's fields; see below.

The envelope may contain fields not in this table; base your code only on the fields documented here.

data

data carries the order state after the transition the event describes. The data of the lead event is different: Lead event payload.

FieldTypeDescription
eventIdstringEvent ID; the same as id in the envelope.
eventTypestringEvent type; the same as type in the envelope.
merchantIdstringYour organization; the same as organizationId in the envelope.
insuranceOrderIdstringOrder ID (inso_…). The same value as orderId on the order endpoint.
paymentIntentIdstring or nullThe Lunixi payment the order is bound to.
merchantOrderIdstring or nullYour own order number.
insuranceTypestringInsurance type, e.g. TICKET_CANCELLATION. See Insurance Types.
premiumCollectedBystringWho collected the premium: MERCHANT when you collect it, PROVIDER when your provider collects it (Provider Collection).
providerobjectThe provider that issued the policy: code, name, logoUrl (string or null) and your connection's ID connectionId. For information.
statusstringOverall status; derived from the four axes. See Concepts › Overall status.
collectionStatusstringCollection axis.
policyStatusstringPolicy axis.
refundStatusstringRefund axis.
documentStatusstringDocument axis.
premiumAmountintegerPremium, in minor units (kuruş).
currencystringCurrency, ISO 4217.
policiesarrayPolicies per basket item; fields below. An empty array if no policy was created.
errorCodestring or nullPresent only in insurance.policy.failed and insurance.refund.required: the Lunixi code of the error. Meaning of the codes: Error Codes.
claimobjectPresent only in insurance.claim.* events: the claim the event is about; fields below.
createdAtstringWhen the order was created. The time of the event is createdAt in the envelope.

Values of the status axes: Concepts › Order statuses.

policies[]:

FieldTypeDescription
policyIdstringPolicy ID (insp_…).
basketItemIdstringThe basket item the policy insures.
policyNumberstring or nullThe number on the policy document. null until the policy is issued.
policyStatusstringStatus of this policy.
documentStatusstringDocument status of this policy.
documentUrlstringIf the policy is in force (ISSUED or CANCEL_PENDING), the full address of the Policy Document endpoint; otherwise an empty string.

claim (only in insurance.claim.* events):

FieldTypeDescription
claimIdstringClaim ID (insclm_…).
policyIdstringThe policy the claim was filed for (insp_…).
statusstringStatus of the claim: SUBMITTED or FAILED.
incidentAtstringTime of the incident the claim is about, ISO 8601.
documentKindsstring[]Types of the documents sent with the claim.
errorCodestring or nullSet only in the insurance.claim.failed event: the Lunixi code of the reason.
submittedAtstring or nullThe time it was confirmed that the provider recorded the claim.
createdAtstringWhen the claim was created.

In claim events, the order's other fields carry the order's status at the time of the event. The document and the provider's claim reference are not included in the payload.

Lead event payload

The data of the insurance.lead.submitted event carries only these fields:

FieldTypeDescription
eventIdstringEvent ID; the same as id in the envelope.
eventTypestringEvent type: insurance.lead.submitted.
merchantIdstringYour organization; the same as organizationId in the envelope.
leadobjectThe lead the event is about; fields below.
createdAtstringWhen the lead was created. The time of the event is the envelope's createdAt.

lead:

FieldTypeDescription
leadIdstringThe lead ID (insl_…).
insuranceTypestringThe lead type, e.g. CARGO_TRANSIT.
schemaVersionintegerThe version of the lead schema the lead was validated against.
statusstringThe lead status: SUBMITTED.
submittedAtstringWhen the provider received the lead.
createdAtstringWhen the lead was created.

The lead body, the note and personal data, the provider's name and the lead reference are not included in the payload. Use the retrieve endpoint for the lead's masked view.

In webhooks, fields without a value come as null; the field is still present in the body. Personal data and the provider's own references are not included in the payload.

Subscription

To receive the events, create a webhook endpoint for the insurance product:

FieldValue
productCodeINSURANCE_SERVICE
eventTypesThe events you want, e.g. ["insurance.policy.issued", "insurance.refund.required"]; ["insurance.*"] for all insurance events
environmentA TEST endpoint receives the events of orders whose provider connection is in the Test environment; a LIVE endpoint those whose connection is in the Live environment.
curl -X POST "https://api-gateway.lunixi.com/api/v1/organizations/$ORG_ID/webhook-endpoints" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Insurance events — test",
    "url": "https://merchant.example.com/webhooks/lunixi",
    "productCode": "INSURANCE_SERVICE",
    "environment": "TEST",
    "secretRef": "vault:<secretId>",
    "eventTypes": ["insurance.*"]
  }'

The event's environment is set by the order's provider connection, not by your API key. When testing, check your connection's environment: Testing › What decides the environment.

Creating the endpoint, the signing secret and delivery history: Webhook Setup.

Signature, retries and deduplication

Verify the signature on every delivery; the signature format and retry policy are the same for all products: Webhooks.

  • Delivery is at least once. The same event may arrive more than once. Process the event idempotently by x-lunixi-event-id. The same event carries the same ID on every delivery; this value is also the same as data.eventId.
  • Do not rely on the order. A retried delivery may arrive after a later event. Derive the order's latest state from the status axes in data, not from the order of events. When in doubt, read the order from the order endpoint.
  • Respond to the event quickly. Verify the signature, write the event to your own queue and return 2xx. Do work such as downloading the document after the response.

Using the webhook with the order endpoint

The webhook is the fast way to learn the order's outcome; it is not the only source. If your endpoint is unreachable for a while, or the status changed through a path without an event (table above), read the order from the order endpoint. data.insuranceOrderId from the webhook is the same as orderId on the order endpoint.

Using the webhook with the order endpointData flow: the webhook is the fast source and the order endpoint the source when an event was missed or not sent; in both cases you derive the latest state from the status axes rather than the order of events and update your record by order ID.FASTIF MISSEDUPDATEWebhookx-lunixi-event-idOrder endpointGET …/orders/{orderId}Read the axesnot the event orderYour recordinsuranceOrderId = orderIdLEGENDSOURCELATEST STATEYOUR SYSTEM
Delivery is at least once and not ordered: deduplicate by x-lunixi-event-id and take the latest state from the status axes in data.

Related