Documentation

Returns and RMA

Customer-initiated returns, return-merchandise-authorisation workflow, inspection, and refund processing.

The returns module manages the post-sale lifecycle: a customer asks to return something, the platform issues a return-merchandise-authorisation number (RMA), the customer ships the item back, staff inspects it, and a refund is processed. Each step is its own endpoint so the workflow can be wired into automations or external systems.

Customer-initiated returns

POST/storefront/returns/requestJWT
GET/storefront/returns/my-returnsJWT
GET/storefront/returns/rma/:rmaNumberJWT
PUT/storefront/returns/rma/:rmaNumber/shipJWT
PUT/storefront/returns/rma/:rmaNumber/cancelJWT

request creates the RMA. The body specifies the order, line items being returned, reason, and whether the customer wants a refund or exchange.

const rma = await fetch('/api/storefront/returns/request', {
  method: 'POST',
  headers: { orgid: ORG_ID, Authorization: `Bearer ${jwt}` },
  body: JSON.stringify({
    orderNumber: 'ord-12345',
    items: [
      { sku: 'SNK-AIR-1-9-BLK', quantity: 1, reason: 'wrong-size', condition: 'unused' },
    ],
    resolutionType: 'refund',
    notes: 'Need size 10 instead.',
  }),
}).then(r => r.json());

// { rmaNumber: 'RMA-2026-04-25-0001', status: 'pending', returnLabel: '...' }

If the org has free-return-shipping enabled, the response includes a return label. Otherwise the customer is responsible for postage.

ship is called by the customer after dropping the parcel at a carrier — they enter the tracking number, RMA moves to in-transit. cancel aborts before the parcel ships.

Staff workflow

GET/storefront/returnsJWT
GET/storefront/returns/statsJWT
GET/storefront/returns/order/:orderNumberJWT

Staff list and filter. Stats break down RMAs by status, reason, refund total — what a returns dashboard renders.

Approval

PUT/storefront/returns/:rmaNumber/approveJWT
PUT/storefront/returns/:rmaNumber/rejectJWT

Some orgs auto-approve all returns; others require staff approval before issuing the label. Approval is a no-op if request already auto-approved.

Inspection

PUT/storefront/returns/:rmaNumber/receiveJWT
PUT/storefront/returns/:rmaNumber/inspectJWT

receive is called when the parcel arrives at the warehouse — moves the RMA to received. inspect records the inspection outcome:

await fetch(`/api/storefront/returns/${rmaNumber}/inspect`, {
  method: 'PUT',
  headers: { orgid: ORG_ID, Authorization: `Bearer ${jwt}` },
  body: JSON.stringify({
    items: [
      {
        sku: 'SNK-AIR-1-9-BLK',
        condition: 'as-received',
        accepted: true,
        restockable: true,
      },
    ],
    notes: 'Tags still attached, returning to stock.',
  }),
});

If restockable: true, the inventory module automatically receives the unit back via POST /storefront/inventory/return.

Completion

PUT/storefront/returns/:rmaNumber/completeJWT
POST/storefront/returns/:rmaNumber/notesJWT
PUT/storefront/returns/:rmaNumber/cancelJWT

complete triggers the refund: the storefront's payment service refunds the original payment method (Stripe, PayPal, gift card portion to gift card balance — see Gift cards). The RMA moves to completed and the customer receives a confirmation email.

notes adds a timestamped note to the RMA — used for staff comments and customer-visible status updates.

Refund types

The resolution types supported:

TypeWhat happens at completion
refundRefund original payment method
exchangeIssue new order for replacement, no refund
store-creditIssue gift card for the refund amount
partial-refundRefund a fixed amount (used for damaged-but-keep flows)

For exchange flows, the new order's payment intent reuses the inspection result — if the customer is upgrading, charge the difference; if downgrading, refund it.

Stats and reporting

The stats endpoint returns:

  • Total RMAs by status
  • Total refund amount this period
  • Top reasons for return
  • Mean time-to-resolution
  • Restock rate (% of returned items returned to inventory)

These feed quality and merchandising decisions — high return rates on a SKU usually mean a sizing issue or a description mismatch.

The RMA workflow integrates with the logistics module. When you generate a return label, it's a real shipment record — track it the same way you track outbound shipments. The customer's "where's my return?" page is the same component as "where's my order?".