Pagination
Cursor pagination of Slicer API lists — the limit and cursor parameters, the nextCursor field and examples that walk through every page.
Long lists — projects and wallet transactions — come in pages. Pagination is cursor-based: each page tells you where the next one starts, and you simply pass that value to the next request.
Parameters and response
| Parameter | Value |
|---|---|
limit | page size, 1 to 100; 20 by default |
cursor | the nextCursor value from the previous page; omit it for the first page |
{
"ok": true,
"data": {
"items": [
{ "id": 318, "title": "A reel in 3 minutes", "status": "succeeded" },
{ "id": 311, "title": "New collection overview", "status": "succeeded" }
],
"nextCursor": "Mg"
}
}nextCursor: null means there are no more pages. A cursor is an opaque string: don't parse it or build it yourself. A
damaged cursor gets 400 bad_cursor.
Paginated lists:
GET /v1/projects— projects, newest first; filtersstatus(all,ready,active,failed,draft— drafts of projects without the AI director) andq— search by title;GET /v1/wallet/transactions— wallet transactions, newest first.
Other lists (versions, project history, publications, webhooks, deliveries) are short and come as a plain array.
Walk through every page
CURSOR=""
while :; do
PAGE=$(curl -s "https://api.slicer.media/v1/projects?limit=100&status=ready${CURSOR:+&cursor=$CURSOR}" \
-H "Authorization: Bearer $SLICER_TOKEN")
echo "$PAGE" | jq -r '.data.items[] | "\(.id)\t\(.title)"'
CURSOR=$(echo "$PAGE" | jq -r '.data.nextCursor // empty')
[ -z "$CURSOR" ] && break
doneasync function* allProjects(params = {}) {
let cursor = null;
do {
const query = new URLSearchParams({ limit: '100', ...params, ...(cursor ? { cursor } : {}) });
const response = await fetch(`https://api.slicer.media/v1/projects?${query}`, {
headers: { Authorization: `Bearer ${process.env.SLICER_TOKEN}` },
});
const json = await response.json();
if (!json.ok) throw new Error(`${json.error.code}: ${json.error.message}`);
yield* json.data.items;
cursor = json.data.nextCursor;
} while (cursor);
}
for await (const project of allProjects({ status: 'ready' })) {
console.log(project.id, project.title);
}import os
import requests
def all_projects(**params):
session = requests.Session()
session.headers["Authorization"] = f"Bearer {os.environ['SLICER_TOKEN']}"
cursor = None
while True:
query = {"limit": 100, **params, **({"cursor": cursor} if cursor else {})}
body = session.get("https://api.slicer.media/v1/projects", params=query, timeout=60).json()
if not body["ok"]:
raise RuntimeError(f"{body['error']['code']}: {body['error']['message']}")
yield from body["data"]["items"]
cursor = body["data"]["nextCursor"]
if not cursor:
break
for project in all_projects(status="ready"):
print(project["id"], project["title"])