BuildBlueprint Runnerx402 Payments

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-ORIGIN and X-X402-QUOTE-DIGEST
  • X-X402-PAYMENT-NETWORK and X-X402-PAYMENT-TOKEN
  • X-TANGLE-SERVICE-ID and X-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 optional markup_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 x402
  • public_paid: payment-gated, otherwise public
  • restricted_paid: payment-gated plus caller authorization and on-chain parity checks

Restricted auth modes:

  • payer_is_caller: settled payer is treated as caller
  • delegated_caller_signature: caller is asserted via signed headers

For restricted jobs, the gateway performs an on-chain parity check with:

  • isPermittedCaller(service_id, caller) via eth_call

Delegated mode headers:

  • X-TANGLE-CALLER
  • X-TANGLE-CALLER-SIG
  • X-TANGLE-CALLER-NONCE
  • X-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: returns ok.
  • 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). Returns 403 x402_disabled if job exists but is disabled for x402.
  • POST /x402/jobs/{service_id}/{job_index}: paid job execution. The x402 middleware returns 402 with payment requirements if no valid payment is provided. After payment settles, the gateway returns 202 Accepted and injects a JobCall into the runner.
  • POST /x402/jobs/{service_id}/{job_index}/auth-dry-run: runs restricted auth + eth_call policy check without enqueueing work or settling payment.

Receipt and Replay Semantics

  • 202 Accepted means 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-run is 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_url pinned to a trusted HTTPS endpoint.
  • Keep conversion rates current. Stale rate_per_native_unit values 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_url and tangle_contract to stable production infrastructure.
  • Use auth-dry-run before enabling restricted jobs to verify caller policy parity and signature wiring.