ConceptsOrder lifecycle

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)
StateMeaningHow it gets here
pendingCheckout started; payment not yet confirmedShopper creates a checkout session
paidPayment captured by Stripe; ready to fulfillStripe confirms the payment
fulfilledItems packed and handed to the carrierFulfillment status reaches Shipped/Delivered (carrier tracking, or a manual advance)
refundedFull captured amount returnedYou issue a refund covering the full remaining balance
cancelledOrder voided before payment completedCurrently 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.paid is delivered to your subscribed endpoints (within about five minutes — deliveries are queued). Its data includes 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.

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.refunded is 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.