All Zenoo API list endpoints use cursor-based pagination. This provides stable, performant pagination even on large datasets with concurrent modifications.
| Parameter | Type | Default | Description |
|---|
cursor | string | null | Pagination cursor from previous response |
limit | number | 25 | Results per page (min 1, max 100) |
# First page
curl -X GET "https://api.zenoo.com/v1/alerts?status=Open&limit=25" \
-H "Authorization: Bearer your-api-key"
# Next page
curl -X GET "https://api.zenoo.com/v1/alerts?status=Open&limit=25&cursor=eyJpZCI6ImFsdF8wMjUiLCJzIjoiMjAyNi0wMi0xNlQxMDowMDowMFoifQ" \
-H "Authorization: Bearer your-api-key"
Every list response includes a meta.page object:
{
"data": [
{ "token": "alt_001", "title": "PEP Match: John Doe", "status": "Open" },
{
"token": "alt_002",
"title": "Sanctions Hit: Acme Corp",
"status": "Open"
}
],
"meta": {
"total": 142,
"page": {
"cursor": "eyJpZCI6ImFsdF8wMjUiLCJzIjoiMjAyNi0wMi0xNlQxMDowMDowMFoifQ",
"has_more": true
}
}
}
| Field | Type | Description |
|---|
meta.total | number | Total count of records matching the query |
meta.page.cursor | string | Opaque cursor to pass for the next page. null if no more pages. |
meta.page.has_more | boolean | Whether more results exist beyond this page |
Full iteration example
import requests
def get_all_alerts(status="Open"):
url = "https://api.zenoo.com/v1/alerts"
headers = {"Authorization": "Bearer your-api-key"}
params = {"status": status, "limit": 100}
all_alerts = []
while True:
response = requests.get(url, headers=headers, params=params)
data = response.json()
all_alerts.extend(data["data"])
if not data["meta"]["page"]["has_more"]:
break
params["cursor"] = data["meta"]["page"]["cursor"]
return all_alerts
alerts = get_all_alerts()
print(f"Total: {len(alerts)} alerts")
Sorting and filtering
Cursors are stable across sort orders and filters. You can combine pagination with any sort or filter parameter:
# Paginate open alerts sorted by priority (descending)
curl -X GET "https://api.zenoo.com/v1/alerts?status=Open&sort=-priority_score&limit=25&cursor=eyJ..." \
-H "Authorization: Bearer your-api-key"
# Paginate case audit logs filtered by date
curl -X GET "https://api.zenoo.com/v1/cases/cas_xyz789/audit-logs?from=2026-01-01T00:00:00Z&limit=50&cursor=eyJ..." \
-H "Authorization: Bearer your-api-key"
Do not modify the sort or filter parameters between paginated requests. Changing filters while iterating may cause duplicate or missing results. Start a new pagination sequence if you need different filters.
| Endpoint | Default limit | Max limit |
|---|
GET /v1/alerts | 25 | 100 |
GET /v1/cases | 25 | 100 |
GET /v1/cases/{token}/alerts | 25 | 100 |
GET /v1/cases/{token}/checks | 25 | 100 |
GET /v1/cases/{token}/entities | 25 | 100 |
GET /v1/cases/{token}/audit-logs | 50 | 200 |
GET /v1/cases/{token}/comments | 25 | 100 |
GET /v1/entities | 25 | 100 |
GET /v1/audit-logs | 50 | 200 |
Cursor-based pagination has advantages over offset-based (?page=2&per_page=25) pagination:
| Aspect | Cursor-based | Offset-based |
|---|
| Performance | O(1) — seeks directly to position | O(n) — scans and skips rows |
| Consistency | Stable under concurrent inserts/deletes | Rows shift, causing duplicates/gaps |
| Deep pages | Same speed for page 1 and page 1000 | Degrades linearly with offset |
Next steps