REST API
ReturnDesk Pro has a REST API under the namespace tsre/v1, and three WooCommerce webhook topics. Staff routes manage returns, customer routes work on the signed-in customer's own returns, and two routes manage store credit.
The REST API and the webhook topics are part of the Pro edition. The Lite edition registers only the signed photo route GET /photos/{id} (see "Photos" below), which the return screen uses to show the customer's photos. Every other route answers 404 rest_no_route in Lite.
Base address: https://example.com/wp-json/tsre/v1
Authentication
| Routes | Who can call them |
|---|---|
/returns... | A signed-in user with the manage_tsre_returns capability (Administrator and Shop manager) |
/settings | A signed-in user with manage_woocommerce |
/me/returns... | Any signed-in user. A customer sees only their own returns, other ids answer 404. |
/credits/... (Pro) | A signed-in user with manage_tsre_returns |
/photos/{id} | A signed link, see "Photos" below |
/webhooks/{carrier} (Pro) | The carrier service, authenticated by signature, see Labels and carriers |
ReturnDesk uses the standard WordPress REST authentication:
- Application Passwords for scripts and other servers. Create one on the user profile and send it with HTTP Basic authentication over HTTPS.
- Cookie sessions for code running in the browser. Send the
X-WP-Nonceheader with thewp_restnonce.
curl -u "api-user:YOUR_APPLICATION_PASSWORD" \
"https://example.com/wp-json/tsre/v1/returns?status[]=requested&per_page=20"
Without a valid login, staff routes answer 401 (or 403 when you are signed in without the capability) with rest_forbidden, and /me routes answer 401 with rest_not_logged_in. The API has no rate limit of its own.
Staff routes
List returns
GET /returns
| Parameter | Type | Notes |
|---|---|---|
status | array | One or more of requested, approved, label_sent, in_transit, received, inspected, resolved, rejected, cancelled |
return_method | array | One or more of prepaid_label, customer_label, dropoff, in_store, keep |
search | string | Up to 200 characters. Matches the RMA number and the email, and the order id when numeric. |
customer_id, order_id | integer | Minimum 1 |
date_from, date_to | string | YYYY-MM-DD or YYYY-MM-DD HH:MM:SS, on the creation date. A date alone covers the whole day. |
page | integer | Default 1 |
per_page | integer | 1 to 100, default 20 |
orderby | string | created_at (default), updated_at, status, return_number, order_id |
order | string | asc or desc (default) |
The body is an array of returns. The headers X-WP-Total and X-WP-TotalPages give the totals.
Get a return
GET /returns/{id}
Returns the return with its items, its events (the timeline) and its photos.
{
"id": 39,
"return_number": "RMA-2026-000039",
"order_id": 74,
"order_number": "74",
"customer_id": 3,
"customer_email": "[email protected]",
"status": "requested",
"resolution": "refund",
"return_method": "customer_label",
"currency": "EUR",
"refund_total": 35.0,
"credit_total": 0.0,
"fee_total": 0.0,
"exchange_order_id": null,
"refund_id": null,
"label_id": null,
"reason_summary": "Wrong size or fit",
"customer_note": "The sleeves are a little too short for me.",
"admin_note": null,
"window_expires_at": "2026-11-27 18:40:00",
"created_at": "2026-10-28 16:40:00",
"updated_at": "2026-10-28 16:40:00",
"resolved_at": null,
"erased_at": null,
"items": [
{
"id": 61,
"return_id": 39,
"order_item_id": 12,
"product_id": 22,
"variation_id": 0,
"qty_requested": 1,
"qty_accepted": 0,
"qty_rejected": 0,
"reason_code": "wrong_size",
"reason_text": "",
"condition_grade": null,
"restock": false,
"unit_refund": 35.0,
"line_refund": 0.0
}
],
"events": [],
"photos": []
}
Dates are UTC. The guest access token is never part of the response.