Pagination
List endpoints take limit and offset. paginate is an async generator that requests one page at a time and yields each item. collectAll runs the same loop and returns all items as an array.
Options
| Option | Type | Default | Description |
|---|---|---|---|
fetchPage | (offset, limit) => Promise<R> | required | Fetches one page |
extractItems | (response) => T[] | reads data.results, then results | Returns the items on the page |
extractNext | (response) => string | null | undefined | reads data.next, then next | Returns a truthy value while more pages remain |
extractCount | (response) => number | reads data.count, then count | Accepted, but the loop does not use it |
limit | number | 100 | Items per page |
The loop stops when extractNext returns a falsy value or a page has fewer than limit items. The default extractors read results and next, which no SpatialFlow list response has, so every example below passes extractItems and extractNext. Without them the loop yields nothing and stops after the first request.
Each endpoint accepts a maximum limit: 500 for geofences (larger values are capped), 200 for webhooks, and 100 for workflows, webhook deliveries, and device events. A larger limit on workflows, deliveries, or events is rejected. The default of 100 is valid for all of them.
Geofences
The geofence list response has geofences, a count for the page, and a total_count. It has no next field and no has_more flag, so extractNext returns any non-empty string while the page has items. A short page ends the loop, and when the total is an exact multiple of limit the last request returns an empty page.
import {SpatialFlow, paginate} from '@spatialflow/sdk';
const client = new SpatialFlow({apiKey: process.env.SPATIALFLOW_API_KEY});
for await (const geofence of paginate({
fetchPage: (offset, limit) => client.geofences.appsGeofencesApiListGeofences(limit, offset),
extractItems: (response) => response.data.geofences,
extractNext: (response) => (response.data.geofences.length > 0 ? 'more' : null),
limit: 100,
})) {
console.log(geofence.name);
}
Collect into an array
import {SpatialFlow, collectAll} from '@spatialflow/sdk';
const client = new SpatialFlow({apiKey: process.env.SPATIALFLOW_API_KEY});
const geofences = await collectAll({
fetchPage: (offset, limit) => client.geofences.appsGeofencesApiListGeofences(limit, offset),
extractItems: (response) => response.data.geofences,
extractNext: (response) => (response.data.geofences.length > 0 ? 'more' : null),
});
console.log(`Found ${geofences.length} geofences`);
collectAll holds every item in memory. Use paginate for large result sets.
Workflows
The workflow list response has workflows, total, page, and page_size, where page is offset / limit + 1 and page_size is the limit you sent. Another page remains while page * page_size < total.
import {SpatialFlow, paginate} from '@spatialflow/sdk';
const client = new SpatialFlow({apiKey: process.env.SPATIALFLOW_API_KEY});
for await (const workflow of paginate({
fetchPage: (offset, limit) => client.workflows.appsWorkflowsApiListWorkflows(limit, offset),
extractItems: (response) => response.data.workflows,
extractNext: (response) =>
response.data.page * response.data.page_size < response.data.total ? 'more' : null,
})) {
console.log(workflow.name);
}
Webhooks and deliveries
The webhook list response has webhooks and a pagination object with total, limit, offset, and has_more. The delivery list has deliveries and the same pagination object. Use has_more. These endpoints accept only an access token.
import {SpatialFlow, paginate} from '@spatialflow/sdk';
const client = new SpatialFlow({accessToken: process.env.SPATIALFLOW_ACCESS_TOKEN});
for await (const webhook of paginate({
fetchPage: (offset, limit) => client.webhooks.appsWebhooksApiListWebhooks(limit, offset),
extractItems: (response) => response.data.webhooks,
extractNext: (response) => (response.data.pagination.has_more ? 'more' : null),
})) {
console.log(webhook.name);
}
const webhookId = '3f1b6a52-0000-0000-0000-000000000000';
for await (const delivery of paginate({
fetchPage: (offset, limit) =>
client.webhooks.appsWebhooksApiGetWebhookDeliveries(webhookId, limit, offset),
extractItems: (response) => response.data.deliveries,
extractNext: (response) => (response.data.pagination.has_more ? 'more' : null),
})) {
console.log(delivery.id);
}
Device events
The device events endpoint returns a plain array and reports whether more remain in the X-Has-More response header. Axios lowercases header names.
import {SpatialFlow, paginate} from '@spatialflow/sdk';
const client = new SpatialFlow({apiKey: process.env.SPATIALFLOW_API_KEY});
const deviceUuid = '3f1b6a52-0000-0000-0000-000000000000';
for await (const event of paginate({
fetchPage: (offset, limit) =>
client.devices.appsDevicesApiGetDeviceEvents(deviceUuid, limit, offset),
extractItems: (response) => response.data,
extractNext: (response) => (response.headers['x-has-more'] === 'true' ? 'more' : null),
})) {
console.log(event.id);
}
Endpoints that are not paginated
appsDevicesApiListDevices, the integrations list, and the storage file list take no limit or offset. Call them directly instead of using paginate. The devices and integrations lists return every result in one response. The storage file list returns at most 1,000 files of a type and doesn't say when it stops short.