Authentication and credits
API Keys, the two permissions, the shared daily budget, and safe retries for paid queries.
Authenticate requests
Send your Key as a Bearer token with every request.
Authorization: Bearer YOUR_API_KEYCreate, expire and revoke Keys in Developer settings. A revoked or expired Key can no longer read data, including cached pages and unfinished pagination. Keep Keys out of URLs, source control and browser code.
Permissions
| Permission | Default | What it allows |
|---|---|---|
data:read | On | Read your accessible tracking accounts, followers, following and detected changes, plus reusable public data. |
data:fetch | Off | Run online queries with an explicit budget, in addition to everything in data:read. |
A personal Key follows your current and future readable tracking range, and it never grants more access than your account has. Connection permissions and list rights are checked on every request.
Plugin connections use the same permissions through OAuth on the MCP resource. An MCP access token cannot be used as a REST API Key.
Credits and the daily budget
The five GET endpoints spend no new collection credits. POST /queries spends from your existing Instoryview wallet, and each query must fit three limits:
- The query's own
maxCredits. - Your daily API budget.
- Your available wallet balance.
All your Keys and connections share one daily budget. It starts at 0, so set it before your first online query; creating or rotating a Key does not reset it. Budget days use UTC. Credits reserved for an unfinished request stay reserved until its outcome is settled.
The budget covers the whole logical query, including any profile lookup and billable source calls it needs. Each source call costs 1 credit: a profile query 1, a first list page 2 (profile, then page), each next page 1. A first list page with maxCredits below 2 is refused before any call, so nothing is charged. A failed or missing-account lookup can still have a source cost, so check meta.creditsUsed on errors as well as successes. null means the final cost is not confirmed yet.
Retries and idempotency
Every POST needs an Idempotency-Key. Keep the key and the exact request body until the result is confirmed. Replaying a completed query returns its original data and original total creditsUsed without charging again.
| Code | What to do |
|---|---|
request_in_progress | Wait for Retry-After, then resend the same POST with the same key. Limit automatic recovery to 60 seconds. |
query_outcome_unknown | Stop automatic retries and keep the key. Within about 15 minutes the query is settled: confirmed source calls are charged, calls that got no answer are not, and the same key then returns query_interrupted with the final cost. |
idempotency_conflict | The key was already used with a different body. Fix the recovery request; never silently start a new paid query. |
result_expired | The stored result can no longer be returned. The old key will not start another collection. |
To get the next page of an online query (1 credit), send the returned online cursor with a new key and a new maxCredits. Cursors from existing-data reads and from online queries cannot be mixed.
Errors
Every error has the same shape. Keep requestId when you contact support.
{
"error": {
"code": "snapshot_unavailable",
"message": "No retained readable follower snapshot is available."
},
"meta": { "requestId": "req_error_example", "creditsUsed": 0 }
}| Status | Code | What to do |
|---|---|---|
| 400 | validation_failed | Check the username, filters or cursor. from and to must be sent together. |
| 401 | unauthorized | Update your Key or reconnect. |
| 402 | budget_exceeded, insufficient_credits | Change the budget yourself before starting a new query. |
| 403 | insufficient_scope, list_not_authorized | Check the online-query permission and your rights to that list. |
| 404 | snapshot_unavailable | No readable retained tracking snapshot exists. This does not mean zero followers. |
| 404 | data_unavailable | No reusable public data exists. An online query is a separate choice. |
| 404 | not_found | The account does not exist, is private, or was removed from Instoryview. |
| 409 | data_changed, account_changed | Check the account, then restart the read. |
| 410 | cursor_expired | Restart the read. Never restart a paid collection automatically. |
| 429 | rate_limited | Each account can send 60 requests a minute and run two change reads at once. Wait for Retry-After before retrying. |
| 503 | upstream_unavailable | Keep the request ID. Recover paid queries with their original idempotency key. |
| 503 | query_interrupted | An online query stopped and was settled: only confirmed source calls were charged, and it never runs again. |
An error never authorizes a client to turn a read of existing data into an online query.
Questions about the API? Email support@instoryview.com