The Returns API models the complete RMA lifecycle: a return is created on an order, it's approved or rejected, the customer ships the merchandise back, the merchant receives it, and finally the refund (or exchange) is processed. Each step is a separate endpoint, with its own permission.
Real state progression
The real catalog of return states has 12 values: return-requested, return-approved, return-rejected, return-shipped, return-received, inspecting, refund-pending, refunded, exchange-pending, exchange-shipped, exchange-completed, closed. Note that in addition to the refund flow there is an exchange flow (exchange-*) — the return type (type) can be refund, exchange, or store-credit.
The endpoint exists and returns a count per return status group, but the exact names of those groups were not confirmed in this audit (we don't assume they match the order status groups — pending, preparing, completed, cancelled, problematic, all — because they are different catalogs). Verify the exact shape against a real response before parsing it by field name.
defective, wrong-item, size-fit, quality-issue, not-as-described, changed-mind, arrived-late, damaged-shipping, duplicate-order, other
Hyphenated, not underscored
All reason values use a hyphen (wrong-item, not wrong_item). Sending an underscored value fails validation.
items is identified by sku, not by itemIndex
Unlike POST /orders/{orderId}/prepare (which identifies items by itemIndex), creating a return identifies each item by sku: the service looks up that SKU inside order.items and fails with OrderValidationError if it isn't found, or if quantity exceeds the order's original quantity.
type isn't enforced at runtime despite the TypeScript type marking it required
The transport validator (createReturnSchema) only requires items and reason — it doesn't validate type at all. And at the library level, createReturn() assigns newReturn.type = input.type directly, with no check whatsoever: if you omit type, the field stays undefined in the saved document, with no error. The CreateReturnInput TypeScript interface marks type as non-optional, but that does NOT translate into an actual validation in any layer — it's a type promise the code doesn't keep. If your integration depends on every return having a type, send it explicitly; don't assume a default.
Updates fields of an existing return. At least one field is required in the body.
orderIdstringrequired
Order ID
returnIdstringrequired
Return ID
statusstring
New status of the return.
overallConditionstring
Overall condition of the merchandise (see catalog in the receive section).
inspectionNotesstring
Notes from the merchandise inspection.
rejectionReasonstring
Rejection reason, if applicable.
skipMerchandiseReturnboolean
Whether the physical return of the merchandise is skipped (e.g. refund without return).
inventoryDispositionobject
What to do with the returned inventory: { locationId, locationName?, placeType: 'available'|'reconditioning'|'damaged'|'shrinkage', placeCode?, costImpact?, currency? }.
The real catalog has exactly these 3 hyphenated values. There is no generic fourth value ("etc."); sending original_payment (underscore) fails validation.