Concordium testnet · x402

x402 facilitator for Concordium

An independent facilitator for x402's exact scheme on Concordium, the one @x402/concordium clients use. The buyer signs a transfer of CCD or a protocol-level token (PLT, e.g. EURR) to the seller and names this facilitator as fee payer (sponsor). The facilitator checks it, co-signs as sponsor, pays the fee and submits it. The buyer pays no fees, and the facilitator never holds anyone's funds.

Status
Live
Network
Concordium testnet
Payments sponsored
30
Today
0 / 50 a day

Latest payments

Read from the chain: every transfer this facilitator's account sponsored. The buyer paid no fee; the fee column is what the sponsor paid (Concordium testnet CCD).

UTCAmountToFeeTransaction
2026-11-13 18:010.001 CCD3HFbRLEG…Qae9v34.374573a9f146e2…f96334
2026-11-13 18:010.001 CCD3HFbRLEG…Qae9v34.3745737d0a19a2…71198e
2026-11-12 18:340.001 CCD3HFbRLEG…Qae9v34.4653446bb79860…d8c1c9
2026-11-12 18:340.001 CCD3HFbRLEG…Qae9v34.4653448ef521f8…01aba4
2026-11-11 18:020.001 CCD3HFbRLEG…Qae9v34.37332589ee22bb…964997
2026-11-11 18:020.001 CCD3HFbRLEG…Qae9v34.37332582445803…adf59b
2026-11-11 16:290.01 CCD3p4koFZ4…RSnTWi4.39944744e3f3c…000e08
2026-11-11 16:280.01 CCD3p4koFZ4…RSnTWi4.399441344dc6c…7d2bc7
2026-11-10 18:120.001 CCD3HFbRLEG…Qae9v34.667126e4cb2af3…8577d5
2026-11-10 18:120.001 CCD3HFbRLEG…Qae9v34.667126fc867da9…36b0d5

First payment settled 6 Nov 2026: 1b2edc98…254c98 (0.001 CCD, buyer fee 0).

How a payment works

  1. The seller's API answers 402 with a Concordium option that names this facilitator in extra.feePayer.
  2. The buyer signs a sponsored transfer (account transaction v1) of exactly that amount to the seller and sends it in the PAYMENT-SIGNATURE header.
  3. The seller posts it to /verify, then /settle: this facilitator checks amount, payee, signature, nonce, expiry and balance, co-signs as sponsor, submits it and waits until it is final.

Who you pay: checked with Concordium

Every Concordium account is opened from an identity a regulated identity provider verified. Before sponsoring a payment this facilitator reads the seller's own credential (which provider, valid until when) and, when the seller's endpoint shows a Concordium badge in its Agent Card, checks its agent in Concordium's Agent Registry: active, its anchored card unchanged, this endpoint listed, and the payTo its registered agent wallet. The answer rides along in every /verify and /settle response as extensions["concordium-identity"]: verified-agent, identity-backed, expired or not-read.

A zero-knowledge proof about the person behind the payTo. A seller's owner can prove, from their own Concordium wallet, facts such as 18 or older or lives in the EU without revealing them (make one), tied to the payTo and the site, and serve it at /.well-known/concordium-proof.json. This facilitator verifies it against the chain with its own node, checks that it came from the payTo account's own credential, and reports the proven facts as proof; nothing else about the person is known to it.

This instance reports it; set IDENTITY=agent to sponsor only verified agents, or IDENTITY=proof to sponsor only sellers with a verified proof. Check a seller before going live: GET /identity?url=<paid endpoint>&payTo=<account>.

Try it: /demo/paid is a demo seller on testnet, paid at the wallet of agent #993 in Concordium's Agent Registry, whose Agent Card is pinned on chain, and whose owner proved they are an adult living in the EU. It answers 402; pay it with any x402 client for Concordium and the answer shows what this facilitator found about the seller.

Who pays: the buyer's proof

It works the other way round too. A seller that may only sell to adults, or only to people living in the EU, adds "buyerProof": ["adult"] to its 402's extra. The paying agent's owner proves it once from their own Concordium wallet (make one), tied to the account the agent pays from, and the agent sends that file with its payments as extensions["concordium-buyer-proof"]. Before sponsoring, this facilitator verifies it against the chain, checks that it came from the paying account's own credential and shows what the seller asked; otherwise it refuses (buyer_proof_required or buyer_proof_invalid) and nothing is signed. The seller learns that the fact holds, and nothing else about the buyer.

Try it: /demo/adult is the demo seller for adults only.

What did my agent pay?

Every payment this facilitator sponsors is a transfer the agent's own account signed, so it is on chain for good. GET /statement?account=<the account your agent pays from> lists them: when, to whom, how much (with totals per asset), and for each payee what Concordium says about it now (an identity-backed account, its identity provider, an expired credential). Read from the chain, it needs no log of ours and holds after restarts. Example: the demo buyer's statement.

For sellers: the 402 option

Add this to accepts[] (here 0.01 CCD; amounts are in the smallest unit, 6 decimals for CCD):

{
  "scheme": "exact",
  "network": "ccd:4221332d34e1694168c2a0c0b3fd0f27",
  "amount": "10000",
  "asset": "CCD",
  "payTo": "<your Concordium account>",
  "maxTimeoutSeconds": 120,
  "extra": {
    "feePayer": "4nkWEqH5534jL4LkSQAuL6zZdZugaU171DXqVvWB7uHbecuYS6"
  }
}

For a PLT, set its token id (the decimals are read from the chain):

{
  "asset": "EURR",
  "amount": "10000",
  "extra": {
    "feePayer": "4nkWEqH5534jL4LkSQAuL6zZdZugaU171DXqVvWB7uHbecuYS6"
  }
}

Then use https://ccd-facilitator.fizzl.eu as your facilitator URL.

Routes

GET /supportedthe scheme, network and sponsor account
POST /verify{ paymentPayload, paymentRequirements } → { isValid, payer } or invalidReason
POST /settlesame body → { success, transaction, network, payer } once final on chain
GET /identity?url=&payTo=: what Concordium says about a seller (credential, registered agent, zero-knowledge proof)
GET /paymentsthe sponsored payments, read from the chain
GET /statement?account=: what one agent paid through this facilitator, to whom, and who those payees are
GET /healthlive state as JSON

Spec and code

The scheme: scheme_exact_concordium.md in the x402 repository. On top of its checks this facilitator also caps the energy at what the transfer needs, checks a PLT's pause and allow/deny lists before sponsoring, and has a seller allow-list and a daily limit (SPEC.md). Code (MIT), tests and a buyer-side helper: github.com/Fizzl13/x402-examples. Built on Concordium's sponsored transactions (protocol 10) with @concordium/web-sdk.