InsightSocial API

Rate limits

60 requests per minute and 10 concurrent requests per API key, what a 429 looks like, and how to size a job.

Each API key may send 60 requests per minute and have 10 requests in flight at once. Going over either limit returns a 429, and a rejected request costs nothing. Beyond those two ceilings, what bounds your volume is your credit balance.

The limits at a glance

LimitApplies toValueWhen exceeded
Request ratePer API key60 requests / sliding 60 seconds429 RATE_LIMITED with Retry-After
ConcurrencyPer API key10 requests in flight429 CONCURRENCY_LIMIT with Retry-After: 1
CreditsPer accountYour balance402 INSUFFICIENT_CREDITS
API keysPer account25 keysKey creation is refused. See Authentication

The dashboard Explorer has its own allowance with the same numbers, so trying endpoints there does not eat into your keys' limits.

Request rate: 60 per minute per key

Every data request on a key counts toward a sliding 60-second window. That includes requests that end in a 402, 404 or 405, and owned re-reads that cost nothing. A max_pages walk is one request and takes one slot. None of these count: GET /v1/credits, GET /v1/endpoints, the bare GET /v1, and any request rejected for a missing or bad key, since authentication runs first.

Response
{
  "success": false,
  "error": {
    "type": "RATE_LIMITED",
    "message": "Too many requests on this key. Honour Retry-After, then back off with jitter."
  },
  "request_id": "req_1a2b3c4d5e6f",
  "credits_used": 0,
  "credits_remaining": null
}

Retry-After is the number of seconds until the oldest request in the window drops out, at least 1.

Concurrency: 10 in flight per key

Separately, a key may have at most 10 open requests. This is not a time window: a slot frees the moment one of your requests returns, so an 11th request sent while 10 are open is rejected.

Response
{
  "success": false,
  "error": {
    "type": "CONCURRENCY_LIMIT",
    "message": "Too many calls in flight on this key. Retry shortly."
  },
  "request_id": "req_1a2b3c4d5e6f",
  "credits_used": 0,
  "credits_remaining": null
}

Retry-After is 1 on this one.

Only Retry-After

The API sends no headers describing your remaining headroom. The only timing header is Retry-After. It comes with every 429, and also with 409 IDEMPOTENCY_IN_PROGRESS and some 503 responses. Pace yourself from your own counts, as described below.

Credits are the volume limit

There is no daily or monthly request quota. What limits sustained work is your balance: the free plan includes 500 credits a month, Pro 10,000, and packs add more. Prices differ per endpoint and some are metered, so price every endpoint your job uses on Endpoint pricing before you size it. See Credits for how charging works.

Handling a 429

Read error.type

RATE_LIMITED means you are sending too fast: slow the request rate. CONCURRENCY_LIMIT means too many requests are open at once: shrink the worker pool. They need different fixes.

Wait for Retry-After

Wait at least that many seconds before retrying.

Back off with jitter

If the retry also gets a 429, double the wait and add random jitter so your workers do not all retry in the same instant.

Cap the attempts

After a handful of attempts, give up and surface the error.

Node.js
async function callWithBackoff(url: string, init: RequestInit, maxRetries = 5): Promise<Response> {
  for (let attempt = 0; ; attempt++) {
    const res = await fetch(url, init);

    // Only 429s are handled here. A 402 or another 4xx will not
    // change on retry, so return it straight away.
    if (res.status !== 429 || attempt >= maxRetries) return res;

    const retryAfter = Number(res.headers.get("Retry-After")) || 1;
    const backoff = retryAfter * 2 ** attempt;
    const jittered = backoff * (0.5 + Math.random() * 0.5);
    await new Promise((r) => setTimeout(r, jittered * 1000));
  }
}

The Errors page has complete retry loops in cURL, Python and Node.js that also cover 503 and 500.

Sizing a job

  • Run at most 10 workers per key.
  • Keep the total under 60 requests a minute, which is one request a second on average.
  • Budget credits per page, not per job, and remember that metered calls hold the top of their price range while they run.
  • Walk paginated endpoints until pagination.has_more is false. See Pagination.
  • Send an Idempotency-Key on each call so retries never pay twice.

Next steps

On this page