x402 Payment Gateway
SDK source (GitHub): https://github.com/tangle-network/blueprint/tree/main/crates/x402 Crate README (GitHub): https://github.com/tangle-network/blueprint/blob/main/crates/x402/README.md Example blueprint (GitHub): https://github.com/tangle-network/blueprint/blob/main/examples/x402-blueprint/README.md
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)
Restricted Policy Example (Recommended Baseline)
Use default_invocation_mode = "disabled" and opt in job-by-job:
default_invocation_mode = "disabled"
[[job_policies]]
service_id = 1
job_index = 0
invocation_mode = "public_paid"
[[job_policies]]
service_id = 1
job_index = 1
invocation_mode = "restricted_paid"
auth_mode = "payer_is_caller"
tangle_rpc_url = "https://rpc.tangle.tools"
tangle_contract = "0xYourTangleContract"If the caller should be asserted independently of the settled payer, use:
auth_mode = "delegated_caller_signature"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.
Callable Surface vs Other Triggers
- x402 can invoke only jobs that are both priced and enabled by x402 job policy.
- Cron/on-chain/webhook producers remain separate trigger paths.
- A job handler can be reachable from multiple triggers only if you explicitly wire and expose it that way.
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.