Skip to main content
All Limitguard API errors follow RFC 7807 Problem Details for consistent, machine-readable responses. Every error has a type, title, status, and detail field, which makes automated error handling straightforward for both human developers and AI agents.
The type field is always "about:blank" in the current API version. Future versions may introduce specific problem type URIs.

Status Code Reference


Error Response Format

Standard Error

All non-2xx responses return RFC 7807 problem details:

Validation Error (422)

Field-level validation errors return a detail array instead of a string. Field names are sanitized, so internal paths are not exposed:
When detail is an array, iterate over it to surface all field errors at once. This avoids fixing one error only to encounter the next on retry.

400 Bad Request

Cause: A required request body field is absent entirely, or the request body is missing.
Fix: Check that your request includes all required fields. For /v1/entity/check, both entity_name and country are required. Verify you are sending Content-Type: application/json and a valid JSON body.
Cause: The request body cannot be parsed as JSON, often because of a trailing comma, an unclosed brace, or non-UTF-8 encoding.
Fix: Validate your JSON before sending. Use json.dumps() in Python or JSON.stringify() in JavaScript rather than constructing JSON strings manually.
Cause: The Content-Type header is missing or set to a value other than application/json on a POST endpoint.Fix: Always include -H "Content-Type: application/json" on POST requests.

401 Unauthorized

Cause: The request reached an authenticated endpoint without an X-API-Key header, and no payment header (PAYMENT-SIGNATURE or X-PAYMENT) was provided either.
Fix: Add X-API-Key: lg_live_xxxxxxxxxxxxxxxxxxxx to every request. Free endpoints (health, key creation, well-known routes) never require authentication.
Cause: The key was valid but has since been revoked or expired.Fix: Create a new key via POST /v1/keys/create. Keys are returned once: if lost, create a new one.
Cause: A key starting with lg_test_ was sent to the production API, which refuses it: 401 Test keys not accepted in production.Fix: For mock data use a sandbox key (lg_sandbox_..., free from POST /v1/keys/create with "tier": "sandbox"); for real data use an lg_live_ key. There is no sandbox header: X-Limitguard-Mode is ignored.

402 Payment Required

HTTP 402 is a protocol response, not just an error. Limitguard implements the x402 V2 micropayment protocol. When you receive a 402, the response body is not an RFC 7807 error: it is a payment requirements object.
For AI agents, 402 is the expected first response when no payment or API key is provided. The correct flow is: receive 402 → build payment → retry with the PAYMENT-SIGNATURE header (or the V1 X-PAYMENT header).

Payment Requirements Response

Trimmed: each accepts entry also repeats resource, description and mimeType, and a third entry offers the settled-transfer scheme. The field reference is on the x402 Protocol page.

x402 Payment Flow

1

Receive 402

Parse the accepts array. Choose an entry whose network (a CAIP-2 chain ID) your agent can pay on.
2

Check the amount

The amount field uses 6 decimal places: 1050000 is $1.05 USDC, the fresh price of POST /v1/entity/check. Pay the amount the 402 quotes, and verify your wallet has sufficient balance before signing.
3

Build EIP-3009 signature (EVM) or SPL transfer (Solana)

Sign a TransferWithAuthorization to the entry’s payTo, with a unique nonce and a validBefore no more than ten minutes ahead (the quote’s maxTimeoutSeconds is 600). See the x402 Protocol guide for full code examples.
4

Retry with the payment header

Base64-encode your payment payload and send it as PAYMENT-SIGNATURE (x402 V2) or X-PAYMENT (V1). Retry the exact same endpoint and body.

Common 402 Sub-Cases

Cause: The amount in your payment object is less than the minimum required for the endpoint and quality tier.
Fix: Use the amount value from the 402 response exactly. If using a non-default X-Response-Quality tier, the required amount changes: cached requires less. See the pricing table for per-endpoint amounts.
Cause: The validBefore timestamp in the EIP-3009 signature has passed (errorCode: expired_payment). The quote’s maxTimeoutSeconds is 600, so sign a validBefore no more than ten minutes ahead.Fix: Rebuild the payment with a fresh timestamp. Do not cache signatures for reuse: build a new one per request.
Cause: The same nonce was used in a previous request within the last ten minutes.
Fix: Generate a cryptographically random 32-byte nonce for every request. Never reuse nonces, even if the previous request failed.
Cause: The EIP-712 signature does not verify against the claimed sender address, or the Solana signature is malformed.Fix: Ensure the sender field matches the wallet that signed the transaction. Verify the EIP-712 domain parameters match exactly: name: "USD Coin", version: "2", chainId as integer, verifyingContract as the USDC contract address.
Cause: The network (or chainId) in your payment is not one the quote listed in accepts (errorCode: unsupported_network).Fix: Pay one of the networks in the 402’s accepts array. The production API quotes eip155:8453 (Base Mainnet) and solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp (Solana Mainnet).
For testing x402 without spending real USDC, use Base Sepolia or Solana Devnet against a test environment that lists them in its accepts array. The production API does not accept testnet payments (testnet_supported: false in /.well-known/x402.json).

x402 error codes

A 402 that rejects a payment carries errorCode in its body beside error; the facilitator endpoints /x402/verify and /x402/settle return the same values as invalidReason. This table is generated from the API’s X402ErrorCode enum.

403 Forbidden

Cause: POST /v1/reports/entity (and the MCP get_compliance_report tool) was called with a sandbox key. Reports are built only from real checks.
Fix: Use an lg_live_ key or pay per call with x402.
Cause: The route is for the service operator (for example /v1/admin/*). Customer keys carry the least-privileged role, so the API answers 403 with Insufficient role or Insufficient permissions.Fix: None needed on your side: these routes are not part of the customer API.
Cause: The watchlist routes (/v1/watchlist) belong to an API key’s own tenant. A call that reached them without a key-bound tenant, for example one paid only by x402, is answered 403 Tenant context required.Fix: Call the watchlist routes with an API key.

Entity report errors

POST /v1/reports/entity and GET /v1/reports/{report_id} answer errors as RFC 7807 problem details whose type links to the entries below. Each body also carries instance (the request path) and errorCode.

404 Not Found

Cause: A lookup endpoint (e.g., GET /v1/reputation/history/{entity_hash}) was called with an entity hash that does not exist in the system.
Fix: Entity hashes are generated by Limitguard from the entity data. Run a POST /v1/entity/check first to create the entity record, then use the returned entity_hash for subsequent lookups.
Cause: A DELETE /v1/webhooks/{webhook_id} or test call was made with an unknown webhook_id, or with the ID of a webhook another API key registered.Fix: Use GET /v1/webhooks to list all registered webhooks and confirm the correct webhook_id.
Cause: The URL path does not exist, often because of a typo (e.g., /v1/entity/checks instead of /v1/entity/check) or a missing version prefix.Fix: All API endpoints are under /v1/. Refer to the API Reference for the exact path of each endpoint.

422 Unprocessable Entity

422 errors occur when the request is syntactically valid JSON but the field values fail business-logic validation. For field validation the detail field is an array of field-level errors; a few checks made after validation (such as the webhook URL check) return a single string detail instead.
422 responses are sanitized: internal field paths and database details are never exposed. The field name matches the key in your request body.

Common Validation Errors

Cause: country is not a valid ISO 3166-1 alpha-2 code, or uses the alpha-3 format.Fix: Use two-letter uppercase codes: NL, BE, DE, FR, US. Not NLD, Netherlands, or lowercase nl.
Cause: entity_name is fewer than 2 characters or more than 255 characters.Fix: Pass the legal entity name as registered. Single-character values and very long strings are rejected.
Cause: kvk_number contains non-numeric characters or is not exactly 8 digits.Fix: KVK numbers are always 8 digits: "12345678". Do not include spaces, dashes, or the KVK: prefix.
Cause: iban fails structural validation (country prefix, check digits, or length for the given country).Fix: Pass a complete IBAN including country code and check digits: "NL91ABNA0417164300". Strip spaces before sending.
Cause: vat_number does not match the expected format for the given country prefix.Fix: Include the country prefix: "NL123456789B01", "BE0123456789". Format rules vary by country: see the European Commission VIES guidelines for country-specific formats.
Cause: wallet_address is not a valid EVM (0x…, 42 chars) or Solana (base58, 32-44 chars) address.Fix: Validate the address client-side before sending. EVM addresses must be checksummed or all-lowercase hex. Solana addresses must be valid base58.
Cause: domain contains a protocol prefix, path, or query string instead of a bare hostname.Fix: Send the bare domain only: "acmecorp.nl", not "https://acmecorp.nl/about?lang=en".
Cause: events array in POST /v1/webhooks contains an unrecognized event name.Fix: Use event types from the list in the Webhooks guide: sanctions.match.new, trust.score.changed, trust.level.downgrade or certificate.expired. There is no * wildcard. Only sanctions.match.new is sent today; delivered_events in the registration response lists which of yours are live.
Cause: The url in POST /v1/webhooks is not https://, its host does not resolve, or it resolves to a private, loopback, link-local, reserved or cloud-metadata address. This error carries a plain string detail instead of the field array above:
Other detail values: "URL must use HTTPS" and "Cannot resolve hostname '<host>': ...".Fix: Use a public https:// URL whose host resolves in public DNS.

429 Too Many Requests

Limitguard enforces two independent limits per key: a per-minute limit and a rolling 24-hour limit. A verified x402 payer has a per-minute limit only.

Rate Limit Response

Retry-After Header

Every 429 response includes a Retry-After header with the number of seconds to wait:

Rate Limits by Tier

See Rate Limits for the authoritative table and Pricing for upgrade prices.

Daily Limit Reached

When a key hits its rolling 24-hour limit, the detail names it:
Fix: Wait for Retry-After, top up to a higher tier for a higher limit, or pay per call with x402, which has no daily cap. The daily caps on keys are abuse limits, not a usage allowance you buy.
Use the X-Response-Quality: cached header where acceptable: a cached answer costs less when the entity was already scored within the cache TTL.

500 Internal Server Error

Cause: An unhandled exception occurred server-side. This is always a Limitguard bug, never a client error. Fix:
  1. Note the Request ID from the detail field.
  2. Retry with exponential backoff: most 500s are transient.
  3. If the error persists for more than 5 minutes, check api.limitguard.ai/health for service status.
  4. Report persistent 500s to support@limitguard.ai with the Request ID.
500 errors on write operations (webhook creation, compliance subscription) should not be retried blindly: the operation may have partially succeeded. Check the resource state first with a GET before retrying.

503 Service Unavailable

Cause: Planned maintenance window or a cascading failure in a critical dependency (e.g., the sanctions list provider is unreachable and the circuit breaker is open). Fix:
  • Check Retry-After header if present.
  • Subscribe to status updates at api.limitguard.ai/health.
  • For x402 users: the circuit breaker fallback (cached wallet verification) handles most dependency failures transparently. A 503 indicates a more severe outage.

Request validation errors

Validation Error

HTTP 422, errorCode validation_error. What happened: The request body does not fit the endpoint. detail lists every field that failed with what is wrong with it; a rule about two fields names both. Nothing was charged. What to do: Fix the fields detail names and send the request again.

Lead Verify errors

Lead Verify Not Available

HTTP 404, errorCode lead_verify_not_available. The MCP tool answers status rejected with the same sentence as error and lead_verify_not_available as code. What happened: Lead Verify is switched off on this server. Nothing was charged. What to do: Try again later.

Lead Verify Not Available In Sandbox

HTTP 403, errorCode lead_verify_not_available_in_sandbox. The MCP tool answers status rejected with the same sentence as error and lead_verify_not_available_in_sandbox as code. What happened: Lead Verify only runs on the live company registers, so it does not work with a sandbox key. Use a live key. Nothing was charged. What to do: Use a live key.

Lead Verify Invalid

HTTP 422, errorCode lead_verify_invalid. The MCP tool answers status rejected with the same sentence as error and lead_verify_invalid as code. What happened: The company_number cannot be checked: it is not a KVK or KBO number, or it belongs to the other country. Nothing was charged. What to do: Enter an 8-digit KVK number (NL) or a 10-digit KBO number (BE); put a VAT number in vat_number. Check that country matches the number.

Lead Verify Unavailable

HTTP 503, errorCode lead_verify_unavailable. The MCP tool answers status rejected with the same sentence as error and lead_verify_unavailable as code. What happened: The company register could not be reached. Nothing was charged. What to do: Try again in a few minutes.

Agent check errors

Agent Check Not Available

HTTP 404, errorCode agent_check_not_available. The MCP tool answers status rejected with the same sentence as error and agent_check_not_available as code. What happened: The agent check is not available yet. Nothing was charged. What to do: The agent check is switched off for now. Try again later.

Agent Check Not Available In Sandbox

HTTP 403, errorCode agent_check_not_available_in_sandbox. The MCP tool answers status rejected with the same sentence as error and agent_check_not_available_in_sandbox as code. What happened: The agent check only runs on live sources, so it does not work with a sandbox key. Use a live key. Nothing was charged. What to do: Use a live key.

Agent Check Unavailable

HTTP 503, errorCode agent_check_unavailable. The MCP tool answers status rejected with the same sentence as error and agent_check_unavailable as code. What happened: None of the wallet checks could be completed. Nothing was charged. What to do: Try again in a few minutes.

Cached result errors

Not Cached

HTTP 404, errorCode not_cached. What happened: No cached result for this entity; no data source was called. Nothing was charged. What to do: Send the request again with X-Response-Quality: fresh for a full check.

Error Handling Patterns

x402 Auto-Payment Handler

For AI agents that need to handle 402 responses automatically:

Debugging Checklist

  • Confirm the header name is exactly X-API-Key (capital X, capital A, capital K)
  • Confirm the key value starts with lg_live_ or lg_sandbox_ (lg_test_ keys are refused in production)
  • Check for leading/trailing whitespace in the header value
  • Verify the key has not been revoked: create a new one at POST /v1/keys/create
  • Check that country is exactly 2 uppercase characters: "NL" not "nl" or "Netherlands"
  • Check that entity_name is at least 2 characters
  • For kvk_number: digits only, exactly 8 characters, as a string: "12345678" not 12345678
  • For iban: strip all spaces before sending
  • The detail array in the response will list every failing field: read all of them before retrying
  • Run GET /v1/usage/summary with your key to see your current tier
  • Check the 403 causes above: sandbox keys get no entity reports, operator routes are not part of the customer API, and the watchlist needs a key-bound tenant
  • Confirm validBefore is at least 60 seconds in the future and within the quote’s maxTimeoutSeconds (600, ten minutes)
  • Confirm chainId in the payment payload exactly matches the network of the accepts entry you pay
  • Confirm recipient is that entry’s payTo: do not substitute your own address
  • Confirm amount matches or exceeds the amount the 402 quoted
  • Generate a new random nonce for every attempt: do not reuse
  • Confirm the USDC contract address is that entry’s asset (each network has its own)
  • 500 on entity checks is usually a transient timeout in a data source (e.g., KVK API slow response)
  • Retry up to 3 times with exponential backoff: 1s, 2s, 4s
  • If the error persists, try X-Response-Quality: cached to bypass live source queries
  • Include the Request ID from the error body when contacting support

Free Endpoints (Never Error on Auth)

These endpoints always return 200 and never require authentication or payment. They will not return 401, 402, or 403:

Further Reading

Rate Limits

Per-tier limits and burst handling

x402 Protocol

Full x402 implementation guide with EVM and Solana examples

Authentication

API keys, sandbox mode, and key management

Sandbox

Test all error scenarios for free