What is not billed: error codes and billing rules
A detailed breakdown of billing rules across HTTP status codes, JSON-RPC errors, and the Data API, with recommended actions for developers.
BlockVectra meters requests in Compute Units (CU). Calls are billed only after a response is obtained; units are not deducted when a request arrives. This guide summarizes the billing determination rules across HTTP status codes, JSON-RPC calls, and the Data API, along with recommended actions for developers.
HTTP Status Codes and Billing Rules
The billing determination and handling rules for HTTP-level responses are as follows:
| HTTP Status | Response Body | Scenario | Billed? | Recommended Action |
|---|---|---|---|---|
| 200 | JSON-RPC response (single or batch) | Normal response; all JSON-RPC layer errors (parse error, method rejection, guard, upstream failure, node error) are also 200 | Evaluated per call | Inspect result or error for each call; if an error is returned, see JSON-RPC error handling below |
| 204 | Empty | All calls in the request are notifications | Notifications are billed as normal | Notifications are accepted and processed in the background; no extra action required |
| 400 | Empty | Malformed HTTP message (cannot parse request line or headers, invalid chunked encoding), or more than 10 s between two reads of the request body | No | Check HTTP request syntax, headers, and transmission continuity |
| 402 | JSON, -32020 | Insufficient balance, allowance exhausted (newly created keys return 503 rather than 402 before billing data is synchronized) | No | Go to the Console billing page to check your balance and top up |
| 403 | Empty | Methods other than POST or OPTIONS on /v1/{chain} or /v1/{chain}/{api_key} (regardless of whether chain name is known) | No | Change the HTTP request method to POST (or cross-origin OPTIONS preflight) |
| 404 | JSON, -32600 (reason = unknown_chain) | POST to an unknown {chain} (request body not read, key not checked) | No | Check the chain name in the URL against Supported Chains (must be exact lowercase slug) |
| 404 | empty body | Missing key on known chain, key unknown or disabled; unmatched path (e.g. POST /v1, /v1/, POST /v1/{chain}/) | No | Include chain in URL (/v1/{chain}) or provide an active API key in x-api-key header (brand-new or rotated keys take a few seconds to take effect; wait a moment and retry) |
| 408 | Empty | Exceeded 35 s from reading request headers to returning response | Possible: calls already forwarded to the node are billed as normal once the node responds | Do not unconditionally retry state-changing calls (e.g. eth_sendRawTransaction); a client disconnect does not cancel calls already forwarded |
| 413 | Empty | Request body > 2 MiB (2,097,152 bytes), checked after auth and balance admission | No | Keep request body under 2 MiB; split batches into smaller requests |
| 414 / 431 | Empty | URI too long (414) or request headers too large (431) | No | Shorten request URI or trim HTTP request headers |
| 429 | JSON, -32005 or -32022; carries Retry-After when CU token bucket is depleted (-32005); account rate limit 429 does not carry it | Bucket balance depleted → -32005; single request CU exceeds burst capacity → -32022; account call rate limit depleted → -32005; calls in single request exceed limit → -32022 | No | For -32005 with Retry-After, wait the specified seconds before retrying; for -32022, split the request or reduce batch size (retrying as-is will never succeed) |
| 503 | JSON, -32021, with Retry-After | Billing data temporarily unavailable; server temporarily rejects request (not a balance issue, no need to top up); newly created keys return this until billing data syncs (usually a few seconds) | No | Not a balance issue, no need to top up; wait the seconds specified in Retry-After and retry |
Note: When accessed through Cloudflare, Cloudflare may return 52x or 1015 error pages; these are not generated by the service.
JSON-RPC Error Codes and Billing Rules
The same error code can originate from the platform or the node, and billing differs:
- Errors generated by the platform itself: never billed;
- Errors returned by the node: passed through as-is and billed at the method weight, with only the node error codes listed below as exceptions.
Rule Details
- Node errors not billed: The node's
-32002(batch timeout),-32003(batch response too large), and-32600(batch rejected as a whole) indicate that the node abandoned the call early and are not billed; notifications in the same batch are also not billed.4444indicates the requested block was pruned by the node (the node retains roughly 7 days of history), is not billed, and does not affect other calls in the batch.-32000(only forhistorical state ... is not available, and Erigon'sold data not available due to pruning...) indicates the request falls outside the node's state history window (roughly 128 blocks), is not billed, and does not affect other calls in the batch. Erigon has a window of about 36 days, is not billed, and does not affect other calls in the batch. - Node errors billed: Other errors returned by the node count as work done by the node and are billed at the method weight, such as
execution reverted(-32000or3withdata), the node's own-32602 invalid argument, or-32601returned for aneth_*method that passed platform admission but is not implemented by the node. - Balance admission and sync:
-32020indicates insufficient account balance and requires a top-up;-32021indicates billing data is temporarily unavailable and the request is temporarily rejected—this is not a balance issue, no need to top up, simply wait the seconds specified inRetry-Afterand retry. A newly created key returns-32021before the system reads billing data for its account (usually within a few seconds), not-32020; after reading, accounts with balance are accepted as normal, while accounts truly depleted or deleted receive-32020(402). - Upstream failures: A
-32603generated by the platform due to upstream communication failure or malformed response (upstream unavailable,no response from upstream,malformed upstream response) carriesdata.reason: upstream_unavailable;internal gateway erroris generated only in extremely rare cases of internal task panic or cancellation, does not represent upstream failure, and carries nodata.reason. - Notification billing: Notifications (204) are billed as normal. Notifications are billed when the node processes the batch successfully: upstream HTTP 2xx; when the batch has calls with an id, at least one received a normal response and there are no
-32002/-32003/-32600elements; requests containing only notifications are billed if the upstream returns 2xx with an empty body.
JSON-RPC Error Codes Table
| Code | Source | HTTP | Message | Reason | Billed? | Recommended Action |
|---|---|---|---|---|---|---|
| -32700 | BlockVectra | 200 | parse error | - | No (costs 1 CU rate-limit token) | Fix request JSON syntax |
| -32600 | BlockVectra | 200 | invalid request | invalid_request | No (costs 1 CU rate-limit token) | Fix JSON-RPC request syntax and structure |
| -32600 | BlockVectra | 200 | batch too large: max <N> calls | batch_too_large (+max) | No | Split batch into calls under the limit (standard batch limit is 100) |
| -32600 | BlockVectra | 200 | invalid request: ambiguous member name | invalid_request | No | Remove duplicate or ambiguous member names in JSON objects |
| -32601 | BlockVectra | 200 | method not available: <method> | - | No | Call only methods allowed for this chain (see Supported Chains) |
| -32600 | BlockVectra | 404 | unknown chain | unknown_chain | No | Check the chain name in the URL |
| -32602 | BlockVectra | 200 | eth_getLogs block range too large: max <N> blocks | - | No | Narrow the eth_getLogs block range (limit defined per chain, e.g. 1000 blocks) |
| -32602 | BlockVectra | 200 | tracer not allowed | - | No | Use an allowed native tracer (callTracer, flatCallTracer, prestateTracer, 4byteTracer, noopTracer, or omit) |
| -32602 | BlockVectra | 200 | trace timeout not allowed | - | No | Set a valid Go duration string with timeout ≤ 30s |
| -32010 | BlockVectra | 200 | node is syncing; calls are temporarily unavailable | - | No | Node is syncing, retry later (except for eth_chainId) |
| -32011 | BlockVectra | 200 | historical state is not available beyond the most recent <N> blocks | - | No | Query a more recent block (target block must be within the state window; avoid safe/finalized/earliest tags) |
| -32000 | BlockVectra | 200 | transaction not found | not_found | No | Verify transaction hash (0x + 64 hex characters) |
| -32000 | BlockVectra | 200 | block not found | not_found | No | Verify block hash or number |
| -32000 | BlockVectra | 200 | upstream response too large | response_too_large | No | Narrow query scope or split requests |
| -32005 | BlockVectra | 200 | gateway overloaded, retry later | overloaded | No | Server temporarily overloaded, retry later |
| -32005 | BlockVectra | 429 | rate limit exceeded | key_rate_limit / free_plan_call_limit / concurrency_limit | No | Reduce request frequency; honour Retry-After when present |
| -32022 | BlockVectra | 429 | request cost <N> CU exceeds burst capacity <M> CU | request_exceeds_burst | No | Split request or batch so single-request CU is below burst capacity |
| -32022 | BlockVectra | 429 | request has <N> calls, exceeding the free-plan limit of <M> calls per second | free_plan_batch_too_large (+max) | No | Split batch to fit under per-second limit, or upgrade to a paid plan |
| -32603 | BlockVectra | 200 | upstream unavailable | upstream_unavailable | No | Upstream communication failure, retry later |
| -32603 | BlockVectra | 200 | no response from upstream | upstream_unavailable | No | Upstream did not respond, retry later |
| -32603 | BlockVectra | 200 | malformed upstream response | upstream_unavailable | No | Upstream response malformed, retry later |
| -32603 | BlockVectra | 200 | internal gateway error | - | No | Rare internal error, retry later |
| -32020 | BlockVectra | 402 | insufficient balance | balance_exhausted / free_grant_exhausted | No | Go to Console billing page to top up, or wait for free refill |
| -32021 | BlockVectra | 503 | billing data temporarily unavailable | - | No | Billing data syncing (not a balance issue); wait Retry-After seconds and retry |
| 4444 | Node | 200 | pruned history unavailable | - | No | Requested block was pruned by node (~7-day history retention); not billed; does not affect batch |
| -32000 | Node | 200 | historical state ... is not available | - | No | Outside node state history window (~128 blocks); not billed; does not affect batch |
| -32000 | Node | 200 | old data not available due to pruning... | - | No (Erigon, ETH mainnet) | Outside node history window (Erigon ~36-day window); not billed; does not affect batch |
| -32002 | Node | 200 | <node message> | - | No | Node timed out on batch and abandoned call; not billed; notifications in batch also not billed |
| -32003 | Node | 200 | <node message> | - | No | Node batch response too large and abandoned; not billed; notifications in batch also not billed |
| -32600 | Node | 200 | <node message> | - | No | Entire batch rejected by node; not billed; notifications in batch also not billed |
| Other | Node | 200 | <node message> | - | Yes (method weight) | Node performed work (e.g. execution reverted, node -32602, node -32601); check contract call parameters |
Data API Billing Rules
The Data API wraps read-only chain data into REST endpoints. Its billing and error handling follow these rules:
Rule Details
- "A Data API request is billed only when it succeeds."
- "Requests are metered and billed in Compute Units (CU); only 2xx successful responses are billed."
- "Chain-specific operations that are unavailable (e.g. unsupported chain or outside trace coverage) return HTTP 422 and are not billed."
- "Requests outside our data coverage are not billed but may count toward rate limits."
- "There are two exceptions for 404 errors: an unknown or not-public chain returns HTTP 404 with
error.codenot_found(decided before the key check, not billed, and not rate-limited; chain names must be exact lowercase slugs), while a missing, unknown, or disabled API key gets HTTP 404 with an empty body (identical to JSON-RPC). Requests exceeding rate limits return HTTP 429 (error.coderate_limitedwithdata.reasonkey_rate_limit), and exhausted balances return HTTP 402 (error.codeinsufficient_balance); neither is billed."
Data API Status Codes Table
| HTTP Status | Error Code / Scenario | Billed? | Recommended Action |
|---|---|---|---|
| 200 | Successful data response | Yes (Data API operation CU weight) | Parse data, meta, and next_cursor in the response envelope |
| 400 | Request parameters malformed or missing required fields | No | Check and fix query or body parameters |
| 402 | Balance exhausted (error.code: "insufficient_balance") | No | Go to Console billing page to check balance and top up |
| 404 | Unknown or not-public chain (error.code: "not_found", decided before the key check; does not count against rate limits), requested object does not exist, or API key missing/unknown/disabled (empty body) | No | Check the chain slug in the URL (must be exact lowercase); pass a valid key in the x-api-key header |
| 409 | Requested block is above the current indexed height (error.code: "not_indexed_yet", includes indexed_through) | No | Query blocks up to indexed_through or retry later |
| 409 | Requested block is above finalized_block (error.code: "finality_exceeded") | No | Wait until the block is finalized, or query an older block |
| 422 | Chain-specific operation unavailable (e.g. unsupported chain or outside trace coverage, error.code: "no_coverage") | No (counts toward rate limits) | Verify chain capabilities via GET https://dev-api.blockvectra.network/v1/data/chains to avoid queries outside coverage |
| 429 | Rate limit exceeded (error.code: "rate_limited"), or a single request costs more than the key's burst capacity (error.code: "cost_exceeds_burst") | No | Reduce request frequency; split oversized requests (a burst-exceeding request will never succeed as sent) |
| 503 | Data service temporarily unavailable (error.code: "unavailable"), or the chain is busy (error.code: "gateway_overloaded") | No | Retry later and honour Retry-After when present |
Testing note: These rules were confirmed on 2026-09-30 with a new free-plan account on the production environment: rejected methods (
-32601), a syncing node (-32010), and the Data API's409 finality_exceededand422 no_coveragedid not add to usage, while successful calls were metered at the weights published byGET /v1/plans. This is a single observation, not a guarantee.
Pricing and Upgrades
The specific cost for all billed calls is determined by published CU weights:
- To inspect weights for all methods and operations, see the method weight table and the JSON-RPC CU Metering Rules.
- For plan pricing and settlement details, see the Pricing page.
- Upgrading to a paid plan: making a paid top-up removes the Free Plan's per-second call limit; each key remains subject to CU rate and burst limits.
One key, many chains: switching an example to another chain
The same API key works on every supported chain. Learn how URLs are structured, how to discover chains programmatically, and how balances and limits are pooled.
Connect an AI agent to BlockVectra: llms.txt, OpenAPI and public JSON
Integration guide for AI agents and LLM tools: discover capabilities, query public metadata, and call BlockVectra APIs using llms.txt, OpenAPI specs, and public endpoints.