AttestPage · Docs · Pricing · OpenAPI · llms.txt

Errors

Last updated: 2026-10-10

Every error code the API can return, what it means and whether the call was charged. All errors share one JSON shape:

{ "error": { "code": "invalid_url", "message": "url: …. You were not charged.", "details": { "field": "url" } } }

code is stable and meant for programs; message is for people; details is optional (for example field or retry_after_ms). An answer with status 400 or above is never charged (with L402, the token is not spent and still works). The one exception is settle_failed: the payment may have gone through even though settling reported a failure. Resend the same request with the same payment id (the x402 payment-identifier extension): if the charge went through, you get the withheld result without paying again (marked payment-redelivered: true); if not, the payment is settled at most once. A charge that went through is also recorded for reconciliation. So a payment_already_used answer can follow a charged settle_failed; that call itself charged nothing.

StatusCodeMeaning
400bad_requestBody is not a JSON object, or a field has the wrong type.
400invalid_requestA field is missing or out of range (for example a quote over 1,000 characters), or both an x402 payment header and an L402 Authorization header or a credit key were sent (details.reason two_payment_headers).
400invalid_urlThe URL is malformed, too long, not http(s) or on another port; details.reason says which.
400blocked_targetThe URL points at a private, loopback or otherwise internal address.
402payment_requiredPay with x402: see the PAYMENT-REQUIRED header and Payments. Where L402 is on, the WWW-Authenticate: L402 header carries a macaroon and a Lightning invoice too. A free-trial call to verify/citations, verify/quotes, verify/document or check/links with more than 3 citations, quotes, pairs or URLs gets this too, with details.reason trial_too_large: pay for it, or send at most 3 per trial call.
402payment_invalidThe payment did not verify (details.reason says why). Sign a new one from the PAYMENT-REQUIRED header. For an L402 token the reason starts with l402_ (for example l402_wrong_route, l402_expired, l402_preimage_mismatch) and a fresh WWW-Authenticate offer is included. A resend for a withheld settle_failed result whose signature is not the payer's own gets this with details.reason invalid_exact_evm_payload_signature: resend the original signed payment, or a new one signed with the payer's key.
403robots_disallowedrobots.txt or our opt-out list disallows the page (or a redirect from it).
403payer_refusedThe paying address is on a sanctions list. For a credit key: a payment to it came from a listed address, so the key is blocked (details.reason credits_payer_refused).
404not_foundNo such route or sample, or (GET /v1/credits) no such credit key.
409payment_id_conflictThe payment id was already used for a different request.
409payment_already_usedThis payment signature was already spent, and this call did not charge again. Sign a new payment; the PAYMENT-REQUIRED header is included. If an earlier call with it ended in settle_failed, resend that request with its payment id to get the result. details.reason result_not_kept: that earlier call was charged but its result is no longer kept; the charge is recorded for reconciliation. For L402: the token already paid for another call (details.reason l402_spent); pay the fresh invoice in WWW-Authenticate.
409settle_pendingAn earlier call with this payment id ended in settle_failed, it is not charged on chain yet, and its payment could still go through. Resend the same signed payment now, or a new one after Retry-After (details.retry_after_ms).
409idempotency_conflictThe attest idempotency_key was already used with a different hash or note.
413body_too_largeBody over 64 KB (168 KB on receipt/verify and /mcp).
422host_not_foundThe URL's host name does not resolve (for check/links and verify/citations: none of the URLs resolves; for verify/document: none in the part).
422page_too_large_for_edgeEdge server only: the page is over the 64 KB it reads, or (check/packages) a registry answer is over the 256 KB it reads, with only the names over that size in details.too_large (no results for the others); details.full_service is the server to send the call to.
422edge_subrequest_limitEdge server only: the call needs more outbound requests than the edge allows (many hosts or redirects); use details.full_service.
422match_too_costlyFuzzy matching this quote would take too long; use "match": "exact" or a shorter quote. For verify/citations and verify/quotes this is an error on that citation or quote only and the call is charged; only when every one fails does the call get 422, with details.failed listing them. verify/document works the same way per part.
422no_pairsverify/document: no quote with a link was found in the document; details.skipped counts what was skipped and why. Never charged.
429rate_limitedToo many requests to that host or from your address, or (for check/packages) the crates.io queue of one lookup a second is full; see Retry-After. Where L402 is the only offer, also too many unpaid Lightning invoices (details.reason l402_invoice_cap). For verify/citations, verify/quotes and verify/document (one shared count), also too many calls from your address that failed uncharged (details.reason uncharged_failures).
429trial_exhaustedFree trial calls used up for the day; see Retry-After.
500internal_errorSomething failed on our side.
502registry_unavailablecheck/packages only: every registry lookup in the batch failed (details.reasons), so nothing was charged. Try again later.
502facilitator_unavailableThe payment facilitator could not be reached, so no payment was taken. Try again later.
502settle_failedThe work ran but the payment could not be settled, so the result is withheld. Resend the same request with the same payment id: if the charge went through on chain, you get the result without paying again; if not, the payment is settled at most once. If a charge went through, it is recorded for reconciliation. Redelivery runs on the full service only; on the edge server see Payments.
501not_on_edgeEdge server only: POST /v1/attest, POST /v1/verify/citations, POST /v1/verify/quotes and POST /v1/verify/document run on the full service (the free verify/document/preview works on the edge) (details.full_service). Also fetch and verify/quote when the page is a PDF (details.reason pdf, with details.final_url): only the full service reads PDFs. Never charged.
503pausedPaid routes are paused for maintenance.
503over_capacityverify/citations, verify/quotes and verify/document: too many batches are waiting to be matched (details.reason match_queue_full). fetch, verify/quote, verify/quotes and verify/citations: the page is a PDF and too many PDFs are waiting to be read (details.reason pdf_queue_full, with details.field). Retry after Retry-After. Never charged, even when it comes after your payment was verified.
503signing_unavailableSigning keys are not loaded.
503payments_unavailablePayments are not set up on this server, (with L402 only) no invoice could be made, or a new payment for a payment id whose earlier call ended in settle_failed came while the chain could not be read. Where credit keys are on, also: no credit address could be issued (the signet explorer is down, the server's addresses are used up, or too many issued addresses are still unpaid: details.reason credits_gap_full).
503sanctions_list_staleEdge server only: its built-in sanctions list is more than 8 days old, so it refuses payments until it is rebuilt (details.list_date, details.full_service). Never charged.
503payment_screening_unavailableThe payment check could not be completed (the chain read failed or timed out, or the sanctions list could not be read); retry after Retry-After and do not pay again. For a credit key that needs a new payment counted: details.reason credits_screening_unavailable.

L402 reasons

Where L402 is on, a token that is refused carries one of these in details.reason. None of them spends the token or charges anything.

ReasonCodeMeaning
l402_malformedpayment_invalidThe Authorization: L402 <macaroon>:<preimage> header or the macaroon cannot be read.
l402_bad_signaturepayment_invalidThe macaroon was not issued by this server, or was changed after it was issued.
l402_bad_versionpayment_invalidThe macaroon identifier has a version this server does not issue.
l402_unknown_caveatpayment_invalidThe macaroon has a caveat this server does not understand.
l402_missing_caveatpayment_invalidThe macaroon lacks its route, price or expires caveat.
l402_wrong_routepayment_invalidThe token was issued for a different route.
l402_price_mismatchpayment_invalidThe token's price is below this route's sats price.
l402_expiredpayment_invalidThe token's expires time has passed.
l402_preimage_mismatchpayment_invalidThe preimage does not hash to the invoice's payment hash (the invoice was not paid).
l402_spentpayment_already_usedThe token already paid for a different call.
l402_invoice_caprate_limitedNo new Lightning invoice: too many unpaid ones from your address (see Limits) (details.scope ip) or open on the server (global). Wait for Retry-After. When x402 can be offered, the answer is instead the usual 402 payment_required with the x402 offer, no L402 offer, this reason and Retry-After.
two_payment_headersinvalid_requestBoth an x402 payment header and an L402 Authorization header were sent.

Credit key reasons

Where prepaid credit keys are on (POST /v1/credits/order, then Authorization: Bearer qpc_… on a paid route; Bitcoin signet, full service only), a refusal carries one of these in details.reason. None of them takes sats from the key. Before a payment to a key's address is credited, every input address of that payment is checked against the OFAC sanctions list; a payment with an input that has no address (a coinbase or bare script) cannot be checked and is held (held_sats, status held), not credited.

ReasonCodeMeaning
credits_amountinvalid_requestPOST /v1/credits/order: sats is not a whole number from details.min_sats to details.max_sats.
credits_order_caprate_limitedToo many credit orders from your address in the last hour; pay a key you have, or wait for Retry-After (details.retry_after_ms).
credits_gap_fullpayments_unavailablePOST /v1/credits/order: too many credit addresses in a row are still waiting for payment, so no new one is issued until one is paid or expires unpaid (see Payments). Pay a key you already have, or try again later.
credits_no_keyinvalid_requestGET /v1/credits without Authorization: Bearer <credit key>.
credits_malformedpayment_invalid on a paid route, not_found on GET /v1/creditsThe qpc_ key is not 47 characters of base64url.
credits_unknown_keypayment_invalid on a paid route, not_found on GET /v1/creditsThis server never issued that key.
credits_insufficientpayment_requiredThe key has fewer confirmed, screened sats available than the route's price (details.price_sats); details also carries the key's address, status and balances. Pay the address again to top up.
credits_payer_refusedpayer_refusedA payment to the key's address came from an address on the sanctions list: the key is blocked for good and that payment is not credited.
credits_screening_unavailablepayment_screening_unavailableThe key has fewer sats than the price, and its address could not be read and screened now (the chain read failed or timed out, or the sanctions list cannot be read), so a new payment may not be counted yet. Do not pay again: retry after Retry-After (details.retry_after_ms). Sats already credited still work.
two_payment_headersinvalid_requestA credit key was sent with an x402 payment header.

Results that are not errors

A 404, 500, bot wall, timeout or dead link on the page you asked about is a result, not an error. It comes back with status 200, a content_kind such as http_error or bot_wall, and a receipt, and it is charged. See How it works.