Guide

API conventions

Pagination, dates, identifiers, location and threshold formats, error shapes and async operations. The rules that apply across every endpoint.

·7 min read ·Updated 3 Sep 2026

These rules hold across the whole API. Learning them once saves reading them 74 times in the reference.

Pagination

List endpoints take page and page_size query parameters.

curl -s "https://api.stockpilot.dev/inventory?page=2&page_size=500" \
  -H "X-CLIENT-ID: $SP_CLIENT_ID" \
  -H "X-CLIENT-SECRET: $SP_CLIENT_SECRET"

page starts at 1. page_size defaults to 100 and caps at 1000.

{
  "count": 1284,
  "page": 2,
  "page_size": 500,
  "results": [ ]
}

Walk pages until a page returns fewer results than you asked for:

def all_pages(client, path, page_size=1000, **params):
    page = 1
    while True:
        data = client.get(path, params={**params, "page": page, "page_size": page_size}).json()
        yield from data["results"]
        if len(data["results"]) < page_size:
            return
        page += 1

GET /returns paginates differently. Its next and previous fields are booleans, not URLs, and you page with current_page and total_pages. Its status filters are lowercase (requested, partly_accepted, accepted) even though the statuses themselves are returned uppercase, and its page_size caps at 100. See sales channels and returns.

Identifying a product

Endpoints that look up a single product accept exactly one of id, sku or barcode.

curl -s "https://api.stockpilot.dev/inventory/get?sku=TSHIRT-BLK-M"  # good
curl -s "https://api.stockpilot.dev/inventory/get?id=90211"          # good
curl -s "https://api.stockpilot.dev/inventory/get?sku=X&id=90211"    # error

Passing none or more than one is a client error, not a silent preference for whichever came first.

Dates and times

Dates are ISO YYYY-MM-DD. Timestamps are ISO 8601 with a timezone offset.

2026-09-03
2026-09-03T09:14:22.481Z

Analytics endpoints take from and to as plain dates. Webhook envelopes carry event_triggered_at as a full timestamp.

Locations

Warehouse locations are hierarchical bins, written as aisle, rack, shelf:

A1-001-01

The format is a string, not a structured object. Match on it literally rather than parsing it into parts unless you know how a specific warehouse is laid out.

Thresholds

A reorder threshold is either a number of units or a number of weeks of cover:

ValueMeaning
5uFive units
33wThirty three weeks of stock cover, based on measured demand

The weeks form is what makes a fast selling SKU trigger long before a slow one at the same unit count.

Order statuses

open, pending, on-hold, completed, cancelled

Filter list calls with ?status=open. Note that the Stockpilot CLI’s status command reports on open orders specifically.

Errors

Every error returns JSON with a detail or an error key, alongside the HTTP status.

{ "detail": "Product not found for sku 'DOES-NOT-EXIST'" }

A robust client checks the status before parsing:

resp = client.get("/inventory/get", params={"sku": sku})
if resp.is_error:
    raise StockpilotError(resp.status_code, resp.json().get("detail", resp.text))

Asynchronous operations

Three things in the API are too slow to answer inline, and all follow the same start then poll shape:

StartPollReturns
POST /shipping/request-labelPOST /shipping/retrieve-labelLabel PDF and tracking metadata
POST /purchase-orders/recommendationsGET /purchase-orders/recommendations/status/{task_id}Recommended order lines
POST /sales-channels/sync-listingsChannel state via GET /sales-channelsSync outcome

The start call returns a handle (entity_id or task_id) rather than a result. Back off between polls: all three sit in the heavy rate limit bucket at 20 requests per minute.

What is not there

Worth knowing so you do not go looking:

  • No Idempotency-Key header. Which calls are safe to retry is covered in rate limits and idempotency.
  • No cursor pagination. Offset paging only.
  • No field selection or sparse responses. Endpoints return their full shape.
  • No bulk write endpoints. Loop, and pace yourself against the write bucket.
A Stockpilot engineer talking through an integration with a developer

Stuck on something

Ask a person, not a search box

The API surface is wide, and some of it only makes sense once someone explains why it works that way. If a payload is not doing what you expect, or you are weighing two approaches, say so and we will look at it with you.