Errors
Every InsightSocial API error type with its status, what to do about it, and copy-paste retry loops.
Every failure returns the same envelope: success: false, an error object with a type to branch on and a readable message, and the usual request_id and credit fields. A failed call is never charged.
{
"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
}error.typeis what your code should branch on.error.messageexplains the failure in a sentence and often names what to change. Show it or log it, but do not parse it.credits_usedis0on every error.credits_remainingis your balance when we know it, andnullwhen we do not (authentication failures, for example).request_idmatches theX-Request-Idheader. Include it when you contact support.
Error types
error.type | Status | Retry? | What it means |
|---|---|---|---|
MISSING_API_KEY | 401 | No | No x-api-key header on the request |
INVALID_API_KEY | 401 | No | The value is not an InsightSocial key, or no key matches it |
API_KEY_REVOKED | 401 | No | The key has been revoked |
INSUFFICIENT_CREDITS | 402 | No | Your balance is below what this call needs to hold |
UNKNOWN_PLATFORM | 404 | No | The first path segment is not one of the nine platforms |
UNKNOWN_ENDPOINT | 404 | No | The platform exists but that path does not |
RESOURCE_NOT_FOUND | 404 | No | Nothing exists at the identifier you sent |
METHOD_NOT_SUPPORTED | 405 | No | This endpoint is not available through the API |
IDEMPOTENCY_IN_PROGRESS | 409 | Yes, after Retry-After | A call with the same Idempotency-Key is still running |
RATE_LIMITED | 429 | Yes, after Retry-After | More than 60 requests in 60 seconds on this key |
CONCURRENCY_LIMIT | 429 | Yes, after Retry-After | More than 10 requests in flight on this key |
CLIENT_CLOSED_REQUEST | 499 | Your call | Your client disconnected before the response |
INTERNAL_ERROR | 500 | Yes, with backoff | Something went wrong on our side |
SERVICE_UNAVAILABLE | 503 | Yes, after Retry-After or backoff | We could not complete the call right now |
UPSTREAM_ERROR | 503 | Yes, after Retry-After | The platform did not answer in time |
Parameter errors, such as INVALID_REQUEST or BAD_REQUEST | 400 (or another 4xx) | No | A parameter is missing, invalid, or not accepted by this endpoint |
Parameter errors can carry different types
When a request is rejected because of its parameters, the error.type is not drawn from a fixed list: you will usually see INVALID_REQUEST or BAD_REQUEST, but other values occur. Treat any 4xx you do not recognise as "fix the request", and read error.message, which says what was wrong.
Which errors to retry
Retry only RATE_LIMITED, CONCURRENCY_LIMIT, IDEMPOTENCY_IN_PROGRESS, SERVICE_UNAVAILABLE, UPSTREAM_ERROR and INTERNAL_ERROR. Everything else is deterministic: the same request fails the same way until you change the request, the key or your balance.
When a response carries Retry-After, wait at least that many seconds. Otherwise back off exponentially with jitter, and give up after a few attempts.
Error reference
MISSING_API_KEY
401. No x-api-key header reached the API. Send the header, and if you already do, make sure nothing between you and the API, such as a proxy or gateway, removes it. A key sent in Authorization is not read and also produces this error. See Authentication.
INVALID_API_KEY
401. Either the value does not look like an InsightSocial key (keys start isk_live_ or isk_test_), or it looks right but matches no key. Copy it again from API keys.
API_KEY_REVOKED
401. The key was revoked in the dashboard. Create a new one in the dashboard.
INSUFFICIENT_CREDITS
402. Before a call runs, we hold the most it can cost. If your balance is below that amount, the call is refused and nothing is charged. credits_remaining shows your balance, and the message states both numbers.
For a metered endpoint, the amount held is the top of its price range, and on endpoints that accept max_pages it is multiplied by the number of pages. You can therefore get a 402 on a call that would have cost less in the end. Fewer pages, or a fixed-price endpoint, holds less. Top up on the pricing page; retrying without a top-up fails the same way.
UNKNOWN_PLATFORM
404. The platform segment of the path is not one we serve. The nine platforms are instagram, tiktok, facebook, linkedin, twitter, threads, youtube, reddit and pinterest.
UNKNOWN_ENDPOINT
404. The path is not in the catalogue. Check it against GET /v1/endpoints or the API reference.
RESOURCE_NOT_FOUND
404. The endpoint exists, but nothing is there for the identifier you sent: a handle that does not exist, a deleted post, and so on. You are not charged. Retrying the same identifier returns the same answer, so record it and move on.
METHOD_NOT_SUPPORTED
405. This path is in the catalogue but cannot be called through the API. Pick another endpoint.
IDEMPOTENCY_IN_PROGRESS
409. An earlier call with the same Idempotency-Key has not finished. Wait for Retry-After, then send the same request with the same key. Once the original has finished, you get its result as a free replay.
RATE_LIMITED
429. This key sent more than 60 requests in a sliding 60-second window. Retry-After is the number of seconds until the oldest request leaves the window. Nothing is charged. See Rate limits.
CONCURRENCY_LIMIT
429. This key already had 10 requests in flight. Retry-After is 1, since a slot frees as soon as any open request returns. Shrink your worker pool.
CLIENT_CLOSED_REQUEST
499. Your client closed the connection before we answered. You only see this in logs, since nobody was listening for the response. Give slow endpoints a generous client timeout.
INTERNAL_ERROR
500. An unexpected error on our side. Nothing was charged. Retry with backoff, and if it keeps happening, contact support with the request_id.
SERVICE_UNAVAILABLE
503. We could not complete the call right now. Causes include being unable to verify your key or read your balance for a moment, or temporarily running out of capacity. Nothing was charged. When Retry-After is present (often 30), wait that long; otherwise retry with backoff.
UPSTREAM_ERROR
503. The platform did not answer, even after our own retries. Nothing was charged. Retry-After is 5.
Parameter errors
400, or another 4xx. A required parameter is missing, a value is in the wrong format, or the endpoint does not accept a parameter you sent. The message says what was rejected and usually names the parameter to fix. Check the endpoint's parameters on its API reference page or in GET /v1/endpoints. Nothing is charged.
Idempotency
Send an Idempotency-Key header, a fresh UUID per logical operation, to make any call safe to retry after a timeout or a dropped connection.
- A retry with the same key returns the original result with
idempotent_replay: true,charge_reason: "replay"andcredits_used: 0. - A retry that arrives while the original is still running gets
409 IDEMPOTENCY_IN_PROGRESS. Wait forRetry-Afterand try again with the same key. - Keys are scoped to your account.
- A key longer than 255 characters, or with characters other than letters, digits,
.,_,:and-, is ignored. The call then runs normally, with no replay protection. - If we never answered the original successfully (for example your client disconnected before it finished), the retry that delivers the data is charged as a normal call (
charge_reason: "miss") at exactly the ceiling the call reserved: the listed price, or the top of the range for a metered endpoint, multiplied bymax_pagesif you sent it. Like any charged call, it can be covered by one of your free calls. It costs 0 if you already own that exact call or if the replay returns nothing.
What is never charged
Every error on this page costs 0 credits. So do empty results, dry_run=1 calls and replays of a call we already answered. API credits are non-refundable, and a call that fails is simply never charged. See Credits.
Retry loops
Each loop retries only the transient statuses (409, 429, 500, 503), honors Retry-After when it is sent, otherwise backs off exponentially with jitter, and stops after five retries.
#!/usr/bin/env bash
url="https://api.insightsocial.app/v1/tiktok/profile?handle=khaby.lame"
max_retries=5
attempt=0
while :; do
body=$(mktemp); headers=$(mktemp)
status=$(curl -s -o "$body" -D "$headers" -w '%{http_code}' \
-H "x-api-key: $INSIGHTSOCIAL_API_KEY" "$url")
if [ "$status" -lt 400 ]; then
cat "$body"; rm -f "$body" "$headers"; break
fi
case "$status" in
409|429|500|503) ;;
*) echo "Not retryable: $status"; cat "$body"; rm -f "$body" "$headers"; exit 1 ;;
esac
attempt=$((attempt + 1))
if [ "$attempt" -gt "$max_retries" ]; then
echo "Giving up after $max_retries retries (last status $status)"
rm -f "$body" "$headers"; exit 1
fi
wait_s=$(grep -i '^retry-after:' "$headers" | tr -d '\r' | awk '{print $2}')
if [ -z "$wait_s" ]; then
wait_s=$(awk "BEGIN{srand(); print (2 ^ $attempt) * (0.5 + rand() / 2)}")
fi
rm -f "$body" "$headers"
sleep "$wait_s"
doneDebugging tips
- Log
request_id(also sent asX-Request-Id) with every failure, so support can trace the exact call. - A
503on an input that worked before is usually temporary. Retry afterRetry-After. - Some calls take a while to answer. Set a client timeout of a minute or more on heavy endpoints rather than aborting early.