Skip to content
IBANforge

Error Reference

IBANforge uses standard HTTP status codes and returns structured JSON errors, {"error": "<token>", "message": "<sentence>"}. Branch on error, which is stable; message may be reworded. This page covers the statuses of the API and the codes its routes share; a code that belongs to one route only (API keys, UK firms) is on that route's page.

An invalid IBAN is not an error status. POST /v1/iban/validate answers HTTP 200 with valid: false, an error code and an error_detail sentence. Only the request itself (its JSON, a missing field, payment, quota, size, rate) changes the HTTP status.

HTTP status codes

StatusMeaningWhen it happens
200OKThe request was answered. An invalid IBAN still returns 200 with valid: false; an unknown BIC returns 200 with found: false
400Bad RequestMalformed JSON, a missing field, or an invalid parameter
401UnauthorizedThe key routes only. missing_key (no key sent) on GET /v1/keys/usage, GET /v1/keys/report, GET /v1/credits/balance, POST /v1/keys/claim, POST /v1/keys/revoke and POST /v1/keys/rotate; invalid_key (unknown or inactive key) on the first four. POST /v1/keys/claim still accepts a key cut off for a burst of automated signups: claiming is how it comes back. A paid route never answers 401
403Forbiddenverification_required: POST /v1/keys/generate with an address, from a network that took a key recently; a code was mailed, repeat the request with it. forbidden_origin: approving or refusing a device key (POST /v1/keys/device/approve, /deny) from a page on another origin
402Payment RequiredA paid route called without a usable way to pay: no key and no free allowance left, a key that is invalid or has spent its allowance or credits, or a payment that was refused. The x402 payment envelope, with a cause when one applies
404Not FoundUnknown endpoint. On POST /v1/keys/revoke and POST /v1/keys/rotate, invalid_key: the key is unknown or already revoked
405Method Not AllowedRight path, wrong method (for example GET /v1/keys/generate); the allow field names the method to use
409ConflictThe key routes: already_claimed: the key is already past the anonymous tier. already_claimed_elsewhere: that address already holds a claimed key, or claimed one in the last 24 hours. verification_in_flight: a code for that address was issued moments ago; use it, or try again in a few minutes. The pack route (POST /v1/credits/buy/…), for a payment already seen whose purchase was not credited: payment_pending (its settlement is not confirmed yet, do not pay again), payment_refused (sign a new payment) or payment_reversed; nothing is settled again
413Payload Too LargeRequest body over 256 KB
429Too Many RequestsMore than 100 requests in one minute from the same IP address; wait for Retry-After
500Internal Server ErrorUnexpected server error (please report it, see Support)
502, 503Bad Gateway, Service UnavailableThe x402 payment rail could not be reached or answered with an error. Retry later. Except 502 settlement_unconfirmed: the outcome of your payment is unknown and it may already be on-chain, so do not pay again before checking the transfer (settlement.transaction carries its hash when the facilitator returned one). On the key routes, 503 verification_unavailable: the verification mail could not be sent (a key created with an address, a claim, a device approval); try again in a few minutes. The UK firms route has its own 502 and 503 codes, on its page

Validation error codes

These appear in the body of a 200 answer when valid is false: the request succeeded, the IBAN did not pass. POST /v1/iban/validate, each item of POST /v1/iban/batch and the free GET /v1/iban/format use the same six codes. One exception on /v1/iban/format: a length out of bounds (fewer than 15 or more than 34 characters once spaces and hyphens are removed, or more than 64 as sent) is a 400 invalid_iban_length, not a 200.

CodeDescriptionExample cause
invalid_formatCharacters other than letters, digits, spaces and hyphens; fewer than 5 characters; or more than 64 characters as sentA dot or an en dash between the groups, curly quotes, a truncated paste
unsupported_countryThe first two letters are not one of the 89 IBAN countriesXX00 0000 0000 0000. Free text lands here too: its first two letters are read as a country code
wrong_lengthThe length does not match the IBAN length of that countryCH93 0076 2011 6238 5295 has 20 characters; a Swiss IBAN has 21
invalid_check_digitsCharacters 3 and 4 are not two digits, or are 00, 01 or 99 (ISO 13616 allows 02 to 98)DE00 3704 0044 0532 0130 00
checksum_failedThe MOD-97 check failsA digit was changed, or two digits were swapped
invalid_bban_structureLength and MOD-97 pass, but the national part does not follow the layout the country definesA letter inside a German bank code, with the check digits recomputed to match

Spaces (non-breaking spaces included) and ASCII hyphens are removed, and letters are read in either case, before any of these checks.

Example: validation error

{
  "iban": "CH100023000000001234",
  "valid": false,
  "error": "wrong_length",
  "error_detail": "Expected 21 characters for CH, got 20.",
  "cost_usdc": 0
}

cost_usdc is 0 when a key or the keyless trial served the call, and the route price when the call was paid with x402.

An empty or missing IBAN

{"iban": ""}, or a body with no iban at all, is an incomplete request rather than an invalid IBAN. With a key it answers 400 invalid_request. With no key it answers the 402 payment envelope and spends nothing of the keyless trial: an empty {} is how x402 indexers probe the route.

Request error codes

These return a status other than 200.

400 Bad Request

CodeRouteDescription
invalid_jsonvalidate, batch, complianceThe request body is not valid JSON
invalid_requestvalidate, batch, complianceThe iban field is missing, empty or not a string; for a batch, the body has no array of IBAN strings (ibans, iban_list or list)
empty_batchbatchThe ibans array is empty
batch_too_largebatchMore than 100 IBANs in a batch request
invalid_bic_formatGET /v1/bic/{code}The BIC is not 8 or 11 alphanumeric characters in the ISO 9362 shape
placeholder_literalGET /v1/bic/{code}, GET /v1/ch/clearing/{iid}The literal placeholder of the OpenAPI document was sent instead of a value
invalid_iid_formatGET /v1/ch/clearing/{iid}The IID is not a number of 1 to 5 digits
missing_ibanGET and POST /v1/iban/formatNo iban query parameter or body field
invalid_iban_lengthGET and POST /v1/iban/formatFewer than 15 or more than 34 characters once spaces and hyphens are removed, or more than 64 characters as sent

Example: bad request

{
  "error": "batch_too_large",
  "message": "Maximum 100 IBANs per batch request"
}

402 Payment Required

Returned when a paid route is called without a usable way to pay: no key and no free allowance left, a key that is invalid or has spent its allowance or credits, or a payment that was sent and refused. The body is the x402 payment envelope; the PAYMENT-SIGNATURE header (x402 v2) or X-PAYMENT (v1) settles it. When a precise reason applies, the body also carries cause.reason and a message that names the way out:

cause.reasonWhen
trial_exhaustedThe keyless trial of POST /v1/iban/validate is used up for this address this week; it comes back on Monday at 00:00 UTC (quota.resets gives the instant)
trial_unavailableThe keyless allowance cannot be counted right now, so the call falls back to payment
monthly_quota_exhaustedThe key's allowance for the month is used up
monthly_quota_insufficientA batch needs more requests than the key has left; nothing was consumed
credits_exhausted, credits_insufficientThe same two cases for the key's prepaid credits: a key born of a purchase, or a key whose allowance is spent and whose credits no longer cover the call. cause.credits.topup and X-Credits-Topup-Url carry the link that recharges this same key
invalid_api_keyA key was sent, but it is unknown or revoked
key_revoked_burstAn anonymous key revoked with a burst of automated signups; the message says how to claim it back
{
  "x402Version": 2,
  "error": "payment_required",
  "resource": { "url": "https://api.ibanforge.com/v1/iban/validate" },
  "accepts": [
    {
      "scheme": "exact",
      "network": "eip155:8453",
      "amount": "5000",
      "payTo": "0x...",
      "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
    }
  ]
}

When a payment was sent and refused, the body also carries payment_error with the reason.

On a valid key, the body also carries credit_packs.topup_this_key: the card links and the USDC route that recharge the key you presented, so the credits land on it and nothing changes in your integration, and, on a key without a subscription, pro: the link that puts Pro on this same key. pay_by_card keeps its meaning, a pack bought without a key, delivered as a new key.

See x402 Payments for how to handle this, and API keys for the free key.

404 Not Found

CodeDescription
not_foundThe requested endpoint does not exist. The body lists the main routes with the shape of their request

An unknown code is not a 404: GET /v1/bic/{code} answers 200 with found: false, and GET /v1/ch/clearing/{iid} answers 200 with found: false and error: "clearing_not_found".

405 Method Not Allowed

method_not_allowed: the path exists, the method does not. The allow field lists the methods the path accepts. The common case is GET /v1/keys/generate: a key is taken with a POST, and with no body at all it needs no e-mail.

413 Payload Too Large

payload_too_large: the request body is over 256 KB. It is checked before routing and before payment, so nothing is charged. A batch of 100 IBANs is about 5 KB.

429 Too Many Requests

rate_limit_exceeded: more than 100 requests in one minute from the same IP address. The answer carries a Retry-After header and a retry_after field, both in seconds. Every counted response carries RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset (seconds), plus the older X-RateLimit-* headers, whose reset is a Unix timestamp. /health, /ping, /openapi.json and /v1/demo are not counted. The same limit is published at /.well-known/rate-limits.yml.

Taking and claiming keys have their own daily limits, with their own 429 codes: see API keys. A key's monthly allowance is not a 429: it ends in the 402 above. Every answer served on a monthly key (free or claimed) carries X-Quota-Used, X-Quota-Limit and X-Quota-Remaining (GET /v1/keys/usage returns the same count); a key with prepaid credits carries X-Credits-Remaining and X-Credits-Total (GET /v1/credits/balance), and a key that holds both carries both sets. Every billed answer on a key says which one paid it in X-Charged-From: allowance, credits, or allowance+credits for a batch split between the two.

500 Internal Server Error

If you receive a 500 error, something unexpected happened on our side. The body is the plain text Internal Server Error: there is no JSON envelope on a 500. Please report it with the endpoint and the time of the call (UTC).

Troubleshooting

"Payment Required" on every request

  • Without a key, only POST /v1/iban/validate has a keyless trial (25 calls a week per source address, reset on Monday at 00:00 UTC). Every other paid route needs a key or a payment
  • Read cause.reason in the 402 body when it is there: it names the allowance that ran out
  • For x402: make sure you have USDC on the Base network (not Ethereum mainnet), that the wallet private key your client reads (for example WALLET_PRIVATE_KEY) is set, and that you use a compatible x402 client SDK

"Invalid IBAN format" but the IBAN looks correct

  • Only letters A-Z, digits 0-9, spaces and ASCII hyphens are accepted; dots, slashes and typographic dashes are refused
  • Make sure there are no other non-ASCII characters (curly quotes, zero-width spaces)
  • Case does not matter

"Unsupported country" for a valid country

  • IBANforge supports the 89 IBAN countries. Some territories use the IBAN of another country: check which one issues it
  • Double-check the two-letter country code at the start of the IBAN

"BIC not found" but the code is real

  • The BIC directory holds 121k+ entries from public sources (GLEIF, national registers such as the Bundesbank, SIX and NBP, EBA STEP2 SCT, and a public copy of the SWIFT directory frozen in January 2018) but may not cover every branch
  • Try the 8-character version (without branch code), e.g. UBSWCHZH instead of UBSWCHZH80A
  • Some financial institutions use BIC codes that are not registered with SWIFT/GLEIF

A batch request is refused

  • More than 100 items is refused as a whole with 400 batch_too_large: split the list
  • Every item must be a string: a number or an object makes the whole request 400 invalid_request
  • The results array always matches the order and count of the input array

Timeout or no response

  • A batch of up to 100 IBANs is one request, answered in one piece
  • Check your network connection and firewall rules
  • Try the free /health endpoint to verify the service is running, and the status page for live availability

Support

  • E-mail support@ibanforge.com with the endpoint, the time of the call (UTC) and your key_prefix, never the key itself
  • Public questions and bug reports: GitHub Issues
  • From an agent: POST /v1/feedback or the MCP tool send_feedback, free and with no key
  • Live availability: the status page. A written SLA exists for Editor/OEM subscriptions only: SLA