Order lifecycle
An order is the record of a purchase. It’s created when a shopper starts checkout and moves through a small number of states as payment, fulfillment, and any refunds happen. This page describes those states, what triggers each transition, and which webhook fires.
States
payment captured tracking confirms
pending ───────────────────────▶ paid ─────────────────▶ fulfilled
│ (Stripe) │ shipment │
│ │ │
│ abandoned / expires │ refund │ refund
▼ ▼ ▼
(no order to refunded refunded
fulfill) (full — see note) (full — see note)| State | Meaning | How it gets here |
|---|---|---|
| pending | Checkout started; payment not yet confirmed | Shopper creates a checkout session |
| paid | Payment captured by Stripe; ready to fulfill | Stripe confirms the payment |
| fulfilled | Items packed and handed to the carrier | Fulfillment status reaches Shipped/Delivered (carrier tracking, or a manual advance) |
| refunded | Full captured amount returned | You issue a refund covering the full remaining balance |
| cancelled | Order voided before payment completed | Currently reserved — no order-detail action triggers this today; see below |
The exact labels in your admin may vary slightly, but the shape is stable.
Transitions in detail
pending to paid
When a shopper completes Stripe-hosted checkout and the payment is captured, Stripe notifies Orchard and the order becomes paid. This is the moment to fulfill.
- Webhook:
order.paidis delivered to your subscribed endpoints (within about five minutes — deliveries are queued). Itsdataincludes the order id, status, total, currency, customer id, and paid-at time. See Webhook events. - A pending order that’s never paid simply doesn’t need fulfillment; it resolves to paid or is abandoned.
paid to fulfilled
You fulfill from the admin: buy a label, print a packing slip, pack, and advance the order’s fulfillment status (carrier tracking usually does this automatically; a manual Advance status control is the fallback). The order becomes fulfilled once tracking confirms shipment, and the shopper is notified by email from your store’s sender. There’s no per-line-item fulfillment — one status and one tracking/carrier pair cover the whole order.
For the click-by-click, see Orders & fulfillment.
to refunded
From a paid (or fulfilled) order you can issue a full or partial refund — there’s no separate full/partial toggle, just an amount field that defaults to the full remaining balance. Orchard returns the money through Stripe to the shopper’s original payment method.
- Webhook:
order.refundedis delivered, with the order id, refund id, amount, currency, and refunded-at time. - A partial refund leaves the order otherwise intact (status unchanged); the order’s own status only becomes refunded once the full captured amount has been returned.
to canceled
There’s currently no Cancel action on the order detail page. If an order that hasn’t shipped needs to be voided (duplicate, fraud hold, customer change of mind), issue a full refund instead so the shopper isn’t charged.
A Stripe-driven automatic cancel path is not currently wired, and the order-detail UI doesn’t expose a manual cancel action either. The webhook surface reserves an order-canceled event for when a cancel path exists.
Idempotency and ordering
- Deliveries can repeat. Webhook retries reuse the same delivery id; dedupe on
X-Orchard-Delivery. See Webhooks. - Don’t assume instant delivery. Lifecycle webhooks are queued and arrive within about five minutes, not synchronously with the state change.
- The admin is the source of truth. If a webhook and the admin ever disagree, trust the order in the admin and check the delivery log.
Related
- Orders & fulfillment — doing this in the admin.
- Cart to checkout to order — creating the order via the API.
- Webhook events — the exact event payloads.