Order lifecycle
Goal: read a tenant’s orders through the fdk_ merchant API, understand the
statuses an order moves through, and pick the right money-moving action for a
given state.
Audience: a back-office integration authenticating with an fdk_
credential (Authorization: Bearer fdk_…). The tenant is carried by the
credential, never in the path or body.
The status set
An order’s status is one of eleven values:
| Status | Meaning |
|---|---|
pending_payment | Created, payment not yet captured. |
placed | Captured and accepted — the normal post-checkout state. |
processing | Being prepared for fulfillment. |
on_hold | Paused (fraud review, stock, manual hold). |
shipped | Handed to the carrier. |
partially_shipped | Some lines shipped, others pending. |
delivered | Delivered to the shopper. |
cancelled | Voided before fulfillment; inventory released. |
refunded | Fully refunded. |
partially_refunded | Partially refunded. |
payment_failed | Capture failed at checkout. |
Money on every order is integer cents: subtotal_cents, discount_cents,
shipping_cents, tax_cents, total_cents.
Reading orders
List the tenant’s orders
Scope read:own_orders — a read-only key can never move money.
GET /v1/merchant/orders HTTP/1.1
Host: api.ruo.pro
Authorization: Bearer fdk_live_…Returns { orders: [...] }, each carrying its status, totals, coupon_code,
and ship_to.
Get one order with items and refunds
GET /v1/merchant/orders/{id} HTTP/1.1
Authorization: Bearer fdk_live_…{
"order": { "id": "…", "status": "placed", "total_cents": 5911, "…": "…" },
"items": [ { "sku": "NOVA-BPC-5MG", "quantity": 2, "line_total_cents": 4998 } ],
"refunds": []
}refunds: [] is the verified “no refund records” answer. refunds: null means
the refund read failed — unknown, never “none”. Do not render null as a
zero-refund order.
Transitions are guarded
Every status change is a checked transition. Two codes tell you a transition
was refused; branch on err.body.error.code:
invalid_transition— the requested move is illegal for the current status.already_in_status— the order is already where you asked it to go. A retried post that walked the status the first time sees this rather than re-walking it.order_fulfilled_use_returns— a409on cancel: the order already shipped/delivered and must go through the returns lifecycle instead.
Cancel vs refund vs return
Choose by the order’s state and what you want to happen:
| You want to… | Order state | Use |
|---|---|---|
| Void the whole order, release stock, return payment | Not yet shipped | cancel |
| Return money but keep the order record | placed and not fully refunded | refund |
| Take back a shipped item, restock, and settle | Shipped / delivered | return (RMA) |
Cancel — pre-fulfillment only
POST /v1/merchant/orders/{id}/cancel HTTP/1.1
Authorization: Bearer fdk_live_…
Content-Type: application/json
{ "reason": "customer changed their mind" }Scope manage:own_orders. Cancel releases reserved inventory and refunds any
captured payment. The response reports reservations_released, refunded, and
refunded_cents. A shipped/delivered order is refused with a 409 — go to
returns.
Refund — full or as recorded
POST /v1/merchant/orders/{id}/refund HTTP/1.1
Authorization: Bearer fdk_live_…
Content-Type: application/json
{ "reason": "goodwill" }The charge is derived server-side from the order — you never send an amount.
The response reports the full split, including store_credit_returned_cents and
gift_card_returned_cents. An already-fully-refunded order, or one with no card
charge to refund (tender-only), is a 409.
Merchant refund and cancel are auto-idempotent per order — no
Idempotency-Key header. A retry replays (replayed: true); it never
double-refunds. This differs from the storefront-token cancel/refund/edit calls
and the returns receive step, which do require the deterministic
Idempotency-Key header.
Return — post-fulfillment
Shipped and delivered orders go through the returns (RMA) lifecycle
(requested -> approved -> received -> refunded), where the receive step
restocks and settles the refund and requires the Idempotency-Key header. See
the recipe below.
Related
- Tenant-facing API — the full
fdk_route and scope list. - Returns and refunds — the RMA lifecycle and the receive-time idempotency header.
- Money invariants — integer cents and idempotency rules.