Skip to content
APIv1
Menu

Pagination

Cursor pagination on GET /v1/shipments. Follow nextCursor until it is null.

View as markdown

GET /v1/shipments returns one page at a time, most recently updated first:

JSON
{
  "data": [{ "reference": "QB51907", "status": "Active", "…": "…" }],
  "nextCursor": "eyJ1IjoiMjAyNi0wOS0xNVQyMTo0ODowMFoiLCJyIjoiUUI1MTkwNyJ9"
}
ParameterMeaning
limitPage size, 1–100. Default 50.
cursorThe nextCursor value of the previous response, unchanged.

Rules

  • Next page: repeat the request with the same filters and cursor set to the previous nextCursor.
  • nextCursor: null means this is the last page.
  • Cursors are opaque.
  • An unusable cursor returns 400 invalid_cursor. Restart without cursor.
  • There is no total count and no page numbers.
  • A shipment that changes while you paginate moves to the front, so it can appear twice or be skipped within one run. Upsert by reference and poll with updatedSince.

Filters

All filters are optional and combine with AND.

ParameterMeaning
statusOne of Active, Delivered, Cancelled. Repeat it to match any of several: ?status=Active&status=Delivered.
updatedSinceISO 8601 timestamp. Shipments whose updatedAt is at or after it.
createdSinceISO 8601 timestamp. Shipments whose createdAt is at or after it.
tagExact match on one of the customer's own tags (PO numbers).
searchFree text across the reference, tags, master bill / air waybill numbers, container numbers, and Amazon FBA and reference IDs.

An invalid value returns 400 invalid_parameter naming the parameter; the hint lists the allowed values.

Read every page

TypeScript
const BASE_URL = 'https://api.gocubic.io/v1';
const headers = { Authorization: `Bearer ${process.env.CUBIC_API_KEY}` };

const shipments = [];
let cursor: string | null = null;
do {
  const url = new URL(`${BASE_URL}/shipments`);
  url.searchParams.set('limit', '100');
  url.searchParams.set('status', 'Active');
  if (cursor) url.searchParams.set('cursor', cursor);

  const response = await fetch(url, { headers });
  if (!response.ok) throw new Error(JSON.stringify(await response.json()));
  const page = await response.json();

  shipments.push(...page.data);
  cursor = page.nextCursor;
} while (cursor);

console.log(`${shipments.length} active shipments`);
Python
import os

import requests

BASE_URL = "https://api.gocubic.io/v1"
headers = {"Authorization": f"Bearer {os.environ['CUBIC_API_KEY']}"}

shipments = []
params = {"limit": 100, "status": "Active"}
while True:
    response = requests.get(f"{BASE_URL}/shipments", headers=headers, params=params, timeout=30)
    response.raise_for_status()
    page = response.json()
    shipments.extend(page["data"])
    if page["nextCursor"] is None:
        break
    params["cursor"] = page["nextCursor"]

print(f"{len(shipments)} active shipments")

The client in Recipes wraps this loop and adds 429 backoff.