Errors
Every /api/v1 error has the same shape. Check the HTTP status first, then branch on error.code. The message text may change, so do not parse it. The exception is the position in a Beamline error, described below.
{
"error": {
"code": "invalid_chain",
"message": "Unknown chain. Use one of: ethereum, base, bnb, arbitrum, optimism, polygon, solana.",
"request_id": "req_342e0edcbc93"
}
}| Field | Type | Meaning |
|---|---|---|
error.code | string | Stable machine-readable code from the table below |
error.message | string | Text for a developer to read |
error.request_id | string | Same value as the x-request-id header. Send it when you report a problem. |
error.source | string or null | Only on upstream_unavailable. Names the source that failed. |
A successful response has data and meta at the top level, and an error response has error instead. No response has both.
#All codes
| HTTP | Code | Meaning | Retry |
|---|---|---|---|
| 400 | invalid_chain | The chain id is not one of the seven | No |
| 400 | invalid_address | The address format does not match the chain | No |
| 400 | invalid_hash | The transaction hash format does not match the chain | No |
| 400 | invalid_parameter | A query or body value is out of range or the wrong type | No |
| 400 | invalid_json | The body is not a JSON object | No |
| 401 | missing_key | The endpoint requires a key and the request has none | No |
| 401 | invalid_key | The key is unknown or revoked | No |
| 401 | sign_in_required | The endpoint needs a wallet session | No |
| 401 | invalid_challenge | The sign-in nonce expired, was used, or does not match the address | Start sign-in again |
| 401 | invalid_signature | The signature does not match the wallet and message | Start sign-in again |
| 404 | not_found | The path, rule, label, token or transaction does not exist | No |
| 405 | method_not_allowed | The path exists, the method does not | No |
| 409 | key_limit | The account already holds 5 active keys | No |
| 409 | rule_limit | The account already holds 10 rules | No |
| 409 | telegram_not_linked | A Telegram rule needs a linked chat | No |
| 413 | payload_too_large | The body is larger than 32,768 bytes | No |
| 422 | invalid_rule | The Beamline expression did not parse | No |
| 422 | invalid_url | The webhook URL was refused | No |
| 429 | rate_limited | A limit was reached | Yes, see below |
| 429 | daily_limit | The key spent 20,000 units this UTC day | After 00:00 UTC |
| 500 | internal | An unexpected error | Once, then report it |
| 502 | upstream_unavailable | A public data source did not answer | Yes, with backoff |
| 503 | telegram_not_configured | The Telegram bot is not connected | No |
#Real samples
All samples on this page were captured on 2026-11-04 UTC.
#Bad parameter
GET /transfers?limit=500 returns 400.
{
"error": {
"code": "invalid_parameter",
"message": "limit must be an integer from 1 to 100.",
"request_id": "req_e79d46ca81d5"
}
}#Address on the wrong chain
GET /tokens/solana/0xdAC17F958D2ee523a2206206994597C13D831ec7 returns 400. The format is checked against the chain family.
{
"error": {
"code": "invalid_address",
"message": "Not a valid Solana address.",
"request_id": "req_dc305197db75"
}
}#Not found
not_found covers several cases. The message tells you which one. GET /labels/0x1111111111111111111111111111111111111111 returns this:
{
"error": {
"code": "not_found",
"message": "This address is not in the Farbeam label set.",
"request_id": "req_ebde8e2eae2b"
}
}A 404 on /labels/{address} is a normal result. It means the address has no label, and it says nothing about who owns it.
#Beamline parse error
POST /rules/validate with {"expression":"usd >= "} returns 422. The message ends with a zero-based character position. See Beamline errors.
{
"error": {
"code": "invalid_rule",
"message": "Expected a value after \">=\" (at position 7)",
"request_id": "req_27cf59c83919"
}
}#Refused webhook URL
POST /rules with http://example.com/x returns 422.
{
"error": {
"code": "invalid_url",
"message": "url must use https",
"request_id": "req_b53d936c174a"
}
}#Source failure
A 502 has one extra field, source. The name uses the source names listed on the status endpoint, such as rpc:ethereum:primary or defillama. The value token-report means every source behind a token report failed.
{
"error": {
"code": "upstream_unavailable",
"message": "A public data source did not answer. Try again in a moment.",
"source": "defillama",
"request_id": "req_000000000000"
}
}Partial failure does not return 502. A wallet read with some failed chains returns 200 with partial: true. A token report with a failed source returns 200, its checks read unknown, and sources[].ok is false. See data sources.
#Handling code
body=$(curl -s -w "\n%{http_code}" "https://farbeamlabs.com/api/v1/chains/nope")
code=$(printf '%s' "$body" | tail -n1)
printf '%s' "$body" | sed '$d'
echo "HTTP $code"const res = await fetch("https://farbeamlabs.com/api/v1/chains/nope");
const body = await res.json();
if (body.error) {
const { code, message, request_id } = body.error;
console.error(`${res.status} ${code}: ${message} (${request_id})`);
} else {
console.log(body.data);
}import requests
res = requests.get("https://farbeamlabs.com/api/v1/chains/nope", timeout=30)
body = res.json()
if "error" in body:
e = body["error"]
print(res.status_code, e["code"], e["message"], e["request_id"])
else:
print(body["data"])#Paths outside the API
The live stream at /api/live returns a bare 429 with retry-after: 30 and no JSON body when the stream limit is reached. Plan for that case in stream clients. See the streaming guide.