> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stateset.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Returns and return-to-vendor

> Customer returns in, refunds out, quality disposition, and sending defective goods back up the supply chain.

# Returns and return-to-vendor

Reverse logistics is two connected flows: goods coming back **from customers**, and goods going back
**to suppliers**. The hinge between them is disposition — deciding whether a returned item is
restockable, scrap, or the supplier's problem.

## Customer return

```bash theme={null}
curl -X POST https://api.stateset.com/api/v1/returns \
  -H "Authorization: Bearer $STATESET_API_KEY" \
  -H 'content-type: application/json' \
  -d '{ "order_id": "ord_9x2", "items": [{ "sku": "SHOE-RED-10", "quantity": 1, "reason": "defective" }] }'

curl -X PATCH https://api.stateset.com/api/v1/returns/{id}/approve \
  -H "Authorization: Bearer $STATESET_API_KEY"
```

Approval authorizes the return — the RMA — before goods move. What arrives then goes through
[receiving](/guides/commerce/receiving-and-putaway) like any inbound goods, with `condition`
recorded honestly, because condition drives everything below.

<Note>
  **Approval is a policy decision, and policy is where agents get argued into things.** If an agent
  handles returns, put the approve call behind the [decision gate](/stateset-nsr-decisions): the gate
  rules on `return_allowed(order_941)` from your actual policy, with cited proof — and "the customer
  was upset" is not a rule it knows.
</Note>

## Refund

```bash theme={null}
curl -X POST https://api.stateset.com/api/v1/payments/{payment_id}/refund \
  -H "Authorization: Bearer $STATESET_API_KEY" \
  -H "Idempotency-Key: rfnd_ret_456" \
  -H 'content-type: application/json' \
  -d '{ "amount": "128.00" }'
```

Refund against the **original payment**, and decide your trigger deliberately: refund-on-approval is
customer-friendly and eats fraud; refund-on-receipt holds cash until goods arrive. Either is fine —
mixing them per-agent-mood is not. The refund posts to the ledger and shows in
[order to cash](/guides/commerce/order-to-cash) views automatically.

## Disposition

The returned unit is now inventory of uncertain quality. Route it:

| Condition                   | Action                                                                                         |
| --------------------------- | ---------------------------------------------------------------------------------------------- |
| Resellable                  | [Put away](/guides/commerce/receiving-and-putaway#3--put-away) to a sellable location          |
| Uncertain                   | `POST /api/v1/quality/holds` — off sellable stock while inspected                              |
| Defective, supplier's fault | Return to vendor, below                                                                        |
| Defective, scrap            | `POST /api/v1/serials/{id}/scrap` for serialized goods; inventory adjust with reason otherwise |

For a suspected *pattern* — the third cracked sole this week — open an NCR
(`POST /api/v1/quality/ncrs`) and disposition the lot as a whole, not unit by unit:
[quality holds and NCRs](/guides/commerce/traceability#quarantine-and-quality) connect a defect to
every unit that shares its lot.

## Return to vendor

```bash theme={null}
curl -X POST https://api.stateset.com/api/v1/vendor-returns \
  -H "Authorization: Bearer $STATESET_API_KEY" \
  -H 'content-type: application/json' \
  -d '{ "supplier_id": "sup_88", "items": [{ "sku": "SHOE-RED-10", "quantity": 12, "reason": "defective_sole" }] }'

curl -X POST https://api.stateset.com/api/v1/vendor-returns/{id}/submit  -H "Authorization: Bearer $STATESET_API_KEY"
curl -X POST https://api.stateset.com/api/v1/vendor-returns/{id}/process -H "Authorization: Bearer $STATESET_API_KEY"
```

`submit` sends it to the supplier for authorization; `process` executes the physical return and
relieves inventory. The money comes back as a **vendor credit**
(`POST /api/v1/vendor-credits`, applied against future [bills](/guides/commerce/procure-to-pay)) —
suppliers rarely wire cash, so model what actually happens.

<Warning>
  Close the loop or the RTV quietly becomes a write-off: goods shipped back, credit never issued, and
  nobody notices because inventory already looks right. Track open vendor returns against received
  credits (`GET /api/v1/vendor-returns?status=processed` vs `GET /api/v1/vendor-credits`) — the gap
  between them is money owed to you.
</Warning>

## Related

* [Order to cash](/guides/commerce/order-to-cash) — the forward flow being reversed
* [Traceability](/guides/commerce/traceability) — lots, serials, and quarantine
* [Object: the return](/object-reference/returns/object) — every field, and which are nullable
