Skip to main content

Idempotency keys

Networks time out and integration layers retry. To make a retry safe, send an Idempotency-Key header on every POST, PUT, PATCH and DELETE:

Idempotency-Key: b0e7d3c1-8a9f-4d52-93e6-4f1a2b7c9d08

Use one new value per user action (a UUID is ideal) and send the same value on every retry of that action.

Behaviour​

SituationResult
First request with a keyRuns normally. The response is stored for 24 hours.
Retry with the same key and the same bodyThe stored response is returned with its original status and Idempotent-Replayed: true. Nothing runs again.
Same key, different body422 idempotency_key_reused.
Same key while the first request is still running409 idempotency_in_progress with Retry-After: 1.
The first request failed with a 5xxNothing is stored; the retry runs again.
The first request failed with a 4xxThe 4xx is stored and replayed; fix the request and use a new key.
No headerThe request runs normally, with no replay protection from the header.

The key is scoped to your tenant. The comparison covers the method, the path and the body.

RuleValue
Key format1 to 255 printable ASCII characters; otherwise 400 invalid_idempotency_key.
Retention24 hours.
SurfacesOrder orchestration, order operations, group agreements, travel parties, group sales, quote store and repricing.

Example​

The first conversion returns the new purchase order. The retry with the same key returns the same answer, marked as replayed:

POST/order-orchestration/quotations/QT-E419E9088B0D/convertThe retry is answered from the stored response
Request
curl -X POST "$BASE/order-orchestration/quotations/QT-E419E9088B0D/convert" \
-H "Authorization: Bearer $TOKEN" \
-H "X-Request-Id: req-0004" \
-H "Idempotency-Key: 7ac926d7-5cf4-478b-abdc-a05e8298b52c" \
-H "Content-Type: application/json" \
-d '{
"frozen": {
"quoteRef": "Q-2027-58213",
"quoteVersion": 2,
"frozenAt": "2026-11-02T09:04:00Z",
"currency": "EUR",
"market": "IT",
"channel": "web",
"configVersion": 9,
"storeVersion": 14,
"customerRef": "CUST-20419",
"lines": [
{
"lineRef": "q-line-1",
"productType": "cruise",
"productCode": "MED7-2027-04-12",
"description": "7-night Western Mediterranean, balcony cabin, 2 guests",
"quantity": 1,
"passengerIds": [
"PAX-01",
"PAX-02"
],
"amountMinor": 238000,
"offerId": "ALL-INCLUSIVE-2027",
"promotionIds": [
"EARLY-BOOKING-10"
],
"explanation": [
{
"layer": "base",
"ruleId": "base-balcony",
"mode": "select",
"basis": "passenger",
"input": 0,
"contribution": 264400,
"runningTotal": 264400,
"source": {
"kind": "store",
"version": 14,
"timestamp": "2026-10-30T00:00:00Z"
},
"flag": "public",
"reason": {
"key": "layer.base",
"params": {}
}
},
{
"layer": "promotion",
"ruleId": "EARLY-BOOKING-10",
"mode": "adjust",
"basis": "booking",
"input": 264400,
"contribution": -26400,
"runningTotal": 238000,
"source": {
"kind": "store",
"version": 14,
"timestamp": "2026-10-30T00:00:00Z"
},
"flag": "public",
"reason": {
"key": "layer.promotion",
"params": {}
}
}
],
"sellingConditions": {
"refundable": true,
"depositPercent": 20
}
},
{
"lineRef": "q-line-2",
"productType": "beverage",
"productCode": "DRINKS-CLASSIC-7N",
"description": "Classic drinks package, 7 nights",
"quantity": 2,
"passengerIds": [
"PAX-01",
"PAX-02"
],
"amountMinor": 30800,
"offerId": "ALL-INCLUSIVE-2027",
"promotionIds": [],
"explanation": []
}
],
"promotions": [
{
"promotionId": "EARLY-BOOKING-10",
"version": 3,
"postBookingPolicy": "keep"
}
],
"totalMinor": 268800
},
"actorRef": "CUST-20419",
"moment": "booking",
"booker": {
"kind": "customer",
"ref": "CUST-20419",
"displayName": "Giulia Rossi"
},
"payer": {
"kind": "customer",
"ref": "CUST-20419",
"displayName": "Giulia Rossi"
}
}'
Response
HTTP/1.1 200
X-Request-Id: req-0004
Idempotent-Replayed: true
{
"quotation": {
"quote": {
"offerId": "ALL-INCLUSIVE-2027",
"currency": "EUR",
"quoteRef": "Q-2027-58213",
"totalMinor": 268800,
"validUntil": "2026-11-09T23:59:59Z",
"promotionIds": [
"EARLY-BOOKING-10"
],
"quoteVersion": 2
},
"market": "IT",
"status": "converted",
"tripId": "TRP-B2BD5A9771E4",
"channel": "web",
"intentId": "INT-E7814BE45E5F",
"agencyRef": null,
"createdAt": "2026-11-02T09:05:37.000Z",
"createdBy": {
"kind": "customer",
"actorRef": "CUST-20419"
},
"updatedAt": "2026-11-02T09:06:51.000Z",
"conversion": {
"poId": "PO-5BEE8AAD2A57",
"convertedAt": "2026-11-02T09:06:51.000Z",
"convertedBy": "CUST-20419"
},
"passengers": 2,
"customerRef": "CUST-20419",
"productCode": "MED7-2027-04-12",
"quotationRef": "QT-E419E9088B0D",
"lastAccessedAt": "2026-11-02T09:06:14.000Z"
},
"purchaseOrder": {
"poId": "PO-5BEE8AAD2A57",
"type": "standard",
"lines": [
{
"lineId": "L-A610167BDD4D",
"status": {
"billing": "not_billed",
"payment": "not_due",
"commercial": "booked",
"fulfilment": "requested"
},
"offerId": "ALL-INCLUSIVE-2027",
"currency": "EUR",
"quantity": 1,
"ownership": {
"ruleId": "anchor-reservation",
"process": "create"
},
"amountMinor": 238000,
"description": "7-night Western Mediterranean, balcony cabin, 2 guests",
"explanation": [
{
"flag": "public",
"mode": "select",
"basis": "passenger",
"input": 0,
"layer": "base",
"reason": {
"key": "layer.base",
"params": {}
},
"ruleId": "base-balcony",
"source": {
"kind": "store",
"version": 14,
"timestamp": "2026-10-30T00:00:00Z"
},
"contribution": 264400,
"runningTotal": 264400
},
{
"flag": "public",
"mode": "adjust",
"basis": "booking",
"input": 264400,
"layer": "promotion",
"reason": {
"key": "layer.promotion",
"params": {}
},
"ruleId": "EARLY-BOOKING-10",
"source": {
"kind": "store",
"version": 14,
"timestamp": "2026-10-30T00:00:00Z"
},
"contribution": -26400,
"runningTotal": 238000
}
],
"externalRef": "RSV-66D6FC0F-000001",
"productCode": "MED7-2027-04-12",
"productType": "cruise",
"passengerIds": [
"PAX-01",
"PAX-02"
],
"promotionIds": [
"EARLY-BOOKING-10"
],
"quoteLineRef": "q-line-1",
"sourceSystem": "reservation",
"sellingConditions": {
"refundable": true,
"depositPercent": 20
}
},
{
"lineId": "L-BB4F731FB7C8",
"status": {
"billing": "not_billed",
"payment": "not_due",
"commercial": "booked",
"fulfilment": "requested"
},
"offerId": "ALL-INCLUSIVE-2027",
"currency": "EUR",
"quantity": 2,
"ownership": {
"ruleId": "beverage-phase1",
"process": "create"
},
"amountMinor": 30800,
"description": "Classic drinks package, 7 nights",
"explanation": [],
"productCode": "DRINKS-CLASSIC-7N",
"productType": "beverage",
"passengerIds": [
"PAX-01",
"PAX-02"
],
"promotionIds": [],
"quoteLineRef": "q-line-2",
"sourceSystem": "onboard"
}
],
"payer": {
"ref": "CUST-20419",
"kind": "customer",
"displayName": "Giulia Rossi"
},
"terms": {},
"booker": {
"ref": "CUST-20419",
"kind": "customer",
"displayName": "Giulia Rossi"
},
"market": "IT",
"moment": "booking",
"origin": {
"channel": "web",
"actorRef": "CUST-20419"
},
"status": {
"billing": "not_billed",
"payment": "not_due",
"commercial": "booked",
"fulfilment": "requested"
},
"tripId": "TRP-B2BD5A9771E4",
"channel": "web",
"version": 3,
"currency": "EUR",
"sequence": 1,
"createdAt": "2026-11-02T09:06:51.000Z",
"revisions": [],
"updatedAt": "2026-11-02T09:06:51.000Z",
"totalMinor": 268800,
"attribution": {},
"fullPayment": false,
"finalisation": {
"at": "2026-11-02T09:06:51.000Z",
"channel": "web"
},
"quotationRef": "QT-E419E9088B0D",
"partiesLocked": true,
"frozenConditions": {
"document": {
"lines": [
{
"lineRef": "q-line-1",
"offerId": "ALL-INCLUSIVE-2027",
"quantity": 1,
"amountMinor": 238000,
"description": "7-night Western Mediterranean, balcony cabin, 2 guests",
"explanation": [
{
"flag": "public",
"mode": "select",
"basis": "passenger",
"input": 0,
"layer": "base",
"reason": {
"key": "layer.base",
"params": {}
},
"ruleId": "base-balcony",
"source": {
"kind": "store",
"version": 14,
"timestamp": "2026-10-30T00:00:00Z"
},
"contribution": 264400,
"runningTotal": 264400
},
{
"flag": "public",
"mode": "adjust",
"basis": "booking",
"input": 264400,
"layer": "promotion",
"reason": {
"key": "layer.promotion",
"params": {}
},
"ruleId": "EARLY-BOOKING-10",
"source": {
"kind": "store",
"version": 14,
"timestamp": "2026-10-30T00:00:00Z"
},
"contribution": -26400,
"runningTotal": 238000
}
],
"productCode": "MED7-2027-04-12",
"productType": "cruise",
"passengerIds": [
"PAX-01",
"PAX-02"
],
"promotionIds": [
"EARLY-BOOKING-10"
],
"sellingConditions": {
"refundable": true,
"depositPercent": 20
}
},
{
"lineRef": "q-line-2",
"offerId": "ALL-INCLUSIVE-2027",
"quantity": 2,
"amountMinor": 30800,
"description": "Classic drinks package, 7 nights",
"explanation": [],
"productCode": "DRINKS-CLASSIC-7N",
"productType": "beverage",
"passengerIds": [
"PAX-01",
"PAX-02"
],
"promotionIds": []
}
],
"market": "IT",
"channel": "web",
"currency": "EUR",
"frozenAt": "2026-11-02T09:04:00Z",
"quoteRef": "Q-2027-58213",
"promotions": [
{
"version": 3,
"promotionId": "EARLY-BOOKING-10",
"postBookingPolicy": "keep"
}
],
"totalMinor": 268800,
"customerRef": "CUST-20419",
"quoteVersion": 2,
"storeVersion": 14,
"configVersion": 9
},
"frozenAt": "2026-11-02T09:04:00Z",
"quoteRef": "Q-2027-58213",
"quoteVersion": 2,
"storeVersion": 14,
"configVersion": 9
}
}
}

The same key with a different body is refused:

POST/order-orchestration/quotations/QT-93DA8CB4947D/convertThe same Idempotency-Key with a different body
Request
curl -X POST "$BASE/order-orchestration/quotations/QT-93DA8CB4947D/convert" \
-H "Authorization: Bearer $TOKEN" \
-H "X-Request-Id: req-0036" \
-H "Idempotency-Key: 0cb8a221-85fb-4894-af64-4d20c65f9867" \
-H "Content-Type: application/json" \
-d '{
"frozen": {
"quoteRef": "Q-2027-58213",
"quoteVersion": 2,
"frozenAt": "2026-11-02T09:04:00Z",
"currency": "EUR",
"market": "IT",
"channel": "web",
"configVersion": 9,
"storeVersion": 14,
"customerRef": "CUST-20419",
"lines": [
{
"lineRef": "q-line-1",
"productType": "cruise",
"productCode": "MED7-2027-04-12",
"description": "7-night Western Mediterranean, balcony cabin, 2 guests",
"quantity": 1,
"passengerIds": [
"PAX-01",
"PAX-02"
],
"amountMinor": 238000,
"offerId": "ALL-INCLUSIVE-2027",
"promotionIds": [
"EARLY-BOOKING-10"
],
"explanation": [
{
"layer": "base",
"ruleId": "base-balcony",
"mode": "select",
"basis": "passenger",
"input": 0,
"contribution": 264400,
"runningTotal": 264400,
"source": {
"kind": "store",
"version": 14,
"timestamp": "2026-10-30T00:00:00Z"
},
"flag": "public",
"reason": {
"key": "layer.base",
"params": {}
}
},
{
"layer": "promotion",
"ruleId": "EARLY-BOOKING-10",
"mode": "adjust",
"basis": "booking",
"input": 264400,
"contribution": -26400,
"runningTotal": 238000,
"source": {
"kind": "store",
"version": 14,
"timestamp": "2026-10-30T00:00:00Z"
},
"flag": "public",
"reason": {
"key": "layer.promotion",
"params": {}
}
}
],
"sellingConditions": {
"refundable": true,
"depositPercent": 20
}
},
{
"lineRef": "q-line-2",
"productType": "beverage",
"productCode": "DRINKS-CLASSIC-7N",
"description": "Classic drinks package, 7 nights",
"quantity": 2,
"passengerIds": [
"PAX-01",
"PAX-02"
],
"amountMinor": 30800,
"offerId": "ALL-INCLUSIVE-2027",
"promotionIds": [],
"explanation": []
}
],
"promotions": [
{
"promotionId": "EARLY-BOOKING-10",
"version": 3,
"postBookingPolicy": "keep"
}
],
"totalMinor": 268800
},
"actorRef": "CUST-20419",
"moment": "pre_trip"
}'
Response
HTTP/1.1 422
X-Request-Id: req-0036
{
"error": "idempotency_key_reused",
"code": "idempotency_key_reused",
"message": "this Idempotency-Key was used for a different request",
"requestId": "req-0036"
}

Business keys in the body​

Some writes also accept an idempotencyKey field in the body: purchase order creation, payments, changes, service-recovery cases, and group agreement receipts, settlement and cancellations. The body key is a business deduplication key: a repeat returns the existing record (for payments, with status 200 and idempotent: true) even after the 24 hours of the header.

Send the same value in both when both exist. On POST /oms-ops/changes and POST /oms-ops/service-recovery/cases, a header and a body key that differ are refused with 400 idempotency_key_mismatch.

Conversions and handovers are also idempotent by nature: converting the same quotation with the same frozen conditions again returns the same purchase order.