Zid · E-commerce Engineering · Returns

Zid reverse orders: reconcile refunds, returns and stock

A production architecture for Zid reverse orders that prevents duplicate refunds and unsafe restocking by separating money, logistics and physical inspection.

TOPIC HUBE-commerce Engineering
Cardboard shipping boxes and packaging supplies arranged inside a warehouse.
Photo: Guilherme Mendes / Unsplash. Published January 25, 2026; free to use under the Unsplash License.

Zid's Reverse Orders APIs should be integrated as a durable workflow, not as one "return" request. Product eligibility, financial calculation, refund initiation, bank-transfer evidence, reverse shipping and physical inspection are separate transitions. The safe design stores every transition, prevents duplicate side effects and reconciles money and inventory independently. This guide is for developers building ERP, WMS, customer-service or accounting integrations for Zid stores.

This is a practical guide, not a news report. Zid's documented endpoint behavior is stated as fact and linked below. The state machine, retry policy and reconciliation controls are engineering recommendations. The documentation was verified on October 23, 2026.

The four records you must not collapse

A return touches four different facts:

  1. The original order proves what was sold and the remaining quantity that can still be returned.
  2. The reverse order records the merchant's return intent, selected lines, location, reason and logistics data.
  3. The refund records the financial action and its payment method.
  4. The inspection result records what physically arrived in good condition, arrived damaged or never arrived.

If an ERP stores all four as one boolean named \returned\, it cannot answer whether money moved before the parcel arrived, whether a damaged unit was restocked, or whether a retry created a second refund.

What Zid documents

Before a partial return, call Zid's View for Return endpoint. It returns only products with remaining returnable quantities and recalculates totals after previous returns. A fully reversed order returns no products and a zero order total.

Next, the Calculate Reverse Totals endpoint previews subtotal, discounts, VAT and total. Zid explicitly documents this calculation as read-only: it does not create a reverse order, move stock, create a refund or update the order status.

The Create Reverse Orders endpoint persists the reverse request. It accepts the order, partial/full choice, inventory location, return reason, products and shipping information. Its response exposes the reverse-order identifier, selected lines, calculated totals and available refund methods.

The Create Refund endpoint is a separate financial step. Zid instructs clients to read \refund_total\ and \available_refund_payment_methods\, then choose an amount and valid method. For \zid_bank_transfer\, the receipt upload endpoint is mandatory and accepts image files after the refund exists.

Physical handling is separate again. The Update Return Products endpoint records \received_quantity\, \not_received_quantity\ and \damaged_quantity\. For each line, their sum must not exceed \reversed_quantity\; quantities are non-negative and at least one must be greater than zero. Zid documents the update as atomic: one invalid line fails the whole request.

Finally, the Reverse Orders Waybill endpoint creates a return label and may return label, tracking URL, tracking number, courier and service-level fields.

Recommended internal state machine

Do not mirror an external status into one mutable column. Keep a local return case with explicit milestones:

Internal stateEvidence requiredSide effect allowed
\DRAFT\Original order and remaining quantitiesNone
\QUOTED\Calculation input hash and totals snapshotCustomer/operator approval
\REVERSE_CREATED\Zid reverse-order IDWaybill request
\REFUND_REQUESTED\Refund ID, amount and methodReceipt upload when required
\IN_TRANSIT\Tracking number or manual-return evidenceTracking updates
\INSPECTED\Good, damaged and missing quantities per lineInventory disposition
\RECONCILED\Money, stock and order checks all passClose case

The order of logistics and refund approval depends on merchant policy. Zid exposes separate operations; that does not mean your system must approve every financial effect immediately. High-value or fraud-sensitive returns may require inspection approval before the refund call. Consumer-policy and payment-provider obligations still apply.

Original engineering diagram separating Zid return eligibility, refund evidence, reverse logistics and physical inventory inspection. The licensed cover photograph illustrates warehouse handling.
Original engineering diagram separating Zid return eligibility, refund evidence, reverse logistics and physical inventory inspection. The licensed cover photograph illustrates warehouse handling. Open for a larger view

Architecture: command, effect and reconciliation

Use three durable tables or equivalent records:

  • \return_cases\: original order ID, Zid reverse ID, state, requested and approved amounts, refund method and version.
  • \return_lines\: original line ID, requested quantity, reversed quantity, received-good, damaged and not-received quantities.
  • \return_effects\: operation name, request hash, started time, external ID, response snapshot, result and reconciliation state.

Your public API should accept an internal idempotency key. Even if the Zid endpoint does not document native idempotency for a write, repeated client requests can return the existing local case instead of issuing another external effect.

async function requestReturn(command: ReturnCommand) {
  return db.transaction(async (tx) => {
    const existing = await tx.returnEffects.find(command.idempotencyKey);
    if (existing) return existing.publicResult;

    const eligible = await zid.viewForReturn(command.orderId);
    validateRemainingQuantities(command.lines, eligible.products);

    const quote = await zid.calculateReverseTotals(command.orderId, command.lines);
    await tx.returnEffects.insert({
      key: command.idempotencyKey,
      operation: "create_reverse_order",
      requestHash: stableHash(command),
      quoteSnapshot: quote,
      status: "prepared"
    });

    return { status: "awaiting_approval", quote };
  });
}

Do not keep a database transaction open while waiting on a network call in production. The example highlights the records; a real implementation should use a short transaction to persist a command, then an outbox worker to call Zid and persist the result.

Handle unknown outcomes safely

A timeout does not prove failure. Zid may have accepted a write while your client lost the response. Retrying a refund blindly can duplicate money movement.

For every write:

  1. Persist \started\ before the call.
  2. Store the exact request hash, not access tokens or unnecessary personal data.
  3. On a definite validation error, mark it rejected and do not retry unchanged input.
  4. On timeout or connection loss, mark the effect \unknown\.
  5. Reconcile against available reverse-order, order, credit-note or payment evidence before another write.
  6. Escalate unresolved financial uncertainty to an operator with the original request and observed evidence.

If an API does not expose enough evidence to distinguish success from failure, automated retry is not safe. A manual queue is better than a duplicated refund.

Money and inventory need different ledgers

Refund amount and restock quantity are related but not identical. A damaged product may be refunded but must not return to sellable stock. A parcel may be missing while the customer-service team has already approved a goodwill refund.

Model inventory disposition explicitly:

Inspection resultFinancial pathInventory path
Received in good conditionRefund according to policyRestock after SKU/location verification
Received damagedRefund or review according to policyQuarantine, repair or write-off
Not receivedHold or investigateNo restock
Quantity mismatchPartial approval or reviewReconcile per line

Never increment ERP stock merely because a reverse order was created. Use the physical inspection result and confirm which system owns the stock mutation. If Zid and the ERP can both adjust inventory, define one authority and import the other side's result; otherwise the same unit can be added twice.

Price, tax and rounding rules

Use Zid's calculated invoice lines and total as the platform quote. Do not reconstruct a refund from the current catalog price: discounts, VAT, line additions and previous returns may change the eligible amount.

Store monetary values as decimal amounts plus currency, and preserve the response snapshot that justified approval. Compare using currency precision, not binary floating-point equality. Before calling the refund endpoint, verify that the requested amount is not greater than the documented \refund_total\ and that the method appears in \available_refund_payment_methods\.

Security and privacy controls

  • Request only the required \orders.read_write\ scope and keep manager credentials out of logs and analytics.
  • Treat receipt images as untrusted uploads: limit size and type, scan them, store them privately and restrict retention.
  • Minimize customer address and phone replication; logistics services should receive only what the return requires.
  • Separate permission to create a reverse order from permission to release money or override inspection results.
  • Audit operator, reason, before/after quantities, approved amount and external identifiers.

Observability and reconciliation

Track business invariants, not only HTTP status:

  • cases stuck in each state and their age;
  • \unknown\ external effects awaiting reconciliation;
  • requested amount versus Zid quote versus refunded amount;
  • reversed quantity versus good, damaged and missing totals;
  • waybills without movement and parcels received without inspection;
  • stock adjustments without a matching inspected line;
  • bank-transfer refunds missing their required receipt.

Run a scheduled reconciliation that compares open local cases with Zid evidence. Alert on mismatches; do not silently rewrite accounting history.

Best practices and anti-patterns

Best practices

  • Refresh \view-for-return\ immediately before quoting a partial return.
  • Save external IDs and immutable response snapshots.
  • Use an outbox, bounded retries and a dead-letter/manual-review queue.
  • Make inspection a per-line decision with explicit stock disposition.
  • Test partial returns, prior returns, damaged items, timeouts and duplicate commands.

Anti-patterns

  • Retrying a refund after a timeout without reconciliation.
  • Treating the reverse order as proof the parcel arrived.
  • Recalculating VAT and discounts from today's product price.
  • Updating sellable stock from the requested return quantity.
  • Storing receipt images in a public bucket or logging manager tokens.

When not to automate the full workflow

A small store with rare, high-touch returns may be safer with operator-assisted processing and automated validation only. Digital products, services and custom-made goods may require a different eligibility model. If the ERP cannot represent damaged and missing quantities separately, fix the data model before enabling automatic restocking.

The reviewed Zid pages document endpoint behavior but do not establish one atomic transaction across return, refund, logistics and inventory, nor do they document a universal idempotency guarantee for every write. Design for partial completion and reconciliation.

Implementation checklist

  1. Map original order and line IDs without relying on SKU alone.
  2. Refresh remaining returnable quantities.
  3. Calculate and snapshot the platform refund quote.
  4. Obtain policy approval, then create one reverse order.
  5. Record refund and receipt evidence as separate effects.
  6. Create and monitor reverse logistics when required.
  7. Inspect every line and apply an explicit stock disposition.
  8. Reconcile money, inventory and order state before closure.

Related guides: Zid wallet reconciliation, Salla and Zid order state machines, recovering broken Zid webhooks, and the engineering article library.

Primary references

Official references

These references document the tools discussed. Examples and design decisions are illustrative and should be adapted to the project and its versions.

Prepared by: Noor Yasser

FROM DECISION TO DELIVERY

Working through a similar engineering challenge?

I help teams turn architecture decisions into a clear scope and dependable, reviewable implementation.

Book a 30-minute callRelated serviceBackend engineering & API integrationsRelevant projectLogistics at scale