Skip to content
Linra Omni Developer Docs

Create scent order

Create a scent order from the caller's own open cart.

Scent Orders

POST/api/v1/scent/orders

Order LINES are never part of this request — they are taken from the partner’s (optionally customerRef-scoped) open cart. Call GET /api/v1/scent/cart/{customerRef}/checkout-preview to price the cart, then POST /api/v1/scent/cart/{customerRef}/price-lock to take a price lock: lockId is REQUIRED here — every order is placed against a frozen price lock and charged the locked prices; live-priced create is no longer allowed. See the Cart preview & price locks guide. A price lock is SINGLE-USE: reusing an already-consumed lockId is rejected with 409 CONFLICT_PRICE_LOCK_ALREADY_USED, carrying the order it was already used for. A repeat externalReference against an order that already completed is REJECTED, not replayed — see the Idempotency guide. The created order is then read via GET /api/v1/scent/orders/{orderId} (the Location header points there; orderId == this response’s own id).

Body parameters

externalReferencestringRequired

Your own idempotency key — see the Idempotency guide.

shippingAddress.recipientstringRequired
shippingAddress.line1stringRequired
shippingAddress.line2string
shippingAddress.citystringRequired

The delivery-zone key — checked against a “within Riyadh” allowlist that drives the order-level shipping fee.

shippingAddress.nationalAddressstringRequired

The customer’s KSA national short address code (e.g. “RAKB2837”). MANDATORY — the required basis for delivery-zone determination alongside city.

shippingAddress.regionstring
shippingAddress.postalCodestring
shippingAddress.countryCodestringRequired

ISO 3166-1 ALPHA-3 country code (e.g. “SAU”) — validated against the real alpha-3 code set; an unknown code is rejected VALIDATION_INVALID_COUNTRY_CODE.

shippingAddress.phonestringRequired
customerRefstring

Must match the customerRef used when building the cart being checked out. Omit for the partner-level cart.

lockIdstring (uuid)Required

REQUIRED. The id returned by a prior POST /api/v1/scent/cart/{customerRef}/price-lock call. Every order is placed against a frozen price lock and charged the locked prices — live-priced create is not allowed. A lock is single-use: reusing an already-consumed lockId is rejected 409 CONFLICT_PRICE_LOCK_ALREADY_USED. See the Cart preview & price locks guide.

discountCodestring

Optional partner discount code to apply/consume at order creation; the applied code + amount appear on the order’s pricing.discount. Display/reporting only — does not change the amount charged.

Response

idstring (uuid)

The created order’s own id — read it back via GET /api/v1/scent/orders/{orderId}, where orderId is this same value.

externalReferencestring
customerRefstring
statusstring (enum)

The one status vocabulary every product’s order maps into — see the Order states & errors guide for what each value means for a Scent order specifically, and for the create-time reject codes (CONFLICT_ORDER_DUPLICATE_REFERENCE, CONFLICT_PRICE_LOCK_ALREADY_USED, VALIDATION_PRICE_LOCK_EXPIRED/_INVALID) that stop an order from ever reaching a live status at all. failureReason on the order response is populated only when status is Failed, and is additive alongside it — status is never replaced by it.

pricing.currencystring
pricing.subtotalnumber (decimal)

Net goods amount, ex-VAT.

pricing.vatnumber (decimal)

Output VAT on the goods leg.

pricing.shippingFeeobject

The order-level shipping fee, shown as its own line. Zero for a free-shipping order.

pricing.discountobject

The discount code applied at checkout, if any. Display/reporting only — it never affects any other figure in pricing.

pricing.totalnumber (decimal)

The single VAT-inclusive gross amount actually charged to your wallet.

pricing.commissionobject

The partner commission on the order. Both the net and gross (VAT-inclusive) figures are carried explicitly.

modeBreakdownobject

Sum of line totals (ex-VAT) per settlement mode, e.g. {“Retail”: 640.00}. The key is YOUR OWN settlement mode for those lines (see pricingMode on an order line) — Wholesale or Retail.

Other responses

400Validation failure — including a missing/malformed lockId, an EXPIRED lock (VALIDATION_PRICE_LOCK_EXPIRED), or a lock whose cart has since mutated (VALIDATION_PRICE_LOCK_INVALID) — as well as ordinary field validation.
401No bearer token (UNAUTHORIZED_MISSING_TOKEN), an invalid token (UNAUTHORIZED_INVALID_TOKEN) or an expired one (UNAUTHORIZED_TOKEN_EXPIRED — mint a new token). UPSTREAM_AUTH_FAILED is different: a dependent service refused the Gateway itself. That is a server-side fault — retry later and do NOT re-mint your token. See the Errors guide.
403The route is not available to your credential (FORBIDDEN).
404No API route matches this path (NOT_FOUND_ROUTE). A missing resource on a real route returns that service’s own NOT_FOUND_* code instead.
409A prior attempt with the SAME externalReference already exists or is still in flight, the cart already has a pending order, a checkout race on the same cart lost, or the lockId was already used to create a (possibly different) order — see the Order states & errors guide and the Idempotency guide.
415The request body is not sent as application/json (UNSUPPORTED_MEDIA_TYPE).
422A business-rule rejection — most commonly BUSINESS_PRICE_NOT_AVAILABLE: a price in the cart is no longer available because prices moved since the cart was priced or locked. Re-run the checkout preview and check out again at the new price.
429Too many requests — see the Rate limits guide. Retry after the Retry-After header (seconds).
502A dependent service returned an invalid response (BAD_GATEWAY). Retry with backoff.
503The service is temporarily unavailable (SERVICE_UNAVAILABLE). Retry with backoff.
504A dependent service did not respond in time (GATEWAY_TIMEOUT). Retry with backoff.
curl --request POST \
--url https://api-omni.linra.net/api/v1/scent/orders \
--header 'Authorization: Bearer $TOKEN' \
--header 'Content-Type: application/json' \
--data '{
"externalReference": "string",
"shippingAddress": {
"recipient": "string",
"line1": "string",
"line2": "string",
"city": "string",
"nationalAddress": "string",
"region": "string",
"postalCode": "string",
"countryCode": "SAU",
"phone": "string"
},
"customerRef": "string",
"lockId": "5b1e3a1c-9d2e-4f3a-8b1c-9f0a2e3d4c5b",
"discountCode": "string"
}'

Response

{
"state": "SUCCESS",
"payload": {
"id": "5b1e3a1c-9d2e-4f3a-8b1c-9f0a2e3d4c5b",
"externalReference": "string",
"customerRef": "string",
"status": "Processing",
"pricing": {
"currency": "SAR",
"subtotal": 0,
"vat": 0,
"shippingFee": {
"amount": 0,
"vatAmount": 0,
"amountWithVat": 0
},
"discount": {
"code": "string",
"amount": 0
},
"total": 0,
"commission": {
"amount": 0,
"vatAmount": 0,
"amountWithVat": 0,
"netAfterCommission": 0
}
},
"modeBreakdown": {}
},
"details": null
}