Return request model
A return request is the central object for a return. It tracks a customer's intent to return items, the merchant's decision, the reverse shipment that carries the parcel back, and the refund entries that record what was returned.
The shape
A return request carries:
- References.
partner_order_referenceand a list of forward Shipments the items came from. - Items. A list of return items, one per order line being returned.
- Status. The request lifecycle state (see below).
- Pickup. The customer's address (where the parcel is collected from).
- Refunds. A list of refund entries, added as the merchant records refunds against the return.
Each return item carries:
- Reason. A merchant-defined code (e.g.
defective,wrong_size) drawn from the merchant's configured return reasons. - Approved quantity. How many units the merchant agreed to take back.
- Returned quantity. How many units have physically been sent back.
- Received quantity. How many units ops has confirmed at the warehouse.
- Reverse shipments. The IDs of the reverse Shipments carrying these items.
- Condition. A merchant-defined condition code, recorded by ops when the item is received.
- Resolution and refund type. The outcome path (see Taxonomy below).
Request lifecycle
The request lifecycle is the state of the customer's request, distinct from the per-item quantity tracking. The states:
pending
│
│ approve / reject
├────────▶ rejected (terminal)
│
▼
approved
│
│ complete
▼
completed (terminal)
Plus two branches that can apply mid-flow:
cancelled: terminal; the request is voided.on_hold: the request is paused (for example, waiting for additional information from the customer).
Status transitions happen via the Returns API
(PATCH /requests/{id}/approve, /reject, /cancel,
/complete) or from the Dashboard. Inactive requests can also
be auto-closed after a configurable number of days. This keeps
the queue clear of abandoned requests.
Item quantities, separate from request status
While the request status tracks the lifecycle, the
returned_quantity and received_quantity fields on each item
track physical movement separately:
returned_quantityincrements when a reverse Shipment reportsDELIVERED.received_quantityincrements when ops confirms the items at the warehouse, through the Dashboard orPATCH /requests/{id}/receive.
A request can be approved with zero returned items (parcel
hasn't moved yet). A request can be completed with partial
received quantities (the merchant decided the return is closed
even though not every item came back). The two dimensions
(request state, item movement) don't have to advance in
lockstep.
Auto-approval
A return reason can be marked auto-approve in Returns Settings. The logic is simple:
- If every item's reason has the auto-approve flag, the request auto-approves on submission.
- If any item's reason is not auto-approve, the request stays
pendingfor the merchant to decide in the Dashboard.
There's no auto-rule engine beyond this. Return windows, item values, and other policies are enforced operationally: the portal hides ineligible items at lookup, ops reviews edge cases manually.
Taxonomy: reason → resolution → refund type
Three merchant-defined code lists, linked together:
- Return reasons. Why the customer wants to return.
- Resolutions. What the merchant offers (
refund,replace,store_credit, etc.). Each reason links to a list of allowed resolutions. - Refund types. How the refund is issued
(
original_payment,store_credit, etc.). Each resolution links to a list of allowed refund types.
When the customer picks a reason, the portal narrows the options available for the rest of the flow. When ops approves, they pick a resolution; when refunding, they pick a refund type. All three lists, and the allow-lists between them, are configured in Settings → Returns Settings.
Refunds
A return request carries a list of refund entries. Each entry captures one refund record:
reference: the merchant's payment-system reference (for example, a Stripe refund ID).type: the refund type code (see taxonomy above).amountandcurrency.noteand timestamps.
Refunds are added via POST /requests/{id}/refunds and can be
deleted. There is no Carriyo-managed refund state machine, no
auto-trigger on item receipt, and no integration with payment
systems. Carriyo records the merchant's refund decisions; the
merchant moves the money.
How it fits with other modules
- Returns. The parent module.
- Reverse shipments. The carrier side of the return.
- Returns portal. The customer-facing portal that creates return requests.
- Orders. Return requests reference back to order lines.
- Webhooks. Return request lifecycle events fire here.