Conventions
Base URL, authentication, response shapes, pagination, rate limits and usage reporting shared by every Social Data API route.
Base URL and authentication
Your base URL comes with your credentials; the examples write it as {API_BASE_URL}. Send your API token as a Bearer token on every request:
curl -G {API_BASE_URL}/v1/stats \
-H "Authorization: Bearer <API_TOKEN>" \
--data-urlencode "url=https://www.instagram.com/p/ABC123/"A missing or invalid token returns 401. Most routes accept any valid token. A few engagement verification routes need one with admin rights and return 403 otherwise: creating and advancing an attempt, redelivering an attempt's webhooks, and registering or disconnecting a creator's handle.
The routes for issuing and revoking tokens are in the Tokens reference.
Responses
The data lookup routes under /v1 return the result object itself. Every other route wraps it in data, and list routes add pagination:
{
"data": [ ... ],
"pagination": { "page": 1, "limit": 20, "total": 150 }
}Errors return an error code and a human-readable message on every route. Branch on error; message may be reworded.
{ "error": "POST_NOT_FOUND", "message": "Post not found" }Routes that read a post or profile can also return the codes listed in Data lookup errors.
A few cases fall outside that envelope:
- A
/v1request with a missing or invalid parameter returns422 VALIDATION_ERRORbefore anything is read. On the engagement verification routes, a request body or query string that fails validation is rejected by the schema layer with400and the validator's own report, not anerrorcode. - In a batch, each failed result carries
erroras an object withcodeandmessage. POST /social-accounts/disconnectanswers404with a sentence inerrorand nomessage.
Pagination
Comments pages with a cursor: pass nextCursor back as cursor until hasMore is false.
The engagement verification list routes accept page (default 1) and limit (default 20), and cap limit at 100; a larger limit is rejected with 400 rather than clamped. GET /admin/brands and GET /admin/creators are not paginated: they take neither parameter and return every row.
Limits
| Limit | Value | When you exceed it |
|---|---|---|
GET /v1/stats, GET /v1/comments, GET /v1/profile | 60 per minute per client IP, for each route | 429 RATE_LIMITED |
POST /v1/stats/batch | 60 URLs per minute per client IP, counting every URL in the batch | 429 RATE_LIMITED |
| URLs in one batch | 1 to 25 | 422 VALIDATION_ERROR |
| Batch duration | 100 seconds | Unfinished URLs return BATCH_TIMEOUT |
Engagement verification adds its own:
| Limit | Value | When you exceed it |
|---|---|---|
| Post metrics refresh, one challenge | Once every 5 minutes | 429 RATE_LIMITED |
| Post metrics refresh, any challenge | 200 per minute per client IP | 429 RATE_LIMITED |
Post check (/admin/posts/thumbnail) | 10 per post per 5 minutes, and 100 per minute per token | 429 RATE_LIMITED |
| Likers refresh | 10 per minute per client IP, across every challenge | 429 RATE_LIMITED |
Likers refresh maxCount | 1 to 5000, default 1000 | — |
limit on a paginated list route | 100 | 400 |
| Webhook response time | Any 2xx within 10 seconds | The delivery is retried; see Webhooks |
| Comment history stored per challenge | 6,000 comments | The walk back through older history stops; newer comments keep being stored. See historyComplete on Comments and metrics on a challenge |
Limits that count per client IP are keyed on the address the request arrives from, not on your token, so every caller behind a shared egress address — an office network, a NAT gateway — counts as one. They are a guardrail against runaway callers rather than a budget to spend down.
Every 429 carries a Retry-After header. Wait for it instead of polling. 429 SCRAPING_RATE_LIMITED is different: reads are being throttled upstream, not by your own usage; see Data lookup errors.
Usage
GET /auth/usage reports what your tokens have done over a window, 30 days by default: requests, billable units and errors, in total and broken down by token, by route and by UTC day. A successful request counts one unit, a batch counts one per distinct post that succeeded, and a failed request counts none.
curl "{API_BASE_URL}/auth/usage?from=2026-09-01&to=2026-10-01" \
-H "Authorization: Bearer <API_TOKEN>"{
"data": {
"from": "2026-09-01T00:00:00.000Z",
"to": "2026-10-01T00:00:00.000Z",
"totals": { "requests": 1240, "billableUnits": 1180, "errors": 60 },
"byToken": [{ "tokenId": 1, "name": "Production Token", "requests": 1240, "billableUnits": 1180, "errors": 60 }],
"byRoute": [{ "method": "GET", "route": "/v1/stats", "requests": 900, "billableUnits": 880, "errors": 20 }],
"byDay": [{ "day": "2026-09-16", "requests": 41, "billableUnits": 40, "errors": 1 }]
}
}from is inclusive, to exclusive, and the window may not exceed 400 days. Add tokenId to report on one token. A token revoked after use keeps its rows with a null tokenId.
Parameter tables and schemas for every route are in the API reference.
Last updated on