ReturnMate

API Reference

Integrate external systems with ReturnMate using the External API — offline repairs and trade returns with API-key authentication.

4 min read
Last updated 14 July 2026

ReturnMate's External API lets your own systems create and manage two kinds of RMAs: offline repairs (items handed in outside the customer portal — for example from a POS, service desk or partner system) and trade returns (B2B returns). It is not a general-purpose RMA API — the admin app and customer portal cover those workflows.

Base URL

https://api.returnmate.io/api/v1/external/v1

All endpoints below are relative to this base.

Authentication

Every request must include your API key in the X-Api-Key header (a Bearer token in the Authorization header is also accepted):

curl https://api.returnmate.io/api/v1/external/v1/offline-repairs \
  -H "X-Api-Key: rm_ext_YOUR_API_KEY"

Creating an API client

API clients are managed by an Admin in Settings → External API:

  1. Click Create API Client and enter a Client name and optional Webhook URL.
  2. The API Client Created dialog shows your API key (prefixed rm_ext_) and webhook secret once. Store both securely — ReturnMate keeps only a SHA-256 hash of the key and cannot show it again.
  3. Clients can be edited (name, webhook URL) or revoked at any time. Revoked keys stop working immediately.
Keys are shown once

If a key is lost or exposed, revoke the client and create a new one. There is no key-reveal or rotation endpoint.

Rate limiting

Creation endpoints (POST /offline-repairs, POST /trade-returns) are limited to 30 requests per minute per client. Other endpoints use the platform default (200 requests per minute). There are no plan-based rate tiers. Exceeding a limit returns 429 Too Many Requests.

Plan limits still apply

RMAs created through the External API count toward your plan's monthly RMA limit. At the limit, creation fails with 403 and code LIMIT_EXCEEDED. See Plans, Billing & Usage Limits.

Offline repairs

Create an offline repair

POST /offline-repairs

{
  "orderNumber": "1001",
  "customerEmail": "customer@example.com",
  "customerName": "Alex Chen",
  "customerPhone": "+61 400 000 000",
  "faultyItem": {
    "sku": "PWR-500",
    "productName": "Power Station 500",
    "quantity": 1,
    "price": 799.0,
    "serialNumber": "SN-1234",
    "variantTitle": "Black",
    "weight": 6.5
  },
  "faultDescription": "Unit will not charge past 20%",
  "storeId": "store_abc123",
  "externalRef": "TICKET-4821",
  "externalSource": "my-pos",
  "startStatus": "OFFLINE_DIAGNOSTICS",
  "replacementSku": "PWR-500",
  "notes": "Swapped over the counter",
  "tracking": { "trackingNumber": "ST123456", "carrierName": "StarTrack" }
}

Required fields: orderNumber, customerEmail, customerName, faultyItem (with sku, productName, quantity, price), faultDescription, storeId. startStatus must be COUNTER_SWAPPED or OFFLINE_DIAGNOSTICS if provided. externalRef/externalSource are your identifiers, echoed back in responses and webhooks.

Returns 201 Created with the RMA:

{
  "id": "cln_…",
  "rmaNumber": "#WAR1234A",
  "status": "OFFLINE_DIAGNOSTICS",
  "externalRef": "TICKET-4821",
  "externalSource": "my-pos",
  "orderNumber": "1001",
  "customerEmail": "customer@example.com",
  "customerName": "Alex Chen",
  "faultDescription": "Unit will not charge past 20%",
  "offlineDisposition": null,
  "isDangerous": false,
  "trackingNumber": null
}

Retrieve and list

  • GET /offline-repairs/:id — fetch one repair.
  • GET /offline-repairs?page=1&limit=20&status=OFFLINE_REPAIR&externalRef=…&externalSource=… — paginated list. The response contains items, total, page, limit and totalPages.
  • GET /offline-repairs/:id/timeline — the RMA's activity timeline entries.

Lifecycle actions

EndpointBodyEffect
POST /offline-repairs/:id/tracking{ "trackingNumber", "carrierName" }Lodge return postage tracking
POST /offline-repairs/:id/begin-diagnostics{ "notes?" }Move to Offline Diagnostics
POST /offline-repairs/:id/begin-repair{ "repairNotes?", "assignedToId?" }Move to Offline Repair
POST /offline-repairs/:id/resolve{ "offlineDisposition", "notes?" }Set disposition and resolve
POST /offline-repairs/:id/closeClose the repair

Dispositions follow the offline repair workflow: restock at master, restock at child, write off, or return to supplier. See Offline Repair Workflow.

Trade returns

For B2B (TradeMate) orders:

  • POST /trade-returns — create a trade return. Required: tradeOrderNumber, customerEmail, customerName, companyName, companyId, reason, items[] (each with sku, productName, quantity, price) and shippingAddress (street, suburb, state, postcode). Optional: customerPhone, orderDate, customerNotes, faultDescription, additionalComment, per-item variantTitle/weight/tradeLineItemId.
  • GET /trade-returns/:id — fetch one trade return.
  • GET /trade-returns — list trade returns.

Errors

Standard HTTP status codes with a JSON body:

StatusMeaning
400Validation failed — the message array lists field errors
401Missing or invalid X-Api-Key
403Plan restriction (e.g. LIMIT_EXCEEDED, READ_ONLY, PLAN_REQUIRED)
404RMA not found for your shop
429Rate limit exceeded

Webhooks

If your API client has a Webhook URL configured, ReturnMate sends signed event notifications (offline_repair.*, trade_return.*) as the RMA progresses. See the Webhooks Reference.

Notes and limitations

  • There are no official SDKs; use any HTTP client.
  • There is no sandbox environment — test against a development store.
  • The API does not expose standard portal-created returns, labels, refunds or analytics.
Was this helpful?
Contact Support