Pagination
List endpoints return results one page at a time using cursor-based pagination. Results are ordered by document id, which is stable as the underlying data changes.
Request parameters
| Parameter | Description |
|---|---|
limit | Maximum items per page. Default 50, maximum 200. |
cursor | Opaque token from a previous response's next_cursor. Omit it for the first page. |
Response shape
Every list response wraps its results in the same envelope:
{
"items": [
{ "id": "7Hb2Kp9QvL3mNx0R8tZ4", "name": "Acme Podcast Network" }
],
"next_cursor": "eyJpZCI6IjdIYjJLcDlRdkwzbU54MFI4dFo0In0"
}
items— the page of results.next_cursor— pass this back as?cursor=to fetch the next page. When it isnull, you have reached the last page.
Treat the cursor as opaque
Do not parse, construct, or modify the cursor. Pass back exactly what you received. Its format may change without notice.
Iterating all pages
Follow next_cursor until it comes back null:
- cURL
- Python
- Node.js
- Go
- Java
cursor=""
while : ; do
resp=$(curl -s -G "https://api.adbridge.ai/v1/networks" \
--data-urlencode "limit=100" \
--data-urlencode "cursor=$cursor" \
-H "Authorization: Bearer $ADBRIDGE_API_KEY")
echo "$resp" | jq -c '.items[]'
cursor=$(echo "$resp" | jq -r '.next_cursor // empty')
[ -z "$cursor" ] && break
done
import os
import requests
def iterate(path, **params):
cursor = None
while True:
resp = requests.get(
f"https://api.adbridge.ai{path}",
headers={"Authorization": f"Bearer {os.environ['ADBRIDGE_API_KEY']}"},
params={**params, "cursor": cursor},
)
resp.raise_for_status()
page = resp.json()
yield from page["items"]
cursor = page.get("next_cursor")
if not cursor:
break
for network in iterate("/v1/networks", limit=100):
print(network["id"])
async function* iterate(path, params = {}) {
let cursor = undefined;
do {
const url = new URL(`https://api.adbridge.ai${path}`);
for (const [k, v] of Object.entries(params)) url.searchParams.set(k, v);
if (cursor) url.searchParams.set("cursor", cursor);
const resp = await fetch(url, {
headers: { Authorization: `Bearer ${process.env.ADBRIDGE_API_KEY}` },
});
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
const page = await resp.json();
yield* page.items;
cursor = page.next_cursor;
} while (cursor);
}
for await (const network of iterate("/v1/networks", { limit: 100 })) {
console.log(network.id);
}
type page struct {
Items []json.RawMessage `json:"items"`
NextCursor string `json:"next_cursor"`
}
cursor := ""
for {
u, _ := url.Parse("https://api.adbridge.ai/v1/networks")
q := u.Query()
q.Set("limit", "100")
if cursor != "" {
q.Set("cursor", cursor)
}
u.RawQuery = q.Encode()
req, _ := http.NewRequest(http.MethodGet, u.String(), nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("ADBRIDGE_API_KEY"))
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
var p page
json.NewDecoder(resp.Body).Decode(&p)
resp.Body.Close()
for _, item := range p.Items {
fmt.Println(string(item))
}
if p.NextCursor == "" {
break
}
cursor = p.NextCursor
}
HttpClient client = HttpClient.newHttpClient();
ObjectMapper mapper = new ObjectMapper();
String cursor = null;
do {
String uri = "https://api.adbridge.ai/v1/networks?limit=100"
+ (cursor != null ? "&cursor=" + URLEncoder.encode(cursor, StandardCharsets.UTF_8) : "");
HttpResponse<String> resp = client.send(
HttpRequest.newBuilder(URI.create(uri))
.header("Authorization", "Bearer " + System.getenv("ADBRIDGE_API_KEY"))
.GET().build(),
HttpResponse.BodyHandlers.ofString());
JsonNode page = mapper.readTree(resp.body());
page.get("items").forEach(item -> System.out.println(item.get("id").asText()));
JsonNode next = page.get("next_cursor");
cursor = (next != null && !next.isNull()) ? next.asText() : null;
} while (cursor != null);
An invalid or malformed cursor returns 400 Bad Request with the standard error envelope.