Skip to content
Linra Omni Developer Docs

Order states & errors

The order-state vocabulary per product, the create-time reject codes, and the failureReason value set.

Every product’s orders share ONE partner-facing lifecycle vocabulary (status, the UnifiedOrderStatus enum) — but which of those values a given product’s orders can actually reach, and what each value means for that product specifically, differs. This page lists Scent’s own applicable subset, plus the create-time states that stop an order from ever reaching a live status at all. A future product line documents its own applicable subset in its own section below, rather than this page being rewritten around it — some values will carry over unchanged, others won’t apply, and a new product may reach values in an order Scent never does.

status on every order response (POST /api/v1/scent/orders’s response, GET /api/v1/scent/orders, GET /api/v1/scent/orders/{orderId}) is one of:

status Meaning for a Scent order
Processing Charged and accepted — fulfilment is under way (being picked, packed, and shipped). This is the value you’ll see immediately after a successful create.
Completed Every fulfilment group on the order has been delivered.
Cancelled The order was cancelled before it was ever charged. No money moved.
PartiallyDelivered At least one, but not every, fulfilment group has been delivered — some parcels have arrived, others are still in transit.
PartiallyReturned At least one line has been returned (refunded, and any commission clawed back) but the order isn’t fully returned.
Returned Every line across the whole order has been returned and refunded.
Failed The order could not be created/charged at all — see failureReason below for why. This is the ONLY value a create call itself can ever hand you directly; every other value is something you observe later via GET/tracking/webhooks.

PartiallyDelivered and a return state (PartiallyReturned/Returned) are not mutually exclusive underneath — if both would apply, the returns state takes display precedence, since “some of this order has been sent back” is more actionable to show a partner than “some of it has arrived.”

failureReason — why a Failed order failed

Section titled “failureReason — why a Failed order failed”

failureReason is present on the order response only when status is Failed, and is additive alongside status — it never replaces it, and it’s omitted from the wire entirely (not merely null) for every other status.

The value is a sanitized, partner-safe reason — never a raw internal/operational code. The rule:

  • A genuine, partner-actionable business-rule rejection (any code prefixed BUSINESS_, e.g. BUSINESS_PRICE_NOT_AVAILABLE, BUSINESS_INSUFFICIENT_FUNDS, BUSINESS_EMPTY_CART) passes through verbatim — you can branch on it the same way you’d branch on any other state code in this API.
  • Anything else — an internal/ops/recovery signal that means nothing actionable to you (e.g. a crashed or stuck saga, a recharge-required dead-letter) — collapses to one generic code, ORDER_PROCESSING_FAILED. You will never see a raw internal code on this field.
{ "id": null, "status": "Failed", "failureReason": "BUSINESS_INSUFFICIENT_FUNDS", "...": "..." }

A Failed row with no downstream order ever created (a pre-create rejection — the most common shape) still carries its own id: null and failureReason — this is the one case where failureReason matters most, since there’s no other field on the row to explain why it failed.

Create-time reject states (never reach a live status at all)

Section titled “Create-time reject states (never reach a live status at all)”

These aren’t values of status — they’re the state code on the ERROR response of POST /api/v1/scent/orders itself, for a request that never even reaches a Processing order. See the Errors guide for the full HTTP-status-to-shape mapping.

state HTTP Meaning
CONFLICT_ORDER_DUPLICATE_REFERENCE 409 This externalReference already succeeded once. details.orderId names the existing order — fetch it, don’t retry. See Idempotency.
CONFLICT_ORDER_IN_PROGRESS 409 A prior attempt with this externalReference is still being processed. Retry again shortly.
CONFLICT_ORDER_REQUIRES_INTERVENTION 409 A prior attempt with this externalReference hit an unrecoverable state (details.status names it) and needs operator intervention before it can be retried at all. Contact your account manager rather than retrying.
CONFLICT_PRICE_LOCK_ALREADY_USED 409 The lockId you passed was already used to create an order (a price lock is single-use). details.orderId names that order. See Cart preview & price locks.
VALIDATION_PRICE_LOCK_EXPIRED 400 The lockId’s TTL passed before you redeemed it. Re-preview and take a new lock.
VALIDATION_PRICE_LOCK_INVALID 400 The lockId is unknown, not yours, or its cart has mutated since the lock was taken. Re-preview and take a new lock.

A second product line gets its own subsection here, listing its OWN applicable status values with their OWN product-specific meanings (some will read identically to Scent’s — Processing and Completed are likely universal — others may not apply, or a new product may introduce a state Scent never reaches), plus its own create-time reject states if it has any beyond the generic CONFLICT_ORDER_* family above (those three are spine-level and shared by every product).