Returns API
Last Updated: 2026-07-02
List Returns
/open/v1/returnsScope: orders:read Returns a paginated list of return requests for the seller bound to your access token. You can filter by status or parent order_id, choose a sort direction, and walk large result sets efficiently with cursor pagination. Return statuses: requested, approved, rejected, received, refunded.
Only returns belonging to your seller are ever returned — the seller scope is enforced server-side from your access token and cannot be overridden by any query parameter.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| status | string | No | Filter by return status. One of requested, approved, rejected, received, refunded. Any other value returns VALIDATION_ERROR (HTTP 400). |
| order_id | string | No | Restrict the list to returns of a single order ID. |
| page | integer | No | 1-based page number for offset pagination. Ignored when cursor is supplied. Default 1. |
| limit | integer | No | Page size. Default 20. |
| sort | string | No | Sort direction by created timestamp: created_at_desc (newest first, default) or created_at_asc. Any other value falls back to the default. |
| cursor | string | No | Opaque keyset cursor returned as meta.nextCursor. When present, switches to cursor pagination: page and sort are ignored, and the response meta omits page/total. A malformed cursor returns VALIDATION_ERROR (HTTP 400). |
Example Request
curl -X GET "https://api.mallplus.com/open/v1/returns?page=1&limit=20&status=requested" \ -H "X-MallPlus-Partner-Id: app_ck9x2mf3w0001" \ -H "X-MallPlus-Timestamp: 1713254400" \ -H "X-MallPlus-Signature: a1b2c3d4e5f6..."
Example Response — offset pagination (default)
{
"success": true,
"data": [
{
"id": "ret_abc123",
"orderId": "ORD-SAMPLE-001",
"status": "requested",
"reason": "Item received damaged",
"items": [
{ "itemId": "100000001", "quantity": 1, "reason": "Damaged" }
],
"refundAmount": 129900,
"created_at": "2026-04-14T10:00:00Z"
}
],
"meta": { "page": 1, "limit": 20, "total": 3 }
}Example Response — cursor pagination
{
"success": true,
"data": [ /* …same Return objects… */ ],
"meta": {
"limit": 50,
"nextCursor": "eyJ0cyI6IjIwMjYtMDQtMTRU..."
}
}Pagination modes: omit cursor for classic page/limit/total offset paging. To walk a very large set without counting rows, pass the previous meta.nextCursor back as ?cursor=; stop when nextCursor is absent.
Get Return
/open/v1/returns/:idScope: orders:readReturns the full details of a single return request, including the reason, items being returned, and current status.
Create Return
/open/v1/returnsScope: orders:write Create a return request for an order. The order must belong to the seller bound to your access token (cross-tenant orders return 404, never the return creation flow). The overall return reason is required; an optional per-item reason may be supplied for finer-grained reporting. On success this endpoint returns 201 and fires a return.created webhook event.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| orderId | string | Yes | The order to create a return for. Must be owned by your seller. |
| items | array | Yes | 1–100 line items to return. Each item: { itemId, quantity, reason? } |
| items[].itemId | string | Yes | The order line item ID being returned. |
| items[].quantity | integer | Yes | Quantity to return. Must be a positive integer (max 1,000,000). |
| items[].reason | string | No | Per-item return reason (max 500 chars). |
| reason | string | Yes | Overall return reason (max 500 chars). |
Example Request
curl -X POST "https://api.mallplus.com/open/v1/returns" \
-H "X-MallPlus-Partner-Id: app_ck9x2mf3w0001" \
-H "X-MallPlus-Timestamp: 1713254400" \
-H "X-MallPlus-Signature: a1b2c3d4e5f6..." \
-H "Content-Type: application/json" \
-d '{
"orderId": "ORD-SAMPLE-001",
"items": [
{ "itemId": "100000001", "quantity": 1, "reason": "Damaged on arrival" }
],
"reason": "Item received damaged"
}'Example Response (201 Created)
{
"success": true,
"data": {
"id": "ret_abc123",
"orderId": "ORD-SAMPLE-001",
"status": "requested",
"reason": "Item received damaged",
"items": [
{ "itemId": "100000001", "quantity": 1, "reason": "Damaged on arrival" }
],
"created_at": "2026-04-14T10:00:00Z"
}
}Idempotency: Include an Idempotency-Key header to safely retry this request without creating duplicate returns. The seller bound to the access token is enforced server-side — never pass a sellerId in the request body.
Approve Return
/open/v1/returns/:id/approveScope: orders:write Approve a return request. The return must be in requested status. Once approved, the seller should expect the items to be returned for inspection.
Example Request
curl -X POST "https://api.mallplus.com/open/v1/returns/ret_abc123/approve" \ -H "X-MallPlus-Partner-Id: app_ck9x2mf3w0001" \ -H "X-MallPlus-Timestamp: 1713254400" \ -H "X-MallPlus-Signature: a1b2c3d4e5f6..."
Reject Return
/open/v1/returns/:id/rejectScope: orders:write Reject a return request with a reason. The return must be in requested status.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| reason | string | Yes | Reason for rejecting the return |
Example Request
curl -X POST "https://api.mallplus.com/open/v1/returns/ret_abc123/reject" \
-H "X-MallPlus-Partner-Id: app_ck9x2mf3w0001" \
-H "X-MallPlus-Timestamp: 1713254400" \
-H "X-MallPlus-Signature: a1b2c3d4e5f6..." \
-H "Content-Type: application/json" \
-d '{"reason": "Item was used, no longer eligible for return"}'Approve Refund
/open/v1/returns/:id/approve-refundScope: orders:write Release the refund for a return. Use this after the seller confirms the returned goods were received — it transitions the return to refunded. This is distinct from Approve Return, which accepts the RMA and signals the buyer to ship the goods back.
Example Request
curl -X POST "https://api.mallplus.com/open/v1/returns/ret_abc123/approve-refund" \ -H "X-MallPlus-Partner-Id: app_ck9x2mf3w0001" \ -H "X-MallPlus-Timestamp: 1713254400" \ -H "X-MallPlus-Signature: a1b2c3d4e5f6..."
Example Response
{
"success": true,
"data": {
"id": "ret_abc123",
"orderId": "ORD-SAMPLE-001",
"status": "refunded",
"reason": "Item received damaged",
"refundAmount": 129900,
"created_at": "2026-04-14T10:00:00Z"
}
}Dispute Return
/open/v1/returns/:id/disputeScope: orders:write Dispute a return request that the seller considers invalid — for example the returned goods never arrived, the return window has elapsed, or the item was already refunded. The return transitions to disputed and a return.disputed webhook is fired. Provide a structured reasonCode from the Dispute Reason Codes list; an optional free-text note may be added for context.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| reasonCode | string | Yes | One of the codes from GET /open/v1/returns/dispute-reasons. |
| note | string | No | Free-text context for the dispute (max 500 chars). |
Example Request
curl -X POST "https://api.mallplus.com/open/v1/returns/ret_abc123/dispute" \
-H "X-MallPlus-Partner-Id: app_ck9x2mf3w0001" \
-H "X-MallPlus-Timestamp: 1713254400" \
-H "X-MallPlus-Signature: a1b2c3d4e5f6..." \
-H "Content-Type: application/json" \
-d '{
"reasonCode": "ITEM_NOT_RECEIVED",
"note": "Tracking shows the parcel was returned to sender, not delivered."
}'Example Response
{
"success": true,
"data": {
"id": "ret_abc123",
"orderId": "ORD-SAMPLE-001",
"status": "disputed",
"reason": "Item received damaged",
"dispute_reason_code": "ITEM_NOT_RECEIVED",
"dispute_note": "Tracking shows the parcel was returned to sender, not delivered.",
"created_at": "2026-04-14T10:00:00Z"
}
}Dispute Reason Codes
/open/v1/returns/dispute-reasonsScope: orders:readReturns the catalogue of reason codes accepted by the Dispute Return endpoint. Use this to populate the picker in your integration UI.
Example Response
{
"success": true,
"data": [
{
"code_id": "ITEM_NOT_RECEIVED",
"code": "ITEM_NOT_RECEIVED",
"label": "Item not received",
"description": "The returned goods never arrived at the seller\u2019s warehouse."
},
{
"code_id": "ITEM_RETURNED_IN_DIFFERENT_CONDITION",
"code": "ITEM_RETURNED_IN_DIFFERENT_CONDITION",
"label": "Item returned in different condition",
"description": "The item was used, damaged, or altered before being returned."
},
{
"code_id": "RETURN_PAST_DEADLINE",
"code": "RETURN_PAST_DEADLINE",
"label": "Return past deadline",
"description": "The return window for this item has already elapsed."
},
{
"code_id": "INVALID_RETURN_REASON",
"code": "INVALID_RETURN_REASON",
"label": "Invalid return reason",
"description": "The stated return reason does not match the actual condition of the item."
},
{
"code_id": "ITEM_ALREADY_REFUNDED",
"code": "ITEM_ALREADY_REFUNDED",
"label": "Item already refunded",
"description": "A refund for this item has already been issued."
},
{
"code_id": "OTHER",
"code": "OTHER",
"label": "Other",
"description": "A reason not covered by the codes above. A note is recommended."
}
]
}