Return request model

Updated May 28, 20263 min read

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_reference and 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_quantity increments when a reverse Shipment reports DELIVERED.
  • received_quantity increments when ops confirms the items at the warehouse, through the Dashboard or PATCH /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 pending for 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).
  • amount and currency.
  • note and 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.