Skip to content
SIBISIBI Developers
Esc
navigateopen⌘Jpreview
On this page

Returns Guide

Check what an order line can be returned, then open a return request

The Returns API lets you check whether the lines of an order can be returned and open a return request for the ones that can. A request opens with every line PENDING; Sibi staff then approve or deny each line, and the outcome arrives on webhooks — the API itself only requests and reads.

Benefits

  • Check before you ask: See per-line returnability, the window that applies, and any conditions before opening a request
  • Return part of an order: A request covers one or more lines, each with its own quantity, condition, and reason
  • Per-line outcomes: Staff approve or deny each line independently, so one request can end with some lines approved and others denied
  • Know the result: Approvals and denials arrive on the return-request webhook events

Core Concepts

Return Eligibility

Per-line returnability for an order: whether each line can be returned, the policy window, and any conditions that apply at intake.

Return Request

A request to return one or more lines of an order. It has no request-level status — status is per line.

Item Status

Each requested line is PENDING, APPROVED, or DENIED, derived from the latest decision on it.

Decisions

Sibi staff approve or deny each line. The outcome is announced on the return-request webhook events.

Checking Eligibility

GET https://api.sibipro.com/orders/{orderId}/returns/eligibility with a read:returns scoped REST API token. The response is index-aligned to the order’s line items: entry index is the verdict for that position in the order.

curl \
  --request GET \
  --header 'Authorization: Bearer <YOUR_API_KEY>' \
  'https://api.sibipro.com/orders/SIBI-12345678/returns/eligibility'
const response = await fetch(
  `https://api.sibipro.com/orders/${encodeURIComponent(orderId)}/returns/eligibility`,
  { headers: { Authorization: `Bearer ${yourApiKey}` } },
);
const { items } = await response.json();
{
  "items": [
    {
      "index": 0,
      "orderLineItemId": "OLI-0001",
      "productId": "GDF510PSRSS",
      "status": "RETURNABLE",
      "isReturnable": true,
      "reasons": [],
      "conditions": [{ "code": "MUST_BE_UNOPENED", "message": "Item must be unopened." }],
      "policy": {
        "partner": "ge",
        "windowDays": 30,
        "daysRemaining": 12,
        "windowEndsAt": "2026-09-16T00:00:00.000Z",
        "restockingFee": "5–10% restocking fee",
        "summary": "Unopened appliances may be returned within 30 days of delivery."
      }
    }
  ]
}

A status of RETURNABLE means the line can be returned (check conditions for caveats verified at intake); NOT_RETURNABLE means it cannot (see reasons); UNKNOWN means no policy answer — route it to support.

Opening a Return Request

POST https://api.sibipro.com/orders/{orderId}/returns with a create:returns scoped token. The body names the lines to return; each line carries a quantity, a condition, and a requestReason.

curl \
  --request POST \
  --header 'Authorization: Bearer <YOUR_API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{
    "items": [
      {
        "orderLineItemId": "OLI-0001",
        "quantity": 1,
        "condition": "UNOPENED",
        "requestReason": "Ordered the wrong size"
      }
    ]
  }' \
  https://api.sibipro.com/orders/SIBI-12345678/returns
const response = await fetch(`https://api.sibipro.com/orders/${encodeURIComponent(orderId)}/returns`, {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${yourApiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    items: [
      {
        orderLineItemId: 'OLI-0001',
        quantity: 1,
        condition: 'UNOPENED',
        requestReason: 'Ordered the wrong size',
      },
    ],
  }),
});
const returnRequest = await response.json();

condition is one of UNOPENED, OPENED-UNUSED, INSTALLED, or DAMAGED. A successful call returns 201 with the request; every line starts PENDING:

{
  "id": "RET-12345XYZ",
  "orderId": "SIBI-12345678",
  "createdAt": "2026-09-04T15:30:45.123Z",
  "updatedAt": "2026-09-04T15:30:45.123Z",
  "items": [
    {
      "orderLineItemId": "OLI-0001",
      "quantity": 1,
      "condition": "UNOPENED",
      "requestReason": "Ordered the wrong size",
      "status": "PENDING",
      "latestDecision": null
    }
  ]
}

Reading Return Requests

GET https://api.sibipro.com/orders/{orderId}/returns lists the return requests on an order, newest first, with a read:returns scoped token. Each item carries its per-line status, and once a line is decided, its latestDecision.

curl \
  --request GET \
  --header 'Authorization: Bearer <YOUR_API_KEY>' \
  'https://api.sibipro.com/orders/SIBI-12345678/returns'
const response = await fetch(
  `https://api.sibipro.com/orders/${encodeURIComponent(orderId)}/returns`,
  { headers: { Authorization: `Bearer ${yourApiKey}` } },
);
const { items } = await response.json();
{
  "items": [
    {
      "id": "RET-12345XYZ",
      "orderId": "SIBI-12345678",
      "createdAt": "2026-09-04T15:30:45.123Z",
      "updatedAt": "2026-09-05T09:12:03.900Z",
      "items": [
        {
          "orderLineItemId": "OLI-0001",
          "quantity": 1,
          "condition": "UNOPENED",
          "requestReason": "Ordered the wrong size",
          "status": "DENIED",
          "latestDecision": {
            "outcome": "DENIED",
            "denialReason": "Item is outside the return window",
            "decidedAt": "2026-09-05T09:12:03.900Z"
          }
        }
      ]
    }
  ]
}

An order with no return requests returns an empty items list. An empty list always means the order genuinely has none: if the return data cannot be read from an upstream dependency, the endpoint returns 503 SERVICE_UNAVAILABLE rather than an empty list (see Errors).

Learning the Outcome

Decisions are made by Sibi staff, not through this API. Subscribe to the return-request webhook events to learn when a line is approved or denied:

  • order.return-request.created — a request was opened
  • order.return-request.item-approved — a line was approved
  • order.return-request.item-denied — a line was denied

See Order Return Requests events for the payloads. You can also poll GET /orders/{orderId}/returns to read the current per-line status.

Errors

A request for a line that cannot be returned is refused with a 400 carrying one of:

Code Meaning
RETURN_INVALID_CONDITION The condition is not one of the accepted values
RETURN_INVALID_QUANTITY The quantity is not a positive whole number
RETURN_DUPLICATE_LINE The same order line appears more than once in the request
RETURN_LINE_NOT_ON_ORDER The orderLineItemId is not a line on the order
RETURN_ITEM_NOT_ELIGIBLE Policy does not allow returning this line
RETURN_QUANTITY_EXCEEDED The requested quantity exceeds what remains returnable on the line

An order that does not exist or is not visible to the caller returns 404 ORDER_NOT_FOUND on every endpoint, so the API cannot be used to discover which order ids exist. Authentication and scope failures follow the usual codes; see Making a REST Request. Every returns endpoint requires a REST API token: a token issued for the GraphQL API receives a 403 with code REST_TOKEN_REQUIRED.

If the return data is temporarily unreadable upstream, the read endpoints (GET /orders/{orderId}/returns and GET /orders/{orderId}/returns/eligibility) return 503 SERVICE_UNAVAILABLE. The order exists and is visible — only the read failed — so the request can be retried.

{
  "code": "RETURN_ITEM_NOT_ELIGIBLE",
  "message": "This item is not eligible for return."
}

Testing

The Returns API is production-only — it has no test environment. Requests to https://dev.sibi.pro/orders/{orderId}/returns*, and any request carrying the test header, are refused with 403 NOT_AVAILABLE_IN_TEST.

Endpoints

Returns endpoints

Every endpoint with parameters, response schemas, and code samples.

Was this page helpful?