REST API
The WPReturns REST API lets other tools read and manage return requests under the ddwcwr/v1 namespace. Routes cover requests (list, create and update), messages (read and post) and the reason list. Every route needs a user with the ddwcwr_manage_requests capability, usually through an application password.
Available in: Pro.
Authentication
Section titled “Authentication”Use a WordPress application password for calls from outside WordPress.
- Pick a user who can manage requests such as a shop manager. Administrators also pass.
- Go to Users > Profile and scroll to Application Passwords.
- Enter a name such as “Helpdesk” and select Add New Application Password.
- Copy the password. WordPress shows it only once.
Send it with HTTP Basic auth over HTTPS:
curl -u "shopmanager:abcd efgh ijkl mnop qrst uvwx" \ https://example.com/wp-json/ddwcwr/v1/requestsCode running inside wp-admin can use the logged-in cookie with a wp_rest nonce instead.
Calls without the capability get rest_forbidden with the message “You are not allowed to manage return requests.”
Routes
Section titled “Routes”| Method | Route | What it does |
|---|---|---|
| GET | /wp-json/ddwcwr/v1/requests | List requests |
| POST | /wp-json/ddwcwr/v1/requests | Create a request |
| GET | /wp-json/ddwcwr/v1/requests/{id} | Get one request |
| PUT, PATCH or POST | /wp-json/ddwcwr/v1/requests/{id} | Update status, assignee or tracking |
| GET | /wp-json/ddwcwr/v1/requests/{id}/messages | List messages, internal notes and log entries |
| POST | /wp-json/ddwcwr/v1/requests/{id}/messages | Add a message or internal note |
| GET | /wp-json/ddwcwr/v1/reasons | List active return reasons |
{id} is the numeric request ID. RMA-01042 has the ID 1042.
List requests
Section titled “List requests”GET /requests takes these query parameters.
| Parameter | Type | Notes |
|---|---|---|
status | string | A status slug such as pending or received |
type | string | return, exchange, warranty, withdrawal or cancellation |
order_id | integer | Requests for one order |
customer | integer | Requests of one customer user ID |
search | string | RMA or order number, or text in email, name or tracking number |
page | integer | Default 1 |
per_page | integer | Default 20 and at most 100 |
The response headers X-WP-Total and X-WP-TotalPages give the totals.
curl -u "shopmanager:abcd efgh ijkl mnop qrst uvwx" \ "https://example.com/wp-json/ddwcwr/v1/requests?status=received&per_page=10"The request object
Section titled “The request object”Every route that returns a request uses this shape. Webhooks send the same object.
{ "id": 1042, "number": "RMA-01042", "order_id": 1042, "customer_id": 17, "customer_email": "jane.cooper@example.com", "customer_name": "Jane Cooper", "type": "return", "status": "received", "status_label": "Received", "resolution": "refund", "customer_note": "The shirt is too small.", "items_total": 49, "restocking_fee": 0, "shipping_fee": 5, "credit_bonus": 0, "resolution_total": 44, "refunded_total": 0, "coupon_code": "", "exchange_order_id": 0, "tracking_number": "1Z999AA10123456784", "carrier": "UPS", "assigned_to": 0, "risk_score": 0, "risk_flags": [], "source": "account", "returnless": false, "date_created": "2026-11-02T10:15:00+00:00", "date_updated": "2026-11-06T14:40:00+00:00", "date_closed": null, "items": [ { "id": 2210, "order_item_id": 3381, "product_id": 512, "variation_id": 515, "name": "Linen shirt - M", "qty": 1, "line_total": 49, "reason": "wrong-size", "condition": "unopened", "exchange_product_id": 0, "restocked": 1 } ]}source is account, portal, admin, api or withdrawal. Money fields are numbers in the order currency.
Create a request
Section titled “Create a request”POST /requests creates a request as staff. It takes a JSON body.
| Field | Required | Notes |
|---|---|---|
order_id | Yes | The WooCommerce order ID |
items | Yes | Array of order_item_id, qty, reason, condition and exchange_product_id |
type | No | Default return. Any type except withdrawal makes sense here. |
resolution | No | refund, store_credit, exchange, repair, replace or keep. Empty picks the first allowed one. |
note | No | Saved as the customer’s note |
curl -u "shopmanager:abcd efgh ijkl mnop qrst uvwx" \ -H "Content-Type: application/json" \ -X POST https://example.com/wp-json/ddwcwr/v1/requests \ -d '{ "order_id": 1042, "type": "return", "resolution": "refund", "items": [ { "order_item_id": 3381, "qty": 1, "reason": "wrong-size", "condition": "unopened" } ], "note": "Customer called the shop." }'The response is the new request with status 201. Like requests made on the New request screen, API requests skip order status checks, return windows and auto decisions.
Each item still needs a valid reason slug for returns, exchanges and warranty claims. Quantities stay capped at what is left on the order line.
Errors return status 400 with the message, for example “Please choose a reason for Linen shirt - M.”
Update a request
Section titled “Update a request”PUT /requests/{id} changes these fields. Send only the ones you want to change.
| Field | Notes |
|---|---|
status | Any status slug. Customers get the email for it when Notify is on. |
note | Sent with the status email and added to the conversation |
assigned_to | A user ID, or 0 to unassign |
tracking_number | The return tracking number |
carrier | The carrier name |
curl -u "shopmanager:abcd efgh ijkl mnop qrst uvwx" \ -H "Content-Type: application/json" \ -X PUT https://example.com/wp-json/ddwcwr/v1/requests/1042 \ -d '{ "status": "approved", "note": "Please use the prepaid label in your email." }'Statuses listed under Restricted statuses need the ddwcwr_process_refunds capability. Without it the call fails with status 403: “You are not allowed to move requests to this status.”
Messages
Section titled “Messages”GET /requests/{id}/messages returns the conversation, internal notes and the history log.
[ { "id": 8812, "kind": "message", "author_type": "customer", "author_id": 17, "message": "The shirt is too small.", "attachments": 2, "date": "2026-11-02T10:15:00+00:00" }]kind is message, note or log. attachments is a count. Files are not served through the API.
POST /requests/{id}/messages adds a staff message. Set private to true for an internal note.
curl -u "shopmanager:abcd efgh ijkl mnop qrst uvwx" \ -H "Content-Type: application/json" \ -X POST https://example.com/wp-json/ddwcwr/v1/requests/1042/messages \ -d '{ "message": "Your parcel arrived today.", "private": false }'The response is { "id": 8813 } with status 201. Messages are emailed to the customer. Notes are not.
Reasons
Section titled “Reasons”GET /reasons returns the active reasons with slug, label, status, require_photo and merchant_fault. Use the slugs in the items[].reason field when you create a request.
Related
Section titled “Related”- Webhooks
- Hooks reference
- Customers and fraud for capabilities
- Developer API feature