API Reference > Returns API

Returns API

Last Updated: 2026-07-02

List Returns

GET/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

ParameterTypeRequiredDescription
statusstringNo Filter by return status. One of requested, approved, rejected, received, refunded. Any other value returns VALIDATION_ERROR (HTTP 400).
order_idstringNoRestrict the list to returns of a single order ID.
pageintegerNo 1-based page number for offset pagination. Ignored when cursor is supplied. Default 1.
limitintegerNo Page size. Default 20.
sortstringNo Sort direction by created timestamp: created_at_desc (newest first, default) or created_at_asc. Any other value falls back to the default.
cursorstringNo 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

GET/open/v1/returns/:idScope: orders:read

Returns the full details of a single return request, including the reason, items being returned, and current status.

Create Return

POST/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

FieldTypeRequiredDescription
orderIdstringYes The order to create a return for. Must be owned by your seller.
itemsarrayYes 1–100 line items to return. Each item: { itemId, quantity, reason? }
items[].itemIdstringYesThe order line item ID being returned.
items[].quantityintegerYes Quantity to return. Must be a positive integer (max 1,000,000).
items[].reasonstringNoPer-item return reason (max 500 chars).
reasonstringYesOverall 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

POST/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

POST/open/v1/returns/:id/rejectScope: orders:write

Reject a return request with a reason. The return must be in requested status.

Request Body

FieldTypeRequiredDescription
reasonstringYesReason 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

POST/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

POST/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

FieldTypeRequiredDescription
reasonCodestringYes One of the codes from GET /open/v1/returns/dispute-reasons.
notestringNoFree-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

GET/open/v1/returns/dispute-reasonsScope: orders:read

Returns 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."
    }
  ]
}