Skip to content

Quickstart

Getting started

Quickstart

Submit a settled x402 transfer, retrieve the fiscal record, and verify the receipt. HTTP is the public integration path.

Happy path

  1. REQUEST
  2. x402 payment (HTTP 402 + settle)
  3. SETTLED
  4. POST /settlements
  5. EU VAT determination
  6. UBL + ledger
  7. fiscal402.receipt

x402 payment happens first. Fiscal402 observes evidence afterward. It does not generate the 402, authorize the transfer, or control funds.

1. Ingest a settled transfer

Replace the placeholders. https://api.fiscal402.com is the operator origin. $FISCAL402_API_KEY is issued to the merchant. txHash must already exist on-chain.

http

POST https://api.fiscal402.com/settlements
Content-Type: application/json
X-Fiscal402-Key: $FISCAL402_API_KEY

{
  "amountUsdc": "1.00",
  "txHash": "0xYOUR_SETTLED_TX",
  "timestamp": "2026-09-10T12:00:00.000Z",
  "payerWallet": "0xPAYER",
  "receiverWallet": "0xPAY_TO",
  "network": "eip155:1",
  "asset": "USDC",
  "scheme": "exact",
  "consumerCountry": "DE"
}

shell

export FISCAL402_ORIGIN="https://api.fiscal402.com"
export FISCAL402_API_KEY="$FISCAL402_API_KEY"

curl -sS -X POST "$FISCAL402_ORIGIN/settlements" \
  -H "Content-Type: application/json" \
  -H "X-Fiscal402-Key: $FISCAL402_API_KEY" \
  -H "Idempotency-Key: demo-nl-de-1" \
  -d '{
    "amountUsdc": "1.00",
    "txHash": "0xYOUR_SETTLED_TX",
    "timestamp": "2026-09-10T12:00:00.000Z",
    "payerWallet": "0xPAYER",
    "receiverWallet": "0xPAY_TO",
    "network": "eip155:1",
    "asset": "USDC",
    "scheme": "exact",
    "consumerCountry": "DE"
  }'

2. Result

A successful ingest returns 201 with a public fiscal record. custody is always none. Production ids keep the x402- prefix.

201.json

{
  "id": "x402-4f9c1670",
  "custody": "none",
  "reviewStatus": "PROCESSED",
  "classification": {
    "regime": "OSS_B2C",
    "taxCategoryCode": "S",
    "ratePercent": 19,
    "taxingCountry": "DE"
  },
  "fx": {
    "pair": "USDC/EUR",
    "netEur": "0.86",
    "vatEur": "0.16"
  }
}

3. Receipt, UBL, JWKS

http

GET https://api.fiscal402.com/v1/receipts/rcpt_x402-4f9c1670
GET https://api.fiscal402.com/settlements/x402-4f9c1670/ubl
GET https://api.fiscal402.com/.well-known/jwks.json

4. Verify locally

  1. Confirm spec is fiscal402.receipt and spec_version is 1.0.0.
  2. Drop hashes and signature. Canonicalize the rest with fiscal402.sorted-json/1. SHA-256 the UTF-8 JSON. Compare to hashes.canonical_payload_sha256.
  3. Select the JWKS key whose kid matches signature.key_id.
  4. Verify Ed25519 over the hex digest string, not the raw 32-byte hash.
  5. SHA-256 the exact UBL UTF-8 bytes. Compare to artifacts.ubl_sha256.

verify-report.json

{
  "verified": true,
  "result": "VERIFIED",
  "receipt_schema": "SUPPORTED",
  "canonicalization": "fiscal402.sorted-json/1",
  "canonical_payload": "MATCH",
  "signing_key": "JWKS_MATCH",
  "signature": "VALID",
  "ubl_sha256": "MATCH",
  "settlement_reference": "PRESENT",
  "notes": [
    "verified means Fiscal402 receipt integrity, not tax-authority acceptance."
  ]
}

Optional sandbox classify

POST /v1/compliance/evaluate classifies without writing a production settlement. seller_country must be EU-27. Currency is USDC.

evaluate.http

POST https://api.fiscal402.com/v1/compliance/evaluate
Content-Type: application/json

{
  "seller_country": "NL",
  "buyer_country": "DE",
  "buyer_type": "B2C",
  "service_type": "DIGITAL_SERVICE",
  "amount": "1.00",
  "currency": "USDC",
  "chain": "eip155:1",
  "settled_at": "2026-09-10T12:00:00.000Z"
}