Skip to main content
What ships today. Bindu’s payment layer is the x402 protocol — a stablecoin paywall over HTTP 402, originally from Coinbase, formalized as an A2A extension. The W3C Payment Request shapes (PaymentMandate, IntentMandate, CartMandate, etc.) sometimes referenced in AP2 drafts are not implemented in this codebase. If you find references to them anywhere in Bindu, treat those references as spec sketches rather than runtime types.
x402 lets a server respond with HTTP 402 plus a structured paymentRequirements payload, the client signs an EIP-3009 transfer-with-authorization, and the server forwards the signed payload to a facilitator that verifies signature + balance + replay. Settlement happens on-chain when the task completes. Concretely, in Bindu:
  • Default network: base-sepolia (Base Sepolia testnet)
  • Default token: USDC
  • Default facilitator: https://x402.org/facilitator (Coinbase-hosted)
  • Default protected method: JSON-RPC message/send
  • Extension URI: https://github.com/google-a2a/a2a-x402/v0.1
All of this is configurable via X402Settings.

Declaring payment on an agent

Add an execution_cost block to your agent config. Source: examples/beginner/agno_paywall_example.py:
What each field means — see X402AgentExtension.__init__: You can also offer multiple payment options:

The request/response flow

This is implemented in bindu/server/middleware/x402/x402_middleware.py. The order — claim nonce before facilitator verify — is deliberate: replays cost zero facilitator round-trips, and we never rely on the on-chain contract to reject replays.

Headers

X-A2A-Extensions (activation)

Clients that want x402 to engage echo the extension URI on their request:
The server confirms activation by echoing the same header on the response. Helper: X402ActivationHandler.

X-PAYMENT (the signed payload)

The serialized x402 PaymentPayload, base64-encoded:
The decoded payload is a JSON object the x402 SDK parses via parse_payment_payload. v1 payloads are explicitly rejected — only v2 (signed EIP-3009) is accepted.
x402 introduces task states beyond standard A2A. From X402Settings: These are written to Task.metadata under well-known keys (settings.py:384-388):
Helpers in bindu/extensions/x402/utils.py build these dicts:
A completed task ends up with metadata roughly like:
(The exact receipt shape comes from the facilitator response.)

402 response shape (what your client gets)

When payment is missing or invalid, the middleware returns HTTP 402 with a JSON body the x402 SDK can consume. The minimal contract:
The accepts array contains every PaymentRequirements your agent published — one per entry in payment_options (or one synthesized from the single amount/token/network).

Configuring the facilitator and networks

The Coinbase default (https://x402.org/facilitator) supports Base mainnet and Base Sepolia out of the box. For other EVM networks the SDK doesn’t know about, add an entry to X402Settings.extra_networks:
The facilitator must also know the network. The Coinbase default does not support SKALE today — point facilitator_url at one that does (e.g. https://facilitator.x402.fi). All knobs are environment-driven (X402__FACILITATOR_URL, X402__DEFAULT_NETWORK, …) — see the env_prefix="X402__" on X402Settings.

What’s not in this implementation

So you know where the boundaries are:
  • No PaymentRequest / PaymentResponse / PaymentMandate / IntentMandate / CartMandate types — those AP2 shapes don’t exist as Python types in this repo. If you’ve seen them in older Bindu docs, they were spec sketches.
  • No multi-currency fiat support — payments are stablecoin transfers on EVM chains via x402.
  • No subscription model — every protected call is a one-shot payment authorization. Long-running tasks bind one payment to one task ID; renewals are not handled by the protocol.
  • Settlement currently happens at task completion. There is no partial-credit / metered billing within a single task.
If you need one of these and want to discuss adding it, open an issue.