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). JSON-RPC and Data API calls are billed only after a response is obtained. 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:

The method rows below apply to ordinary HTTP requests to /v1/{chain} and /v1/{chain}/{api_key}, not named routes such as /v1/chains. A valid WebSocket upgrade follows the WebSocket capability and authentication checks instead of the plain GET/HEAD rules.

HTTP StatusResponse BodyScenarioBilled?Recommended Action
200JSON-RPC response (single or batch)Normal response; all JSON-RPC layer errors (parse error, method rejection, upstream failure, node error) are also 200Evaluated per callInspect result or error for each call; if an error is returned, see JSON-RPC error handling below
204EmptyAll calls in the request are notificationsNotifications are billed as normalNo extra action required
204EmptyOPTIONS preflight, for either a known or unknown chainNoSend the JSON-RPC request with POST
400EmptyMalformed HTTP message (cannot parse request line or headers, invalid chunked encoding), or more than 10 s between two reads of the request bodyNoCheck HTTP request syntax, headers, and transmission continuity
402JSON, -32020Insufficient balance, allowance exhausted; when balance is known, error.data includes balance_units and balance_cuNoCheck your balance on the Console billing page or via GET /v1/topup/deposit-address (MCP get_deposit_address); top up on-chain to your account's dedicated address (see the Agent top-up guide)
403EmptyMethods other than POST, OPTIONS, GET, or HEAD on these RPC routes (regardless of whether the chain name is known)NoChange the HTTP request method to POST
405Plain GET: JSON-RPC -32600, error.data.reason: method_not_allowed; HEAD: empty body. Both include Allow: POSTPlain GET or HEAD to a known, public chain, before key checks; also applies when the chain does not support WebSocketNoUse POST for JSON-RPC
401JSON, -32024 (missing_api_key or invalid_api_key)Missing key on known chain, key unknown or disabledNoProvide 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)
404POST/GET: JSON-RPC -32600 (error.data.reason: unknown_chain); HEAD: empty body, without AllowPOST, GET, or HEAD to an unknown or not-public {chain}, before key checksNoCheck the chain name in the URL against Supported Chains (must be exact lowercase slug)
404empty bodyUnmatched path (e.g. POST /v1, /v1/, POST /v1/{chain}/)NoInclude chain in URL (/v1/{chain})
408EmptyExceeded 35 s from reading request headers to returning responsePossible: calls already forwarded to the node are billed as normal once the node respondsDo not unconditionally retry state-changing calls (e.g. eth_sendRawTransaction); a client disconnect does not cancel calls already forwarded
413EmptyRequest body > 2 MiB (2,097,152 bytes; see “10. Limits at a glance” in the full OpenAPI reference)NoKeep request body under 2 MiB; split batches into smaller requests
414 / 431EmptyURI too long (414) or request headers too large (431)NoShorten request URI or trim HTTP request headers
429JSON, -32005 or -32022; carries Retry-After for rate limits (-32005); burst/batch size limits (-32022) do not carry itBucket balance depleted → -32005; single request CU exceeds burst capacity → -32022; account call rate limit depleted → -32005; calls in single request exceed limit → -32022NoFor -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)
503JSON, -32021, with Retry-AfterBilling 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)NoNot 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.

Charge and balance response headers: When sending x-bv-meter: 1 on HTTP requests (applicable to both JSON-RPC and Data API), a response that billed at least one call returns x-bv-cu-charged (the Compute Units billed for this request, or the sum across billed calls of a batch) and x-bv-balance-units (the account's remaining balance units right after this charge, negative when overdrawn; omitted if the balance is unknown). Requests without x-bv-meter: 1, responses where nothing was billed, and 402, 403, 429, or 503 error responses omit both headers. These response headers are accessible to browser scripts via CORS, while WebSocket does not use them. The balance subtracts total unsettled usage rounded up once to whole units; hourly settlement rounds down, so the reported balance may rise by up to one unit after settlement.

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; these and any notifications in the same batch are not billed. Node -32601 (exposed method not implemented) and -32603 (node internal failure) are not billed over HTTP or WebSocket and do not affect other calls or notifications in the batch. In addition, 4444 (pruned block) and -32000 (historical state outside the node's state history window, defined by state_window_blocks in GET /v1/chains) are not billed and do not affect other calls in the batch.
  • Node errors billed: Other errors returned by the node are billed at the method weight when they report the chain's outcome, such as execution reverted (-32000 or 3 with data), the node's own -32602 invalid argument.
  • Balance admission and sync: -32020 indicates insufficient account balance and requires a top-up; when the balance is known, error.data.balance_units and error.data.balance_cu carry what is left (it can be negative). A newly created key may return -32021 (503) for a few seconds; wait Retry-After and retry.
  • Upstream failures: A -32603 generated by the platform due to upstream communication failure or malformed response (upstream unavailable, no response from upstream, malformed upstream response) carries data.reason: upstream_unavailable.
  • Notification billing: Notifications (204) are billed at their method weights.

JSON-RPC error codes table

CodeSourceHTTPMessageReasonBilled?Recommended Action
-32700BlockVectra200parse error-No (costs 1 CU rate-limit token; see “9. Rate limiting” in the full OpenAPI reference)Fix request JSON syntax
-32600BlockVectra200invalid requestinvalid_requestNo (costs 1 CU rate-limit token; see “9. Rate limiting” in the full OpenAPI reference)Fix JSON-RPC request syntax and structure
-32600BlockVectra200batch too large: max <N> callsbatch_too_large (+max)NoSplit batch into calls under the limit (standard batch limit is 100)
-32600BlockVectra200invalid request: ambiguous member nameinvalid_requestNoRemove duplicate or ambiguous member names in JSON objects
-32601BlockVectra200method not available: <method>-NoCall only methods allowed for this chain (see Supported Chains)
-32600BlockVectra404unknown chainunknown_chainNoCheck the chain name in the URL
-32602BlockVectra200eth_getLogs block range too large: max <N> blocks-NoNarrow the eth_getLogs block range (limit defined per chain, e.g. 1000 blocks)
-32602BlockVectra200tracer not allowed-NoUse an allowed native tracer (callTracer, flatCallTracer, prestateTracer, 4byteTracer, noopTracer, or omit)
-32602BlockVectra200trace timeout not allowed-NoSet a valid Go duration string with timeout ≤ 30s
-32010BlockVectra200node is syncing; calls are temporarily unavailable-NoNode is syncing, retry later (except for eth_chainId)
-32011BlockVectra200historical state is not available beyond the most recent <N> blocks-NoQuery a more recent block (target block must be within the state window; avoid safe/finalized/earliest tags)
-32000BlockVectra200transaction not foundnot_foundNoVerify transaction hash (0x + 64 hex characters)
-32000BlockVectra200block not foundnot_foundNoVerify block hash or number
-32000BlockVectra200upstream response too largeresponse_too_largeNoNarrow query scope or split requests
-32005BlockVectra200-overloadedNoServer temporarily overloaded, retry later
-32005BlockVectra429rate limit exceededkey_rate_limit / free_plan_call_limit / concurrency_limitNoReduce request frequency; honour Retry-After when present
-32022BlockVectra429request cost <N> CU exceeds burst capacity <M> CUrequest_exceeds_burstNoSplit request or batch so single-request CU is below burst capacity
-32022BlockVectra429request has <N> calls, exceeding the free-plan limit of <M> calls per secondfree_plan_batch_too_large (+max)NoSplit batch to fit under per-second limit, or upgrade to a paid plan
-32603BlockVectra200upstream unavailableupstream_unavailableNoUpstream communication failure, retry later
-32603BlockVectra200no response from upstreamupstream_unavailableNoUpstream did not respond, retry later
-32603BlockVectra200malformed upstream responseupstream_unavailableNoUpstream response malformed, retry later
-32603BlockVectra200--NoRare internal error, retry later
-32020BlockVectra402insufficient balancebalance_exhausted / free_grant_exhausted (+topup_url, and +balance_units / balance_cu when balance is known)NoCheck your balance on the Console Billing page or via GET /v1/topup/deposit-address (MCP get_deposit_address); top up on-chain to your account's dedicated address (see the Agent top-up guide)
-32021BlockVectra503billing data temporarily unavailable-NoBilling data syncing (not a balance issue); wait Retry-After seconds and retry
4444Node200pruned history unavailable-NoRequested block was pruned by node; not billed; does not affect batch
-32000Node200historical state ... is not available-NoOutside node state history window; not billed; does not affect batch
-32000Node200old data not available due to pruning...-NoOutside node history window (window determined by state_window_blocks); not billed; does not affect batch
-32002Node200<node message>-NoNode timed out on batch and abandoned call; not billed; notifications in batch also not billed
-32003Node200<node message>-NoNode batch response too large and abandoned; not billed; notifications in batch also not billed
-32601Node200<node message>-NoExposed method is not implemented by the node; use another supported method
-32603Node200<node message>-NoNode internal failure; retry with backoff
-32600Node200<node message>-NoEntire batch rejected by node; not billed; notifications in batch also not billed
OtherNode200<node message>-Yes (method weight)Chain outcome (e.g. execution reverted, node -32602); 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

  • Only 2xx successful responses are billed.
  • Unavailable operations outside coverage (such as unsupported chains or blocks outside trace coverage) return HTTP 422 no_coverage, which is not billed but counts toward rate limits.
  • HTTP 401, 402, 404, and 429 responses are not billed. For response headers (x-bv-meter: 1), see HTTP status codes and billing rules.

Data API status codes table

HTTP StatusError Code / ScenarioBilled?Recommended Action
200Successful data responseYes (Data API operation CU weight)Parse data, meta, and next_cursor in the response envelope
400Request parameters malformed or missing required fieldsNoCheck and fix query or body parameters
402Balance exhausted (error.code: "insufficient_balance", includes balance_units and balance_cu when balance is known)NoCheck your balance on the Console billing page or via GET /v1/topup/deposit-address (MCP get_deposit_address); top up on-chain to your account's dedicated address (see the Agent top-up guide)
401API key missing, unknown or disabled (error.code: "missing_api_key" or "invalid_api_key")NoPass an active API key in the x-api-key header
404Unknown or not-public chain (error.code: "not_found"), or requested object does not existNoCheck the chain slug in the URL (must be exact lowercase) and the request path
409Requested block or window is above the current indexed height (error.code: "not_indexed_yet", includes indexed_through)NoQuery blocks up to indexed_through or retry later
422Chain-specific operation unavailable (e.g. unsupported chain or outside trace coverage, error.code: "no_coverage")No (counts toward rate limits)Check supported features via GET /v1/status (free, keyless data_features)
429Rate limit exceeded (error.code: "rate_limited"), or a single request costs more than the key's burst capacity (error.code: "cost_exceeds_burst")NoReduce request frequency; split oversized requests (a burst-exceeding request will never succeed as sent)
503Data service temporarily unavailable (error.code: "unavailable"), or the chain is busy (error.code: "gateway_overloaded")NoRetry later and honour Retry-After when present

Query balance (GET /v1/account)

An API key holder can check balance and key quota details directly without incurring any billing or deducting Compute Units (CU):

curl -H "x-api-key: $BLOCKVECTRA_API_KEY" https://api.blockvectra.com/v1/account
  • Free and unbilled: GET /v1/account is free. It is never billed, does not deduct CU, and returns HTTP 200 with the current balance even when it is zero or negative (it never returns 402).
  • Authentication: Key authentication uses the x-api-key header exclusively (path keys and Bearer tokens are not accepted). Missing header returns 401 missing_api_key; invalid or revoked keys return 401 invalid_api_key. (Expired keys return 403 key_expired; transient service unavailabilities return 503 auth_unavailable or billing_unavailable with Retry-After.)
  • Rate limiting: Has an independent limit of 5 requests per second per key ID, independent of CU metering and billing (see “10. Limits at a glance” in the full OpenAPI reference). Exceeding the limit returns HTTP 429 rate_limited with a Retry-After header.

Response fields:

  • key_id: The API key's identifier string.
  • plan: Account plan type (free when the account has a free-plan call-rate allowance; paid otherwise).
  • balance_units: Remaining account balance in units (may be zero or negative).
  • balance_cu: Remaining balance converted to Compute Units (CU).
  • balance_as_of_age_ms: Milliseconds elapsed since the balance was read from its data source.
  • key: Key-specific limits and quota details:
    • cu_per_sec: Token-bucket refill rate in CU per second.
    • burst_cu: Token-bucket burst capacity in CU.
    • cu_cap: Lifetime CU cap for this key, or null if uncapped.
    • cu_cap_remaining: CU remaining under cu_cap, or null if uncapped (can be zero or negative).
    • expires_at: RFC 3339 expiration timestamp, or null if the key never expires.

Example response:

{
  "key_id": "<key_id>",
  "plan": "<plan>",
  "balance_units": <integer>,
  "balance_cu": <integer>,
  "balance_as_of_age_ms": <integer>,
  "key": {
    "cu_per_sec": <integer>,
    "burst_cu": <integer>,
    "cu_cap": <integer_or_null>,
    "cu_cap_remaining": <integer_or_null>,
    "expires_at": "<expires_at_or_null>"
  }
}

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.

On-Chain Top-up Process

When your account balance is insufficient or you need higher throughput, top up on-chain in the console following these steps:

  1. Log in to the Console: Sign in to the BlockVectra Console.
  2. Go to the Billing Page: Navigate to the Billing page.
  3. Get Your Dedicated Address: In the on-chain top-up card, copy your account's dedicated top-up address or scan the QR code.
  4. Transfer Funds: Transfer only using the supported networks and USDC / USDT / USDG listed on the page. Supported networks and minimum top-up amounts are shown in the console.
  5. Automatic Crediting: Once detected on-chain, transactions show as "Processing"; once credited, credits are automatically added to your balance.

Important Notes:

  • Only use the networks and tokens explicitly listed in the console. Transfers on unsupported chains or with wrong tokens cannot be credited automatically.
  • Ensure each transfer meets the minimum top-up amount indicated in the console.
  • Once your first paid top-up is credited, your account is upgraded to a paid account, removing the Free Plan's per-second call limit.

Agent or server programs can directly call top-up endpoints using an API key; see the Agent programmatic top-up guide.

Webhook push billing

Push has separate weights for delivered data events, successful history queries and billable address-days. Management calls other than event history, failed delivery attempts, automatic retries and control events are free. Each delivered event is charged once; customer replay and canonical events redelivered after a reorg are new billed deliveries. Address charges use each subscription’s maximum address count while online during the UTC day; the account free-address allowance is shared across subscriptions, with older subscriptions using it first. An address in two subscriptions is counted twice; adding chains changes event fees, not address fees.

See the Blockchain Webhook API guide for setup, signature verification and delivery recovery. The stablecoin payment guide covers receipt validation and polling backfill; WebSocket subscriptions use their own connection and notification metering. Request errors are listed in the error reference. The weights below come from GET /v1/plans.

UsageBilling unitCU
push.address_dayBillable address-day33
push.historySuccessful history request25
push.logDelivered data event150
push.native_transferDelivered data event150
push.token_transferDelivered data event150

Free addresses per account per UTC day: 1000

Free address allowance per account per UTC day, shared by all subscription groups regardless of plan. For each group, count its maximum address count while online during that day; allocate the allowance in ascending group ID order. The same address in two groups counts twice; the number of chains in a group does not multiply its address count. A group offline or deleted for the entire day contributes nothing. For each group, the remaining count after its share of the allowance is multiplied by the `push.address_day` CU weight in `method_weights`. The current configured allowance comes from the same pricing policy used for the address-day charge; it is not an account capacity limit or a separate allowance per group.

Example: 10 delivered native.transfer events, 2 successful history requests and 10 billable address-days cost 10 × 150 + 2 × 25 + 10 × 33 = 1880 CU. Billable address-days are counted after the account free-address allowance.

Next steps

Last updated:

On this page