Pagination¶
Every list the API serves is bounded. A collection — anything that grows as you use the product: workspaces, projects, audits, comments, activity, API keys, members — is returned one page at a time, in the same shape on every product namespace.
Request¶
| Parameter | Meaning |
|---|---|
page_size |
Items per page. Default 50, maximum 200. A larger value is clamped to 200, never refused; the page tells you the size it actually used. |
page_token |
The next_page_token from the previous page. Omit it to start from the first page. |
| filters | Each collection's own typed filters (project_id, status, …), documented per endpoint in the reference. |
Response¶
{
"data": [ { "id": "…" } ],
"has_more": true,
"next_page_token": "eyJhIjpbIjIwMjYtMDktMzAi…",
"page_size": 50
}
When there is a next page the response also carries an RFC 8288 header, so generic HTTP tooling can follow it without reading the body:
The target is a relative reference (query only): resolve it against the URL you called.
has_more is authoritative. next_page_token is null on the last page. total_size appears
only on the few collections where the count is free; do not rely on it.
A page can be short — even empty — before the end
Some lists are filtered by what you may see. To keep every request cheap, the service reads
a bounded number of rows per request; if few of them are visible to you, the page comes back
with fewer than page_size items — possibly none — and has_more: true. Keep following
next_page_token. Never treat a short or empty page as the end of the list, and never treat
an empty page with has_more: true as "no results".
Walking every page¶
URL="https://api.trilocore.ai/api/v1/workspaces/$WORKSPACE_ID/audits?page_size=200"
TOKEN=""
while :; do
PAGE=$(curl -sf "$URL${TOKEN:+&page_token=$TOKEN}" \
-H "Authorization: Bearer $TRILOCORE_API_KEY")
echo "$PAGE" | jq -c '.data[]'
TOKEN=$(echo "$PAGE" | jq -r '.next_page_token // empty')
[ -z "$TOKEN" ] && break
done
import os
import httpx
def every(path, **filters):
params = {**filters, "page_size": 200}
with httpx.Client(base_url="https://api.trilocore.ai",
headers={"Authorization": f"Bearer {os.environ['TRILOCORE_API_KEY']}"}) as http:
while True:
page = http.get(path, params=params).raise_for_status().json()
yield from page["data"]
if not page["next_page_token"]:
return
params["page_token"] = page["next_page_token"]
Rules for tokens¶
- Opaque. Never parse or build a token; its format can change without notice.
- Bound to the query. A token only works with the same filters and the same caller
that produced it. Change a filter and start again without
page_token; otherwise the answer is400page_token_filter_mismatch. - Short-lived. A token is valid for 3 days. An expired, altered or foreign token is
400invalid_page_token, never a silent restart from page one. - Not a permission. Every page is authorized again. A token carries a position, never access.
- Stable under change. Pages are keyset-ordered: an item that exists for the whole walk is returned exactly once. Items created or deleted while you walk may or may not appear. Lists ordered by last update (audit reports, publications, the contract inventory) are the one exception: an item edited while you walk moves, so it may be skipped or returned twice.
- Long tokens are normal. A token can be up to 2048 characters (lists ordered by a name carry that name); send it back unchanged.
Lists that are not paginated¶
Some endpoints return an array that is not a growing collection. Each still has a fixed bound:
| Kind | Examples | Bound |
|---|---|---|
| Catalogues | compiler versions, templates, toolchains, rules, prices | a small server-defined set |
| One resource's own parts | a report's findings, a contract's ABI, a file tree, SARIF | that resource's size limit (for example ≤ 500 findings per report) |
| Change feeds | execution events, analysis-job events, note events | resume with after=<last id>; each response is capped |
| Windows over one document | a target's CFG blocks | offset + limit, capped per request |
Radar contract search (POST /api/v1/radar/code/search) pages with page_size / page_token in
the request body, up to 500 results per page.