Documentation Index
Fetch the complete documentation index at: https://developers.fireblocks.com/llms.txt
Use this file to discover all available pages before exploring further.
Open-source or hosted? This page describes the open-source facilitator that you run yourself. Fireblocks also offers a fully managed, fully secured hosted x402 Facilitator — production-grade security, operational support, monitoring, and a managed endpoint, with no infrastructure for you to run or upgrade. Talk to us about early access.
Integrating from your merchant server
Your server keeps serving its own traffic. You add middleware (Express, Next.js, Hono, or any equivalent — the same pattern as the Coinbase x402 SDK packages) that does two things:- On every request, inspect the incoming path. If the path is payment-gated and lacks a
payment-signatureheader, return 402 with a JSON body. Your middleware builds this from a product declared in your config. - On a request that carries a
payment-signatureheader, call this facilitator’sPOST /api/payments/verifyto check the signature, thenPOST /api/payments/settleto run the on-chain transaction. If both succeed, serve your resource.
POST /api/payments/settle takes the same body shape.
The facilitator never sees the end-user’s HTTP request. It only handles the cryptographic verification and the Fireblocks CONTRACT_CALL.
The payment processing API
These are the endpoints your merchant server (or any machine client) hits once you have given it an API key. All endpoints under/api/payments/* are authenticated with the merchant API key you minted via x402 keys create or POST /api/admin/tokens — except /api/payments/supported, which is public.
GET /api/payments/supported
Public discovery endpoint. Returns the schemes, networks, and extensions this facilitator accepts.
POST /api/payments/create
Returns a 402 PaymentRequired payload for a product without being gated behind a 402 flow. Useful for clients that want the quote before making the real request.
POST /api/payments/verify
Validates an EIP-712 signature off-chain without moving funds. Use this as a cheap pre-flight to confirm the signature is well-formed, the authorization covers the advertised price, and the payer signed the expected payload.
POST /api/payments/settle
Verifies the signature, then submits the on-chain transfer through Fireblocks. The request body matches /verify. The facilitator persists the Fireblocks transaction ID before polling for confirmation, so a process restart never loses track of an in-flight settlement.
When to settle
Your middleware controls the order:- Optimistic settlement — serve the response first, call
/settlein the background. Simpler, preferred when the resource is idempotent or cheap. - Settle-first — call
/settlesynchronously before serving. Safer for one-shot, expensive deliveries where a refund is not practical.
/api/payments/settle is a single atomic operation on the facilitator side. The choice of when to invoke it is a middleware concern, not a facilitator one.
Transfer mechanisms
Every asset registered on the facilitator declares atransfer_mechanism. The mechanism controls how signatures are validated and how the on-chain transfer is executed. A product can offer the same asset under multiple mechanisms; the facilitator emits one accepts[] entry per pricing row in the 402 response.
| Mechanism | Use it when |
|---|---|
eip-3009 | The token natively supports transferWithAuthorization() (notably USDC). Single transaction, no helper contract. The default for USDC. |
permit2 | You need a universal ERC-20 path that does not depend on the token implementing 3009. Settled through the Uniswap-deployed Permit2 contract via the x402ExactPermit2Proxy. |
upto-permit2 | The merchant needs to charge a variable amount within a client-signed ceiling — metered API calls billed at the end, for example. The facilitator picks the actual charge up to the signed maximum. |
erc7710 | The payer is a smart account (or an EOA upgraded via EIP-7702) authorizing through the MetaMask Delegation Framework. Settled with DelegationManager.redeemDelegations(). |
Picking a mechanism
- If you accept USDC and your customers hold standard USDC, choose
eip-3009. - If you accept other ERC-20s, or you want a single code path that works across tokens, choose
permit2. - If your billing model is metered or usage-based, choose
upto-permit2. - If your customers transact from smart accounts or want delegation-based authorization, choose
erc7710.
/verify and /settle. A client cannot upgrade from eip-3009 to permit2 by shipping a different payload shape — if the resolved mechanism is not in the product’s pricing[], the request returns 400 unsupported_scheme. Requests missing extra.productId (that is, requests not originated through /api/payments/create) are rejected.
Pricing modes
Each product has apricing[] table listing one entry per accepted asset. Each entry is one of:
- Native-denomination —
amountis set. The client is charged exactlyamountbase units of that asset, regardless of exchange rates. Useful when you bill in crypto directly. - USD-converted —
amountis null. The product’susd_price(fractional dollars) is converted to this asset at request time using aPriceProvider.
Mixing both on one product
A product can mix native and USD-converted entries in the samepricing[]:
Multiple transfer mechanisms on the same asset
Each pricing row accepts an optionaltransfer_mechanism override. When present, it takes precedence over the asset’s own transfer_mechanism — so a single asset can be offered under several mechanisms at once, and the 402 emits one accepts[] entry per row.
PriceProvider
The bundledPriceProvider stack is a CompositePriceProvider that tries in order:
StableOnlyPriceProvider— any asset markedstable: truequotes at 1:1 USD. No network call.CoinGeckoPriceProvider— queries CoinGecko/simple/priceusing the asset’sprice_symbol(for example,ethereum,weth,matic-network). 30-second in-memory cache; serves stale prices for up to 5 minutes if the live call fails. Pro-tier users can setCOINGECKO_API_KEY.
PriceProvider interface (src/services/pricing/PriceProvider.ts) and passing it into PricingService at startup.
Assets that cannot be priced at all (no stable flag, no price_symbol, live provider down) are dropped from the 402 response, not rejected — other accepted assets remain available to the client.
Gas cost — placeholder today
Ethereum mainnet settlement can cost 0.10” should not accept mainnet payments at $0.10, or they lose money to settlement gas. TheGasCostEstimator interface and NoopGasCostEstimator are wired into the pricing pipeline today but return 0 on every chain. When you are ready to enable chain-aware pricing, implement GasCostEstimator.estimate(chainId, mechanism) (using your RPC, Chainlink gas oracles, or Fireblocks fee estimates) and pick a GasCostPolicy:
ignore— the current default.add-to-quote— gross up the client’s charge so merchant revenue is constant.reject-if-above-pct— drop uneconomic chains fromaccepts[].
src/services/pricing/GasCostEstimator.ts in the repo for the interfaces.
What to read next
- Operating and production — the config file, auth model, management API, CLI reference, Payment Instruction Integrity, production deployment, and operator responsibilities.