Returns
A return is its own case tied to proven shipped quantities. It does not unship an order, issue a refund or create an automatic credit. The warehouse operator records physical facts; the goods owner chooses among the offered decisions; the operator confirms the actual disposition. An own warehouse uses the same sequence.
| Method and path | Scope | Purpose |
|---|---|---|
| GET /v1/returns | returns:read | Current authorized cases and decisions |
| GET /v1/returns/commands/{idempotencyKey} | returns:read | Recover the original command receipt |
| POST /v1/returns/commands | returns:announce | Owner announces a return |
| POST /v1/returns/commands/preview | returns:announce + returns:read | Check announcement without saving |
| POST /v1/returns/decisions | returns:decide | Owner decides after inspection |
| POST /v1/returns/decisions/preview | returns:decide + returns:read | Check decision without saving |
| POST /v1/returns/processing-commands | returns:process | Operator receives, inspects and carries out disposition |
| POST /v1/returns/processing-commands/preview | returns:process + returns:read | Check operator action without saving |
#Read and identify
GET /v1/returns accepts limit=1..100 (default 50), after from next, and optional return_id for a complete case. A list row with details_included=false is a summary; empty child arrays do not mean that a case lacks receipts or inspections. All reads check current organization and partner authorization.
An announcement uses a client-chosen return_id, a reference and lines containing id, shipment_id, order_item_id, exact decimal-string quantity and reason. Shipment and item must be a proven source authorized for this API connection. Repeated or partial returns cannot exceed the returnable shipped quantity. No matching is guessed from name or SKU.
#Commands and responsibilities
Commands contain idempotency_key and operation.kind. Changes to an existing case require its current expected_version. The exact schemas, nullable fields and limits are published in OpenAPI.
| kind | Role and main fields |
|---|---|
| announce | Owner: return_id, reference, lines |
| report_unknown | Operator: return_id, reference, description, quantity |
| identify | Operator: return_id, expected_version, owner_organization_id and the proven shipment line |
| receive | Operator: line_id, stock_item_id, quantity, location_id, quarantine_condition_id, received_at, batch or null |
| inspect | Operator: line_id, receipt_id, inspection_id, quantity, observed_condition_id, offered_condition_ids, notes |
| decide | Owner: inspection_id, disposition, target_condition_id or null, reason |
| execute_disposition | Operator: inspection_id, source_balance_id, expected_balance_version, target_location_id or null, reason |
| reinspect | Operator: inspection_id, observed_condition_id, offered_condition_ids, notes |
| close | Operator: accept_shortage, reason |
Unknown goods remain a clarification case until an authorized source is identified. An unknown or foreign order does not disclose which of those two cases occurred.
#Conditions and decisions
Known received returns enter the existing warehouse stock ledger in quarantine. They are not immediately available for sale or picking. Inspection records the actual condition and the condition choices the operator offers for the next action; the owner cannot choose an arbitrary private condition from the partner's catalogue.
disposition is restock, refurbish, return_to_sender, scrap or hold. Restock and refurbishment require an offered target_condition_id; other decisions require null. A decision itself does not move stock. Execution records the actual result, and refurbishment can require reinspection before release.
Restock reclassifies and moves the already received goods. It does not book the same incoming quantity a second time. Personalization, incomplete sets and damaged items do not become new sellable goods without the appropriate explicit decision. A return of one component does not reconstruct a complete physical kit.
#Preview and uncertain outcomes
Previews run the same validation and roll back all effects. They need the matching write and read scopes. saved=false is never a physical receipt. A successful command returns an immutable event receipt with case, operation, revision and optional stock-event reference.
Retain the original idempotency key, input and expected version after any uncertain response. Recover the receipt or retry exactly; a fresh key cannot prove that the earlier action failed. Current permission and case visibility are still checked on recovery. Ordinary test keys never inspect or change live goods: use the isolated simulator to exercise receive, quarantine, inspection, decision and final disposition together.
#Photos, documents and recovery
- Prepare the file using
POST /v1/uploads. Actual supported image, PDF or text content is validated, up to 25 MiB; a filename alone is no proof of content. - Call
POST /v1/returns/evidencewithevidence_id,return_id,upload_idandperspective(owneroroperator). This requiresfiles:writeplusreturns:decidefor the owner orreturns:processfor the operator. Keep the same IDs after an uncertain response. - Preparation is not attachment. Execute
attach_evidenceon the decisions endpoint orattach_inspection_evidenceon the processing endpoint with the current case version. Inspection evidence additionally names its actualinspection_id. GET /v1/returns/{returnId}/evidence/{evidenceId}checksreturns:readand current case access. It returns file name, MIME type, size,download_urlandexpires_in: 60. Previously issued links can continue working until expiry.
Unattached preparations and temporary transfer parts expire after seven days. The daily retention worker removes eligible unbound bytes only after rechecking permanent attachments and active uploads. Attached case and inspection documents are retained with the case. An expired or removed evidence ID cannot be revived; start a new explicitly intended preparation after the old one expires. A timeout is different: recover or retry the original IDs first. Historical integration profiles cannot replay evidence staging from a file hit alone, because it does not prove the original upload reference; use an active validated profile or the canonical endpoint.
GET /v1/returns/custody exposes only the actual operator's own physical holdings after access withdrawal. It accepts optional entity_id, after and limit (1–50, default 20). handoff_recovery on the processing endpoint moves exclusively held goods into quarantine after explicit physical confirmation. It does not execute a former owner's decision. Order reservations remain on their original warehouse recovery path.
GET /v1/returns/sources?order_id={orderId} requires returns:read and orders:read and returns currently accessible proved shipments from the original order of this API connection. Select the shipment, order item, optional component and remaining returnable quantity from that response. Virtual sets are returned by their proved physical components; the commercial set head is never received as physical stock. Returns never undo the shipment history.
All public quantity units are piece, including source lines, case lines, custody and previews. No quantity conversion is performed. Unsupported historical base units return HTTP 422 unit_unsupported. The shared native workspace and AI tools keep their own existing unit labels.
#Global list selection
GET /v1/returns applies search, role=all|owner|operator, status=open|clarification|closed|recovery, sort=id|created_at|reference and direction=asc|desc to every currently authorized record before counting and cursor pagination. Search matches references without case sensitivity; % and _ are literal characters. total is the exact current filtered count, independent of the page size or cursor. It does not count hidden partner records.
Omitting the new fields retains the previous id ascending order. Date/reference sorts break ties by the same public identifier and direction. Continue with unchanged filters/sort and after=next. Changing a filter or sort starts again without after. An inaccessible, deleted or no-longer-matching date/reference anchor returns 409 resource_revision_conflict; restart the selection. These are current lists, not immutable stock snapshots: changes between calls can affect membership and order. The UI, MCP readers and integration profiles use this same contract.
Machine-readable version of this page: https://www.meykt.com/developers/returns.md