Response schema
The InsightSocial API envelope, pagination, response headers, idempotent replays and fresh fetches.
Every data endpoint answers in one envelope, success or error, so a single parser handles all nine platforms. The two account endpoints are the exception: GET /v1/credits returns a balance body of its own (it still carries success, credits_used and credits_remaining), and GET /v1/endpoints returns the catalogue in its own shape.
Successful response
{
"success": true,
"platform": "instagram",
"endpoint": "/v1/instagram/profile",
"data": {
"author": { "username": "natgeo", "followers": 276000000 }
},
"credits_used": 20,
"credits_remaining": 9980,
"request_id": "req_1a2b3c4d5e6f",
"cached": false,
"idempotent_replay": false,
"charge_reason": "miss",
"free_call": false
}Envelope fields
| Field | Type | Always present | Description |
|---|---|---|---|
success | boolean | yes | true on success, false on error. |
platform | string | yes | The platform you called, such as instagram. |
endpoint | string | yes | The path you called, such as /v1/instagram/profile. |
data | object | yes | The platform payload. Its shape depends on the endpoint; see its API reference page. |
pagination | object | no | List endpoints only. See List endpoints. |
credits_used | integer | yes | Credits charged for this call. 0 for replays, owned re-reads, free calls, empty results and failures. |
credits_remaining | integer | yes | Your balance after this call. |
request_id | string | yes | Our identifier for this call, in the form req_ plus 12 hex characters. |
cached | boolean | yes | true when the result came from the shared cache rather than a live fetch. |
idempotent_replay | boolean | yes | true when this is a replay of an earlier call with the same Idempotency-Key. |
charge_reason | string | yes | Why credits_used has the value it has. See below. |
free_call | boolean | yes | true when the call used one of your free calls, so credits_used is 0. |
charge_reason
| Value | Meaning | Credits |
|---|---|---|
miss | A live fetch | The endpoint's price, or for a metered endpoint what the call used |
shared_cache | Served from the shared cache | 5 |
owned | You already paid for this exact call inside its ownership window | 0 |
replay | An idempotent replay of a call you already made | 0 |
no_result | Nothing to charge for, such as an empty result or a dry_run=1 call | 0 |
Ownership windows and the other pricing rules are on Credits.
Fields inside data
Two fields live inside data rather than at the root of the envelope.
data.dropped. On list endpoints, counts items left out of the page because they could not be mapped to the endpoint's schema. A healthy page carries "dropped": 0. It is the only sign that a page came back short, so check it on every page instead of judging completeness by the length of items.
dropped is inside data
dropped sits next to items under data, while pagination sits at the root. Reading response.dropped returns undefined, which is easy to mistake for zero.
data._warnings. An array of human-readable notes, present only when something about the data was ambiguous or partial:
{
"data": {
"author": { "username": "natgeo" },
"_warnings": [
"posts: one call reads one page of 12 posts; pass posts_cursor back as cursor for the next page"
]
}
}Treat warnings as advisory. The response is still valid. When there is nothing to report, the key is absent.
Endpoints that attach computed fields or labels return them inside data as well.
Error response
{
"success": false,
"error": {
"type": "INSUFFICIENT_CREDITS",
"message": "This call needs up to 340 credits and 120 remain. Top up at https://www.insightsocial.app/pricing"
},
"request_id": "req_1a2b3c4d5e6f",
"credits_used": 0,
"credits_remaining": 120
}| Field | Description |
|---|---|
error.type | A stable string to branch on. |
error.message | A readable explanation, often naming what to fix. Do not parse it. |
request_id | Quote it to support. |
credits_used | Always 0: failed calls are never charged. |
credits_remaining | Your balance when we know it, otherwise null (for example on authentication failures). |
The full list of types is on Errors.
Response headers
| Header | Value |
|---|---|
X-Request-Id | Same as request_id in the body. |
X-Credits-Used | Credits charged for this call. |
X-Credits-Remaining | Your balance after the call. Omitted when it is unknown, never sent as a placeholder 0. |
Retry-After | Seconds to wait. Sent on 429, on 409 IDEMPOTENCY_IN_PROGRESS and on some 503 responses. |
Cache-Control | no-store. Do not cache API responses in a shared proxy. |
CORS headers are also set, and X-Request-Id, X-Credits-Used, X-Credits-Remaining and Retry-After are exposed to browser code. Keys still belong on your server; see Authentication.
List endpoints
List responses put their rows in data.items and carry a pagination object at the root of the envelope:
{
"success": true,
"platform": "tiktok",
"endpoint": "/v1/tiktok/search",
"data": {
"items": [
/* ... */
],
"dropped": 0
},
"pagination": {
"next_cursor": "is2.eyJ2IjoyLCJwIjoiNDgyMTk5NjAzNzEifQ",
"has_more": true,
"page_size": 30
},
"credits_used": 20,
"credits_remaining": 9960,
"request_id": "req_1a2b3c4d5e6f",
"cached": false,
"idempotent_replay": false,
"charge_reason": "miss",
"free_call": false
}| Field | Description |
|---|---|
next_cursor | Send it back as the cursor query parameter to get the next page. Starts with is2.; pass it unchanged. |
has_more | false on the last page. Stop there. |
page_size | Rows on this page. |
stopped_at | Only on creator post lists called with since or stop_at_id. Says which boundary ended the walk, such as since. |
Some endpoints page with their own parameter, such as page or continuationToken, instead of cursor. Their reference pages name it. The full loop is on Pagination.
Idempotent requests
Send an Idempotency-Key header to make a call safe to retry. Use a fresh UUID for each logical operation.
curl "https://api.insightsocial.app/v1/tiktok/profile?handle=khaby.lame" \
-H "x-api-key: $INSIGHTSOCIAL_API_KEY" \
-H "Idempotency-Key: c3f9d27e-81b4-4e06-a5d2-94be0f6c1a78"- A replay returns
idempotent_replay: true,charge_reason: "replay"andcredits_used: 0. - If the original call with the same key is still running, you get
409 IDEMPOTENCY_IN_PROGRESSwithRetry-After. Wait, then send the same key again. - Keys are scoped to your account.
- A key must be at most 255 characters of letters, digits,
.,_,:or-. A key that does not fit is ignored, and the call runs as an ordinary request.
Force a fresh fetch
Repeat calls can be served from the shared cache (cached: true) or free as an owned re-read. To skip both and fetch live, send Cache-Control: no-cache, or add fresh=1 to the query:
curl "https://api.insightsocial.app/v1/tiktok/profile?handle=khaby.lame" \
-H "x-api-key: $INSIGHTSOCIAL_API_KEY" \
-H "Cache-Control: no-cache"A fresh fetch is always charged at the normal price. See Credits for ownership windows.
Next steps
Using an AI agent
Point Claude, ChatGPT, Cursor or any coding agent at the InsightSocial API with one paste-in prompt and the free endpoint catalogue, so it reads the real paths, parameters and prices instead of guessing.
Data availability
How to read values, nulls, missing fields, dropped rows, warnings and cache state in a response.