API
Pagination
The ShipPulse API supports offset-based pagination for list endpoints. All list responses include metadata to help you fetch subsequent pages.
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| limit | integer | 20 | Number of results per page. Max 100. |
| offset | integer | 0 | Number of results to skip before returning. |
| order | string | desc | Sort direction: asc or desc. Sorted by created_at. |
| cursor | string | — | Opaque cursor for cursor-based pagination (where supported). |
Offset pagination
Most list endpoints use offset pagination. Pass limit and offset query parameters:
bash
# Page 1: first 20
GET /api/v1/testimonials?limit=20&offset=0
# Page 2: next 20
GET /api/v1/testimonials?limit=20&offset=20
# Page 3
GET /api/v1/testimonials?limit=20&offset=40Response shape
json
{
"data": [...],
"meta": {
"total": 143,
"count": 20,
"limit": 20,
"offset": 0,
"has_more": true
}
}| Field | Description |
|---|---|
| meta.total | Total number of items matching the query (before pagination) |
| meta.count | Number of items in this response |
| meta.limit | The limit that was applied |
| meta.offset | The offset that was applied |
| meta.has_more | true if there are more results after this page |
Cursor pagination (real-time feeds)
For real-time feeds like changelog entries or subscriber lists, cursor-based pagination is more reliable than offset — it avoids missing or duplicating items when new rows are inserted between requests.
bash
# First page
GET /api/v1/changelog?limit=20
# Response includes next_cursor when has_more is true
# { "meta": { "has_more": true, "next_cursor": "eyJpZCI6IjEyMyJ9" } }
# Next page: pass cursor
GET /api/v1/changelog?limit=20&cursor=eyJpZCI6IjEyMyJ9Cursor response shape
json
{
"data": [...],
"meta": {
"count": 20,
"limit": 20,
"has_more": true,
"next_cursor": "eyJpZCI6IjEyMyJ9",
"prev_cursor": null
}
}Cursors are opaque base64 strings. Do not parse or construct them — always use the value returned by the previous response.
Fetching all pages (JavaScript)
To fetch all results across multiple pages, iterate until has_more is false:
typescript
async function fetchAll<T>(
baseUrl: string,
apiKey: string,
pageSize = 100,
): Promise<T[]> {
const results: T[] = [];
let offset = 0;
while (true) {
const url = `${baseUrl}?limit=${pageSize}&offset=${offset}`;
const res = await fetch(url, {
headers: { Authorization: `Bearer ${apiKey}` },
});
const { data, meta } = await res.json();
results.push(...data);
if (!meta.has_more) break;
offset += pageSize;
}
return results;
}
// Example
const all = await fetchAll(
"https://shippulse.dev/api/v1/testimonials",
"sp_your_api_key",
);