Typical public error envelope:
error.json
{
"error": {
"code": "CHAIN_VERIFY_FAILED",
"message": "tx_not_found",
"request_id": "req_…",
"retryable": false
}
}Some 401 responses still return a string error instead of the envelope. Treat missing/invalid X-Fiscal402-Key as AUTHENTICATION_FAILED.
HTTP and result codes
AUTHENTICATION_FAILED
The merchant key is missing or invalid.
- HTTP
- 401
- Retry
- no
- Cause
- No X-Fiscal402-Key header, or the value is not a merchant-scoped f402m_ key issued for this origin.
- Fix
- Send X-Fiscal402-Key from a server environment with FISCAL402_MERCHANT_KEY. Request a production pilot if you do not have a merchant key.
BAD_REQUEST
The JSON body is malformed or fails schema.
- HTTP
- 400
- Retry
- no
- Cause
- Invalid JSON, missing txHash, or amountUsdc is not a decimal string.
- Fix
- Compare the body to POST /settlements. Amounts are decimal strings, never floats.
- Docs
- /docs/api
NOT_FOUND
No settlement or receipt exists for that id.
- HTTP
- 404
- Retry
- no
- Cause
- Wrong id, or the event was never ingested.
- Fix
- Use the id from the 201 ingest response. Do not invent x402- prefixes.
- Docs
- /docs/api
IDEMPOTENCY_CONFLICT
The same Idempotency-Key was reused with a different body.
- HTTP
- 409
- Retry
- no
- Cause
- Retry with a mutated payload under a key that already succeeded.
- Fix
- Reuse the key only with the exact same body, or mint a new key for a new settlement.
UNSUPPORTED_ASSET
This asset cannot be valued on the production FX path.
- HTTP
- 422
- Retry
- no
- Cause
- Production FX is USDC → EUR at settled_at. Other assets fail closed.
- Fix
- Send USDC on eip155:1 or eip155:8453, or keep the event in manual review.
- Docs
- /docs/fx
UNSUPPORTED_JURISDICTION
No production engine exists for this corridor.
- HTTP
- 422
- Retry
- no
- Cause
- Production V1 is EU VAT. Non-EU sellers to attested EU customers are in that path. EU export and US/CA tax are not.
- Fix
- Check POST /v1/capabilities/check for the corridor before ingest. Do not treat this as 0% tax.
- Docs
- /docs/coverage
JURISDICTION_MANUAL_REVIEW
Facts are incomplete or ambiguous for an automatic determination.
- HTTP
- 422
- Retry
- no
- Cause
- Missing buyer country, unconfirmed VAT ID, or a corridor without a pinned ruleset.
- Fix
- This is not a failure of settlement. Complete attested buyer context and retry, or handle PENDING_MANUAL_REVIEW.
- Docs
- /docs/errors
AMBIGUOUS_JURISDICTION
More than one engine could apply and Fiscal402 will not guess.
- HTTP
- 409
- Retry
- no
- Cause
- Conflicting location evidence.
- Fix
- Send a single attested buyer country. Wallet, IP, and chain are not jurisdiction.
UNSUPPORTED_PAYMENT_ADAPTER
This payment evidence profile is not a production ingest adapter.
- HTTP
- 422
- Retry
- no
- Cause
- Production POST /settlements is x402 v2 exact.
- Fix
- Send x402 exact settlement evidence on POST /settlements. Do not invent another ingest path.
- Docs
- /docs/x402
CHAIN_VERIFY_FAILED
The on-chain USDC transfer check did not confirm the settlement.
- HTTP
- 422
- Retry
- yes
- Cause
- tx_not_found, mismatched payTo/amount, or RPC failure.
- Fix
- If retryable, wait and retry. If the hash is wrong, do not retry blindly.
SANDBOX_QUOTA
Evaluate/simulate quota exceeded.
- HTTP
- 429
- Retry
- yes
- Cause
- Too many POST /v1/compliance/evaluate calls.
- Fix
- Back off. Respect Retry-After if present. Production ingest is a different path.
- Docs
- /docs/api
PENDING_MANUAL_REVIEW
A fiscal event was recorded without an invented tax rate.
- Retry
- no
- Cause
- Buyer country missing, VIES unconfirmed, or corridor not automatically determined.
- Fix
- Treat as a result, not a 500. Persist the event id. Complete attested facts and resubmit if appropriate.
- Docs
- /docs/eu-vat
INSUFFICIENT_FISCAL_CONTEXT
The source client refused the call because attested buyer context is missing.
- Retry
- no
- Cause
- buyer.country was omitted. HTTP POST /settlements still accepts the body and may return PENDING_MANUAL_REVIEW.
- Fix
- Provide an attested buyer country. Wallet, IP, and chain are not jurisdiction.
Local verifier codes
SCHEMA_INVALID
The object is not fiscal402.receipt/1.0.0.
- Retry
- no
- Cause
- Wrong spec or spec_version.
- Fix
- Verify a receipt document, not a transaction hash.
UNKNOWN_KEY
JWKS does not contain signature.key_id.
- Retry
- no
- Cause
- Wrong JWKS, or a receipt from another issuer.
- Fix
- Fetch https://api.fiscal402.com/.well-known/jwks.json for production receipts.
SIGNATURE_INVALID
Ed25519 verification failed.
- Retry
- no
- Cause
- Tampered payload, wrong canonicalization, or corrupted signature value.
- Fix
- Canonicalize with fiscal402.sorted-json/1. Sign over the hex digest string, not raw bytes.
CANONICAL_HASH_MISMATCH
Recomputed payload hash does not match hashes.canonical_payload_sha256.
- Retry
- no
- Cause
- Reordered keys, dropped nulls, or edited fields after signing.
- Fix
- Do not pretty-print-and-restore. Drop hashes and signature, then canonicalize.
ARTIFACT_HASH_MISMATCH
SHA-256 of the UBL bytes does not match artifacts.ubl_sha256.
- Retry
- no
- Cause
- Re-serialized XML, encoding change, or a different invoice.
- Fix
- Hash the exact UTF-8 bytes Fiscal402 generated. There is no XML C14N.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| 401 | Key missing or in the browser | Server header X-Fiscal402-Key |
| Receipt does not verify | Pretty-printed JSON or wrong JWKS | Canonicalize; use production JWKS |
| Unknown kid | Example JWKS used on a live receipt | GET /.well-known/jwks.json |
| UBL hash mismatch | Re-serialized XML | Hash exact UTF-8 bytes |
| Manual review | buyer country missing | Attest consumerCountry |
| Duplicate settlement | Idempotency-Key reused with new body | Same key + same body, or new key |
| invalid PAYMENT-RESPONSE | success:false or missing tx | Do not ingest failed payments |