Skip to content

Concepts

Errors & billing

Authentication, authorization and billing are three separate outcomes here, and nothing that fails to return usable data costs anything. Both of those are specified behaviour with tests behind them, not a courtesy.

The order things happen in

Every request — synchronous, batch item, async job, or subscription poll — runs through the same eight stages in the same order. The order is what makes the guarantees hold: charging sits after the cache and before the run, and settlement sits after it.

  1. 01
    validatefree

    Parameters are checked against the endpoint schema. A failure lists every bad path and never reaches a scraper.

  2. 02
    preflightfree

    Missing credentials or proxies fail here, before the cache, so a misconfigured deployment fails identically whether or not something happens to be cached.

  3. 03
    cachefree

    A hit inside your cache_max_age returns immediately with creditsCharged 0. A cache read failure degrades to a live fetch, never to an error.

  4. 04
    chargemay charge

    Taken only after a miss, only when the endpoint costs more than zero, and only if the balance covers it. A balance can never go negative.

  5. 05
    runfree

    The scraper executes. Async jobs run here too, with no request timeout above them.

  6. 06
    settlefree

    Anything that threw is refunded in full. Anything empty is refunded in full. An endpoint may charge less than its listed price, never more.

  7. 07
    cache writefree

    The result is stored for the next caller, unless your team has cache writes or retention turned off.

  8. 08
    logfree

    Exactly one request log row per request, success or failure. A failed log write never fails the request.

Every error code

The charged column reads no on every row. That is the point of the table. The origin column is the one to act on: a you error needs a change on your side, a platform error usually needs a retry, and a us error needs nothing from you at all.

CodeHTTPOriginRetryChargedMeaning
missing_api_key401younonoNo x-api-key header was sent.
invalid_api_key401younonoThe key is not recognised. This is a typo, not a billing problem.
revoked_api_key401younonoThe key existed and was revoked. Issue a new one.
account_suspended403younonoThe account has been suspended. Contact support to restore access.
insufficient_credits402younonoThe key is valid and the balance is not. The only condition that returns 402.
daily_cap_exceeded429younonoYour configured daily cap would be exceeded. Checked before any charge.
invalid_request400younonoParameters failed validation. Every failing path is listed, not just the first.
not_found404younonoThe route or resource does not exist on this API. Check the path.
upstream_not_found404younonoThe profile, video, or post does not exist or is not public.
empty_result200platformnonoThe target exists and has nothing to return. A success, and free.
upstream_blocked502platformyesnoThe platform refused the request. Ours to fix, not yours.
upstream_rate_limited429platformyesnoThe platform throttled us. Back off and retry.
upstream_unavailable503platformyesnoThe platform is unreachable.
upstream_timeout504platformyesnoThe upstream request ran out of time. Use a job for work this long.
upstream_schema_drift502platformnonoThe platform changed its response shape. We are alerted automatically.
not_configured501usnonoThis deployment is missing credentials or proxies for that endpoint. The response names them.
too_many_targets400younonoA batch exceeded the maximum target count.
job_not_found404younonoNo job with that id belongs to your team.
internal_error500usnonoOur fault. Refunded, logged, and alerted on.

401 is not 402

A missing, unrecognised, or revoked key always returns 401. A 402 means the key is valid and the balance is not. Nothing else returns 402, so a 402 in your logs is never something you fix by checking for a typo.

This matters more than it sounds. A competitor returns 402 out of credits for an invalid key, which sends people to buy credits when what they actually have is a stray whitespace character in an environment variable.

What an error looks like

error response
{
  "success": false,
  "error": {
    "code": "upstream_blocked",
    "message": "The platform blocked this request. It was not charged.",
    "details": { }
  }
}

Empty is a success

A channel with no uploads, a video with no captions, a search with no hits — the target exists and the answer is nothing. You get a 200, an empty payload, and creditsCharged: 0. Treat empty as data, not as failure.

empty result
{
  "success": true,
  "data": { "items": [] },
  "meta": {
    "endpoint": "youtube.channel-videos",
    "creditsCharged": 0,
    "cached": false,
    "durationMs": 1104,
    "requestId": "req_01JB8Z..."
  }
}

The clauses this page implements

P1You are never charged for a failed request.SPEC §2.5
P2You are never charged for an empty result.SPEC §2.5
P3Cache hits cost 0 credits.SPEC §2.3
P4An invalid API key is an auth error, not a billing error.SPEC §3
P5Every endpoint's price is machine-readable.SPEC §2.6
P6A balance can never go negative.SPEC §1.1
P7Per-tenant cache isolation is standard.SPEC §2.3
P8Hard daily spend caps.SPEC §1.3