Skip to main content
This walkthrough takes an existing hosted payment agent to a paid x402 request. It assumes an active hosted agent (see the Agentic Payments quickstart) and an API key.
Beta. x402 is in early access. Run this walkthrough against the sandbox on Base Sepolia.

1. Enable x402 on the agent

This creates the agent’s x402 wallet, the one wallet it pays x402 from.
The call is idempotent: calling it again returns the same wallet. If it stopped part-way, status is provisioning and calling it again completes it. GET /payment-agents/{id}/x402 returns the same object. A frozen customer cannot enable x402.

2. Fund the wallet

Send USDC to address on the network the agent will pay on. For the sandbox, that’s USDC on Base Sepolia (0x036CbD53842c5426634e7929541eC2318f3dCF7e). The wallet only ever needs USDC. Payments are signed authorizations that the seller’s facilitator submits and pays gas for, so the wallet never needs ETH.

3. Set a budget

Create an x402 mandate. This one lets the agent pay up to $0.50 per call and $2.00 per hour in total, only for APIs under *.marketpulse.example:
Amounts are atomic units. USDC has 6 decimals, so "500000" is $0.50.

4. Pay the 402

Call the seller. An unpaid request comes back as 402 Payment Required with the seller’s terms:
  • x402 v1 sellers put the terms in the JSON body: {"x402Version": 1, "accepts": [ ... ]}.
  • x402 v2 sellers put them, base64-encoded, in the PAYMENT-REQUIRED response header.
Pick one entry from accepts and forward it verbatim as payment_requirements. Pass the seller’s x402Version as x402_version, and the URL you’re paying for as resource_url:
Retry the seller’s request with the header named by payment_header_name, set to payment_header:
The two protocol versions differ only in packaging. The signature underneath is the same: Either network spelling is accepted, and a mandate covers the seller in both.
Treat payment_header like cash. Anyone holding it can settle the payment until valid_before. Send it only to the seller whose 402 you forwarded, and don’t log it.

Retrying safely

Every POST takes X-Idempotency-Key, and on the signing endpoint it does real work: one key mints at most one payment authorization. Reuse the same key and you get the same authorization back — same nonce, same window — signed again, and it is charged against the budget once. So a request that times out is safe to retry under the same key, and only one of the two can ever settle. Reuse a key for a different payment and the call is refused with 409 and nothing is signed: That last row is the one to handle deliberately: a settled payment is never re-signed, because its nonce is spent and a re-signed header would be refused by the seller’s facilitator. Reading that refusal as a failure and retrying with a fresh key would pay the seller twice.

When the budget says no

A payment the mandate won’t cover returns 403 with the reason, and nothing is signed. For example:
Budgets & holds lists every refusal.

5. Watch the payment settle

Every signature has a hold. It starts outstanding. Once the seller’s facilitator settles it on-chain, Dakota sees the transfer and marks it settled with the transaction hash:
Both x402 lists page the same way as the rest of the API: limit, starting_after and ending_before, newest first, with meta telling you whether there is more in either direction. A signature the seller never used is released a few minutes after its valid_before, and its amount returns to the budget.