API Reference
Integrate external systems with ReturnMate using the External API — offline repairs and trade returns with API-key authentication.
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:
- Click Create API Client and enter a Client name and optional Webhook URL.
- 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. - Clients can be edited (name, webhook URL) or revoked at any time. Revoked keys stop working immediately.
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.
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 containsitems,total,page,limitandtotalPages.GET /offline-repairs/:id/timeline— the RMA's activity timeline entries.
Lifecycle actions
| Endpoint | Body | Effect |
|---|---|---|
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/close | — | Close 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 withsku,productName,quantity,price) andshippingAddress(street,suburb,state,postcode). Optional:customerPhone,orderDate,customerNotes,faultDescription,additionalComment, per-itemvariantTitle/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:
| Status | Meaning |
|---|---|
400 | Validation failed — the message array lists field errors |
401 | Missing or invalid X-Api-Key |
403 | Plan restriction (e.g. LIMIT_EXCEEDED, READ_ONLY, PLAN_REQUIRED) |
404 | RMA not found for your shop |
429 | Rate 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.