x402 Payment Gateway
SDK source (GitHub): https://github.com/tangle-network/blueprint/tree/main/crates/x402
x402 is an optional, off-chain payment ingress path for job execution. It exposes HTTP endpoints that require a valid
x402 payment (typically stablecoins on an EVM chain) and then injects a JobCall into the Blueprint Runner after the
payment is verified and settled by an x402 facilitator.
This is useful when you want a service to accept payments from clients on EVM chains without requiring the client to submit on-chain Tangle transactions for each job.
How It Fits In the Runner
X402Gateway runs as a BackgroundService and X402Producer is the paired producer that converts verified payments
into JobCalls.
Quick start (from the crate docs):
Each x402-originated JobCall includes metadata for correlation and accounting:
X-X402-ORIGINandX-X402-QUOTE-DIGESTX-X402-PAYMENT-NETWORKandX-X402-PAYMENT-TOKENX-TANGLE-SERVICE-IDandX-TANGLE-CALL-ID(synthetic, for correlation)
Enabling It (Blueprint SDK)
If you are using blueprint-sdk, enable the feature flag:
[dependencies]
blueprint-sdk = { version = "*", features = ["x402"] }You can also depend on blueprint-x402 directly.
Configuration (TOML)
The operator configures:
- where the gateway listens (
bind_address) - which facilitator to use (
facilitator_url) - which tokens and chains are accepted (
accepted_tokens) - conversion rates from wei-denominated job prices into token amounts (
rate_per_native_unit, plus optionalmarkup_bps) - default x402 exposure policy (
default_invocation_mode) - per-job invocation and auth policies (
job_policies)
Job Pricing Input
The x402 gateway needs a per-job price map in wei:
- key:
(service_id, job_index) - value:
price_wei
This is the same shape as the pricing engine job pricing config, and it is intentionally explicit. If a job is not in
the map, the gateway returns 404 for that job.
Invocation and Authorization Model
x402 job exposure is explicit and policy-driven per (service_id, job_index).
Invocation modes:
disabled: job cannot be invoked via x402public_paid: payment-gated, otherwise publicrestricted_paid: payment-gated plus caller authorization and on-chain parity checks
Restricted auth modes:
payer_is_caller: settled payer is treated as callerdelegated_caller_signature: caller is asserted via signed headers
For restricted jobs, the gateway performs an on-chain parity check with:
isPermittedCaller(service_id, caller)viaeth_call
Delegated mode headers:
X-TANGLE-CALLERX-TANGLE-CALLER-SIGX-TANGLE-CALLER-NONCEX-TANGLE-CALLER-EXPIRY
Delegated signed payload format:
x402-authorize:{service_id}:{job_index}:{keccak(body)_hex_no_0x}:{nonce}:{expiry_unix_secs}HTTP Endpoints
The gateway exposes:
GET /x402/health: returnsok.GET /x402/stats: lightweight counters for accepted, denied, replay-denied, enqueue-failed, and dry-run outcomes.GET /x402/jobs/{service_id}/{job_index}/price: discovery endpoint that returns the wei price and settlement options (no payment required). Returns403 x402_disabledif job exists but is disabled for x402.POST /x402/jobs/{service_id}/{job_index}: paid job execution. The x402 middleware returns402with payment requirements if no valid payment is provided. After payment settles, the gateway returns202 Acceptedand injects aJobCallinto the runner.POST /x402/jobs/{service_id}/{job_index}/auth-dry-run: runs restricted auth +eth_callpolicy check without enqueueing work or settling payment.
Receipt and Replay Semantics
202 Acceptedmeans the paid request was accepted and enqueued, not that the job has completed.- In delegated restricted mode, duplicate nonce reuse in the same caller/job scope is rejected in paid flow with
409 signature_replay. auth-dry-runis non-mutating and does not consume delegated nonces.
Relationship to RFQ and the Pricing Engine
Tangle’s on-chain RFQ path is submitJobFromQuote. Separately, operators can expose x402 as an off-chain settlement
path.
The pricing engine proto includes optional x402 fields (settlement_options, x402_endpoint) in GetJobPriceResponse.
At time of writing, enabling those fields requires constructing PricingEngineService programmatically with
with_x402_settlement, since the pricing-engine-server binary does not expose x402 flags yet.
Operational Notes
- Keep
facilitator_urlpinned to a trusted HTTPS endpoint. - Keep conversion rates current. Stale
rate_per_native_unitvalues create user-facing price surprises. - Treat the HTTP body as untrusted input and validate it inside the job handler.
- For restricted jobs, pin
tangle_rpc_urlandtangle_contractto stable production infrastructure. - Use
auth-dry-runbefore enabling restricted jobs to verify caller policy parity and signature wiring.