A return is not a refund with a shipping label attached. It is a coordinated process across customer intent, item eligibility, physical receipt, inventory disposition and money movement. If an integration compresses those facts into one `returned` flag, a retry can refund twice, a damaged item can re-enter saleable stock, or support can close a case while the customer is still waiting for money.
Zid's current Reverse Orders documentation exposes distinct operations for viewing returnable items, calculating totals, creating a reverse order, updating received-condition quantities and creating a refund. That separation is useful, but an integration still needs its own durable control plane. The API describes available commands; it does not replace the merchant's approval policy, warehouse evidence or financial reconciliation.
This explainer uses official Zid documentation verified on 29 September 2026. The architecture, state model and examples are recommendations, not a claim that Zid implements the suggested internal ledger for your application.
Start from what is still returnable
Before presenting a return form, read the current order through Zid's View for Return endpoint. The documentation says it returns only products with remaining returnable quantities and recalculates totals from those remaining items. It defines the remaining quantity as the original quantity minus previous returns. A cached order snapshot cannot safely answer this after partial returns.
Store the response as an eligibility snapshot with its retrieval time, order ID, line identity, maximum remaining quantity, currency and maximum refundable amount. Let the customer choose against that snapshot, then re-read or recalculate immediately before committing. The snapshot explains what the customer saw; the fresh read protects against another return that completed meanwhile.
Do not identify a line by SKU alone. Two lines can share a SKU but differ in price, discount, tax or customization. Keep Zid's order-product identity and the reverse-order product identity throughout the workflow.
Calculate first, but do not treat calculation as approval
Zid's Calculate Reverse Totals endpoint previews subtotal, discounts, VAT and total for full or partial returns. The documentation explicitly says that it is read-only: it creates no reverse order and changes no stock, refund or order status. This makes it a quote, not a financial event.
Persist the calculation input and response as a versioned proposal. Display its currency and breakdown to the operator or customer. If products, quantities, promotions or previous returns change before approval, expire the proposal and calculate again. Never use a locally reconstructed amount as authority when the platform can calculate the current refundable total.
The proposal should carry a business decision too: who requested the return, which policy rule accepted it, whether shipping is deducted, and whether inspection is required. Those are merchant decisions, not values inferred from an HTTP 200 response.
Create one reverse order for one approved intent
The Create Reverse Orders endpoint creates the reverse request and returns a reverse-order identifier, selected inventory location, products, reverse total, refund total and available refund methods. Treat that identifier as the durable platform reference for every later operation.
Place a unique constraint on the merchant, original order and your approved return-intent ID. Before calling Zid, write a command row with a stable idempotency key and the intended line quantities. After success, store the Zid reverse-order ID and response. If the network times out, mark the command `outcome_unknown`; do not create a second intent blindly. Reconcile against platform state or route the case for controlled review.
This local idempotency boundary is an integration recommendation. Do not assume an undocumented provider-side idempotency guarantee. The safe question after an ambiguous response is “did this intent already create a reverse order?”, not “can I resend the same POST?”
Keep four linked records, not one status
Use four records with explicit relationships: the return intent, the Zid reverse order, the physical receipt inspection and the refund command. The return intent captures requested items and approval evidence. The reverse-order record mirrors platform identity and eligible quantities. The inspection record stores what physically arrived and its condition. The refund command records amount, method, attempt identity and observed result.
A customer-facing state can be derived from those records—requested, approved, in transit, received, under inspection, refund pending, refunded, rejected or exception—but it must not overwrite the evidence behind it. Warehouse staff should be able to record a damaged item without silently changing the approved refund, and finance should be able to hold a payment without erasing the receipt event.
Use an append-only transition log containing actor, source, timestamp, previous state, new state and reason. Corrections should add a compensating event rather than rewrite history. This is what lets support explain why two units were requested, one arrived, one was damaged and only one was restocked.
Record condition before changing saleable inventory
Zid's Update Return Products endpoint records quantities received in good condition, not received and damaged. The documented invariant is that their sum must not exceed the reversed quantity; quantities must be non-negative integers, and the update is atomic across the request. The documentation also says those values affect refund reconciliation, inventory adjustments and return auditing.
Mirror the same invariant locally before calling the API. Keep an inspection version and the warehouse operator or system that produced it. “Received” is not automatically “saleable”: add a disposition such as restock, quarantine, refurbish, discard or return to supplier. Only a confirmed restock disposition may produce a saleable inventory movement.
Inventory movement needs its own idempotent command keyed by reverse order, line and disposition version. If the warehouse corrects a quantity, post the difference as a new movement or compensate the old one. Never recompute stock by replaying mutable snapshots without a ledger.
Execute the refund as a controlled financial command
Zid's Create Refund endpoint is called for an existing reverse order after reviewing its `refund_total` and `available_refund_payment_methods`. The documentation lists multiple methods and notes that a `zid_bank_transfer` refund needs a receipt uploaded through a separate endpoint. A reverse-order approval therefore does not prove that money moved, and a refund request does not prove final settlement.
Create a refund command only from a frozen approved amount, currency and method. Give it a unique local command ID and store the reverse-order ID, calculation version, amount, initiator, request time and provider result. Lock the remaining refundable balance while the command is in progress so two workers cannot spend it concurrently.
For timeouts and 5xx responses, move to `refund_outcome_unknown`. Block a new refund for the same balance until reconciliation establishes whether the first command succeeded. For bank transfer, keep receipt attachment and financial completion as separate evidence. Uploading a receipt documents an action; it is not by itself a bank-settlement signal unless the merchant's process explicitly defines and verifies that meaning.
Reconcile physical, platform and financial truth
Run a reconciliation job that compares four totals per line and currency: requested quantity, platform reversed quantity, physically classified quantity and locally posted inventory movement; then compare calculated refundable amount, refund commands and the platform refund record. Every mismatch should produce a bounded exception, not an automatic retry loop.
Useful exceptions include reverse order missing after an unknown create outcome, physical quantity above reversed quantity, saleable restock above good-condition receipt, refund amount above remaining refundable balance, bank-transfer refund without required receipt evidence, and a completed refund with an unresolved inventory disposition. Assign an owner and next safe action to each class.
Keep money as decimal minor units or a decimal type with the original currency. Do not compare display strings. Recalculate from Zid before a corrective refund, and record why the new calculation differs from the original proposal.
A practical orchestration sequence
A robust integration can follow this sequence: read the returnable view; capture the customer's requested lines; calculate current totals; run merchant policy; create a durable local intent; create the Zid reverse order once; arrange the return waybill when needed; record warehouse inspection; decide inventory disposition; authorize the refund amount and method; execute one refund command; attach bank-transfer evidence when applicable; then reconcile until physical, platform and financial records agree.
The exact operational order can vary by merchant policy and payment method. Some merchants refund before receipt; others require inspection. Encode that difference as a policy and approval rule, not as scattered conditional code. What must remain invariant is that no stage impersonates another: a label is not receipt, receipt is not saleable restock, approval is not settlement, and an HTTP response is not reconciliation.
Measure control quality, not only return speed
Track time from request to approval, approval to first carrier scan, receipt to inspection, inspection to refund initiation and initiation to confirmed completion. Add rates for duplicate-create attempts blocked, unknown outcomes, manual exceptions, quantity corrections, refund variance, inventory variance and returns reopened after closure. Segment by payment method, carrier, inventory location and reason.
Speed is not the only goal. Guardrails should include refunds above eligible value, duplicate refunds, saleable restock of damaged items, unresolved unknown outcomes and cases closed before both the customer-facing and accounting obligations are complete. A faster workflow that increases those events is not an improvement.
The core design rule is simple: treat the reverse order, inspection, inventory movement and refund as linked but independent records. Freeze the evidence used for each decision, make external commands idempotent on your side, and close the return only after reconciliation proves that the parcel and the money reached their intended final states.
Official references
These references document the tools discussed. Examples and design decisions are illustrative and should be adapted to the project and its versions.
- Zid Docs — Reverse Orders overview, verified 29 September 2026
- Zid Docs — Order Details: View for Return, verified 29 September 2026
- Zid Docs — Calculate Reverse Totals, verified 29 September 2026
- Zid Docs — Create Reverse Orders, verified 29 September 2026
- Zid Docs — Update Return Products, verified 29 September 2026
- Zid Docs — Create Refund for Reverse Order, verified 29 September 2026
- Zid Docs — Upload Bank Transfer Receipt, verified 29 September 2026
Prepared by: Noor Yasser
Working through a similar engineering challenge?
I help teams turn architecture decisions into a clear scope and dependable, reviewable implementation.




