Pagination
List endpoints in the ConsentForge API use cursor-based pagination. This ensures stable, consistent results even when new records are added while you're paginating.
Request parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | integer | 50 | Number of results per page (max 500) |
cursor | string | — | Cursor from the previous response's next_cursor field |
Response format
All list endpoints return a consistent envelope:
{
"data": [...],
"meta": {
"total": 12483,
"limit": 50,
"next_cursor": "cur_eyJpZCI6InJlY18wMTkzIn0",
"has_more": true
}
}
| Field | Description |
|---|---|
data | Array of results for this page |
meta.total | Total matching records (approximate for large sets) |
meta.limit | The limit applied to this page |
meta.next_cursor | Opaque cursor — pass as cursor on the next request |
meta.has_more | true if more pages exist |
When has_more is false, you have reached the last page.
Example: paginating receipts
GET /api/v1/receipts?property_id=prop_abc&limit=100
Authorization: Bearer cf_api_live_YOUR_TOKEN
Response:
{
"data": [
{
"id": "rec_0001",
"property_id": "prop_abc",
"timestamp": "2026-03-09T12:00:00Z",
"choices": { "analytics": true, "marketing": false },
"policy_version": 3
}
],
"meta": {
"total": 8201,
"limit": 100,
"next_cursor": "cur_eyJpZCI6InJlY18wMTAwIn0",
"has_more": true
}
}
Fetch the next page:
GET /api/v1/receipts?property_id=prop_abc&limit=100&cursor=cur_eyJpZCI6InJlY18wMTAwIn0
Authorization: Bearer cf_api_live_YOUR_TOKEN
Code example: fetch all pages
- JavaScript
- Python
async function fetchAllReceipts(propertyId, apiKey) {
const results = [];
let cursor = null;
do {
const params = new URLSearchParams({ property_id: propertyId, limit: '500' });
if (cursor) params.set('cursor', cursor);
const res = await fetch(`https://api.consentforge.com/api/v1/receipts?${params}`, {
headers: { Authorization: `Bearer ${apiKey}` }
});
const page = await res.json();
results.push(...page.data);
cursor = page.meta.has_more ? page.meta.next_cursor : null;
} while (cursor);
return results;
}
import requests
def fetch_all_receipts(property_id, api_key):
results = []
cursor = None
base = 'https://api.consentforge.com/api/v1/receipts'
headers = {'Authorization': f'Bearer {api_key}'}
while True:
params = {'property_id': property_id, 'limit': 500}
if cursor:
params['cursor'] = cursor
resp = requests.get(base, params=params, headers=headers)
resp.raise_for_status()
page = resp.json()
results.extend(page['data'])
if not page['meta']['has_more']:
break
cursor = page['meta']['next_cursor']
return results
Paginated endpoints
| Endpoint | Default limit | Max limit |
|---|---|---|
GET /api/v1/receipts | 50 | 500 |
GET /api/v1/properties | 50 | 100 |
GET /api/v1/vendors | 100 | 500 |
GET /api/v1/webhooks | 50 | 100 |
GET /api/v1/scan-findings | 100 | 500 |
Filtering
Most list endpoints support filtering. Filters combine with pagination:
GET /api/v1/receipts?property_id=prop_abc&from=2026-01-01T00:00:00Z&to=2026-02-01T00:00:00Z&limit=100
Common filter parameters:
| Parameter | Type | Description |
|---|---|---|
from | ISO 8601 | Filter records after this timestamp |
to | ISO 8601 | Filter records before this timestamp |
property_id | string | Scope to a specific property |
user_id | string | Scope to a specific user hash |
event | string | Filter by event type (webhooks) |