Errors and limits

Every response the Anysite API can return, what each status means, what is charged, timeouts, paging and rate limits.

Goal: handle every response the API can give and know which calls cost credits.

A successful response

The body of a successful data call is always a JSON array, even on an endpoint that returns a single entity — linkedin/user returns a list with one item. A search that matched nothing is a normal 200 with [].

The x-result-count header counts the rows in the body you received, so it never exceeds the array. To learn how much more exists beyond what you asked for, read X-Total-Available-Results on the endpoints whose source reports a usable total.

How a call is processed

Checks run in this order; the first one that fails returns its error and nothing is charged:

  1. Auth header present, exactly one → else 422.
  2. Key valid, plan not ended, key allowed on the REST API → else 401 / 403.
  3. Endpoint available for your plan and parameters within your plan's maximum → else 404 / 529 / 403 / 400.
  4. Enough credits on the balance → else 401.
  5. Rate limits and usage windows → else 429.
  6. The request runs on the endpoint; its response is returned to you, and is charged by the rules in What is charged.

Statuses returned before the call runs

These come from Anysite's billing layer, before the endpoint is reached. None of them is charged, and their body is {"detail": ...}:

{"detail": "Token expired"}

422 returns a list of field errors instead, and 429 returns an object plus an X-Retry-After header with the same number of seconds:

{"detail": {"message": "Rate limit exceeded: ...", "retry_after": 12}}
Status detail What to do
422 a required header is missing Send the access-token header.
422 Body should be a valid dict object Send a JSON object as the body, not an array or a scalar.
401 Invalid token Copy the key again from the Billing page. See Authentication.
401 Token does not exist The key was deleted; use another key.
401 Token expired The plan has ended; renew it on the Billing page.
401 Points limit exhausted, required at least N points Add credits or upgrade the plan. See Plans and credits.
403 This token is restricted to MCP usage only and cannot be used for direct API access Use the MCP server, or a plan that includes the REST API.
403 This endpoint is disabled for your plan Use a plan that includes this endpoint.
400 Parameter 'count' exceeds the maximum allowed for your plan: N Lower count to N or less, or page through results.
404 Endpoint was removed The endpoint no longer exists; find its replacement in the API reference.
529 This endpoint is temporarily unavailable while we work on a fix. ... We switched this endpoint off. Retrying does not help; open a ticket from the Support page if you depend on it.
429 object, Rate limit exceeded: scope=..., limit=N requests <window>. ... Wait retry_after seconds. See Rate limits.
429 object, You've reached your <window> usage limit. ... Wait for the window to free up or upgrade. See Usage windows.

A 429 always comes from Anysite's rate limiter — the sources behind an endpoint never produce one.

Statuses from the endpoint

Once the checks pass, the endpoint's own status and body are returned to you unchanged. An endpoint error usually answers with an empty JSON array [], but a call that had already collected rows returns them alongside the error status; the reason is in the x-error header, which is set only when the status is 400 or higher:

HTTP/1.1 412
x-error: Failed to fetch URL. Website is not accessible
x-result-count: 0

[]

The exception is validation: a malformed body is rejected with 422 and a detail object naming the field.

Status Meaning
200 Success. The body is an array, possibly empty.
209 Looked and found nothing — a free miss. Only on the endpoints listed under What is charged.
400 Your client disconnected before the answer was ready.
408 The call ran out of time. See Timeouts. The body may still carry the rows collected before the deadline.
412 The API's "not found": the entity does not exist, the profile is private or gated, or (on webparser/*) the target host is unreachable.
415 webparser/* was pointed at a PDF, Office document, image, archive or other non-page file.
422 Schema validation failed (detail names the field), a LinkedIn URN was malformed (detail has "type": "linkedin_wrong_urn"), or the response was too large to return.
500 The source is out of reach, or retries against it were exhausted.
529 All scraping capacity for that source is busy right now.

Each endpoint in the API reference publishes only its non-obvious statuses — for example that linkedin/user answers 412 where you might expect 404. A status missing from that list is not impossible; the meanings above always apply.

A gated LinkedIn profile answers 412 for as long as it stays gated — retrying the same alias will not change the answer.

What is charged

In words:

Endpoint response Charged
Any status below 400 except 209 Yes
209 No
408, 412 Yes
Any other 4xx / 5xx Only if the response reports at least one result
Any error from the checks above, or 500 "Internal server error" when the endpoint was unreachable No

The price of a call depends on the endpoint and your plan, and on many endpoints it grows with the number of results: the base price is charged for every started block of results, so an endpoint priced per 10 results charges twice for 11 rows and three times for 21. Where they are published, both numbers are in the API reference as x-price (the base price) and x-increase-every (the block size; absent means one flat price per call) — some endpoints publish neither, and their price lives only in our billing records. Ask for the count you actually need: a larger count can cost more. Asking for less of a profile can cost less too — on linkedin/user, every with_* section you turn off lowers the price of the call, and fast_mode raises it.

Whatever the reference says, the amount actually taken for a call is the x-credits-charged header — 0 means the call was free — and it is in the request logs on the Billing page.

Credits are taken from the plan's credits first, then from purchased credits. A call is allowed when the balance covers its base price; if the final price is higher (for example because more results came back), the balance can go below zero, and the negative amount is subtracted from credits you add later.

Headers worth reading

Header What it tells you
x-credits-charged Credits this call cost. 0 means it was free.
x-token-points Credits left on the balance.
x-result-count Rows in this response — the length of the array you received.
x-error Why the call failed. Present only on 400 and above.
x-warning Something was off with the request although it succeeded — see Ignored parameters.
x-execution-time How long the endpoint worked, in seconds.
x-request-id The id of this call. Quote it in a support ticket. You may send it yourself, but it must be a valid UUID or the request is rejected with 422.
X-Total-Available-Results How many results are reachable in total, on endpoints whose source reports a usable total.

Timeouts

The timeout field in the body defaults to 300 seconds and accepts 20-1500.

It is a stall budget, not a total duration. A call that has not produced its first result is cut with 408 once timeout elapses. After results start arriving, each new one pushes the deadline out to about a minute after it — less, if your timeout is shorter than that — up to a hard ceiling of 1500 seconds. So a call that keeps producing rows may legitimately run far longer than its timeout, while a call that stops producing them is cut shortly after it stalls.

Because of that ceiling, set your HTTP client's own timeout to about 1600 seconds on endpoints that can run long. A client that gives up at 30 or 60 seconds abandons calls that were still working.

curl --max-time 1600 -X POST "https://api.anysite.io/api/linkedin/search/users" \
  -H "access-token: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"keywords": "cto", "count": 100, "timeout": 600}'

ACTION FOR THE HUMAN: copy your API key at https://app.anysite.io/billing — an agent cannot obtain it.

Ignored parameters

Unknown keys in the body are ignored, not rejected. A misspelled filter therefore behaves exactly like no filter: you get 200 with unfiltered results, and you pay for them. Every ignored key is listed in the x-warning header (and in warnings in an MCP result), so check that header whenever a filter appears to do nothing.

count is required on every endpoint that can return more than one result, and it is a maximum, not a promise: asking for more than exists returns 200 with fewer rows.

Paging

Most endpoints have no paging parameter at all: they take only count and page through the source for you, so ask for the number of results you need in one call. A minority do take offset or page — the API reference shows which — and there you advance offset by count, or increment page, on each call. Repeating such a call without advancing returns the same rows, which is the usual cause of "the API keeps giving me duplicates".

Retrying

Transport failures between Anysite and the source are already retried for you, with backoff, before you ever see an error. There is no idempotency key: a call you retry yourself is charged again if it is a charged status.

An endpoint can be switched off

An endpoint may appear in the API reference while it is switched off. You recognise it by the answer arriving before the endpoint runs: a 404 Endpoint was removed, or a 529 whose detail says the endpoint is temporarily unavailable while we work on a fix. Retrying does not help; open a ticket from the Support page if you depend on it.

A 529 that carries no such detail is a different thing — the endpoint ran and the scraping capacity for that source is busy. Retry it later.

Rate limits

Plans, and some endpoints, limit the number of requests over rolling windows (10 seconds, minute, hour, day or 30 days). Every request that passes the checks before it counts toward these limits, whether or not it ends up charged — a free 209 included. When a limit is hit, the API returns 429 with retry_after equal to the seconds until the oldest request in the window expires.

Usage windows

Some plans, including MCP plans, also cap the credits spent over two rolling windows: 5 hours and weekly. Some plans add separate LinkedIn 5-hour and weekly windows, which count only linkedin/* endpoints and skip the database ones whose path contains /sql/. Usage is the sum of credits charged within the window, so it frees up gradually as older calls leave the window.

When a window is full, the API returns 429 with retry_after equal to the full window length — the longest possible wait. Usage may free up sooner.

For an MCP plan, the current usage of each window is shown as a percentage on the MCP page.

ACTION FOR THE HUMAN: open https://app.anysite.io/mcp (Open MCP usage).