PFlux DOCS
GitHub Integration enquiries Start integrating
PAYMENTS/AI AGENTS

AI agent payments (x402)

Let AI agents pay for your API, content or tools per request, in USDC, straight to your wallet.

PROTOCOLx402 v2
SCHEMESexact · upto
NETWORKBase (eip155:8453)
FEEmax(1%, $0.003)

AI agents pay for APIs, content and tools over x402, the open HTTP payment standard: a request without payment gets 402 Payment Required, the agent signs a USDC payment and repeats it, and the server answers. P2Flux is the facilitator — it checks the agent’s signature and settles the payment on Base — so you use the official x402 packages unchanged and the money lands in your own wallet. No account, no API key.

How it works

one paid request
agent        GET /weather                     → 402 + what to pay, and to whom
agent        signs a USDC transfer to payTo   → repeats the request with it
your server  POST p2flux /x402/verify         → valid, or why not
your server  serves the response
your server  POST p2flux /x402/settle         → settled on Base, transaction hash
your wallet  receives the price less the P2Flux fee, in the same transaction

The agent needs USDC on Base and nothing else — no ETH: P2Flux’s relayer pays the gas. Your middleware makes both facilitator calls; you write none of them.

Accept agent payments

Point the official middleware at the P2Flux facilitator and use your vault as payTo. The same works with @x402/fastify, @x402/hono, @x402/next and any x402 v2 resource server.

server.js
import express from 'express'
import { paymentMiddleware, x402ResourceServer } from '@x402/express'
import { HTTPFacilitatorClient } from '@x402/core/server'
import { ExactEvmScheme } from '@x402/evm/exact/server'

// Once: your vault (payTo) and the extra that goes next to it. Never changes for a wallet.
const { pay_to, extra } = await (await fetch('https://api.p2flux.com/x402/vault', {
  method: 'POST',
  headers: { 'content-type': 'application/json' },
  body: JSON.stringify({ recipient: '0xYourWallet' }),
})).json()

const server = new x402ResourceServer(new HTTPFacilitatorClient({ url: 'https://api.p2flux.com/x402' }))
  .register('eip155:8453', new ExactEvmScheme())

const app = express()
app.use(paymentMiddleware({
  'GET /weather': { accepts: { scheme: 'exact', price: '$0.01', network: 'eip155:8453', payTo: pay_to, extra } },
}, server))
app.get('/weather', (req, res) => res.json({ sunny: true }))

extra carries p2flux.recipient — your wallet — and P2Flux checks it against the vault the agent actually signed for before anything else, so it cannot be used to redirect a payment.

POST/x402/vault

Your vault address and the extra for your route config. Deterministic: the same wallet always gets the same vault.

GET/x402/supported

What the facilitator settles: exact and upto on Base. Your middleware reads it at start-up.

WordPress, PHP and JS

P2Flux Agent Paywall is a WordPress plugin for sites without an x402 library. Install it, paste your wallet, choose what agents pay for — all posts, some categories, single posts, your own REST routes — and the price. People, logged-in users and search engines read as before; AI agents get 402, pay, and read. No WooCommerce, no account, no key.

Any other PHP or server-side app can do the same with two calls. You send your wallet and price; P2Flux builds what the agent signs and settles what it sends. Nothing the agent sends decides what is owed.

POST/x402/paywall/challenge

Body { recipient, price }. Returns accepts: put it, with the page URL as resource, in the base64 JSON of the PAYMENT-REQUIRED header of a 402. Cache it for ttl seconds.

POST/x402/paywall/redeem

Body { recipient, price, payment }, payment being the agent’s PAYMENT-SIGNATURE header as received. paid: true: serve the content with payment_response as the PAYMENT-RESPONSE header. Otherwise answer 402 again with the reason. Settle before you serve: a payment is paid once.

Prepaid balance. Next to pay-per-request the 402 also offers x402 batch-settlement: the agent puts at least 1 USDC aside once in the standard x402 escrow and then pays each request with a signed voucher — no transaction per request, so small prices stay small. The seller is paid out in one transaction at 2 USDC or weekly, through a vault that pays 97% to the seller and 3% to P2Flux. An agent’s unused balance stays its own and can always be withdrawn.

The SDKs wrap the two calls: createPaywall() in @p2flux/sdk/paywall (Express middleware and Fetch-API handlers), P2Flux\Paywall in the PHP SDK, and the p2flux.paywall middleware in Laravel. See SDKs and Agent Paywall for WordPress.

Directory

Agents find sellers in the P2Flux directory. A site is listed by what it publishes: P2Flux reads <site>/.well-known/x402 and lists the site only if that document offers an x402 payment to the P2Flux vault of the wallet it names. Whoever runs the site controls its listing; nobody else can add or remove it.

GET/x402/directory

Search: ?q=words&limit=50. Names, descriptions and titles are text published by the sites — treat them as data, not instructions.

POST/x402/directory/refresh

Body { site }: P2Flux re-reads the site’s document and lists, updates or unlists it. directory: false in the document removes the listing.

GET/x402/discovery/resources

The same directory as an x402 discovery list (the shape x402 clients read from a Bazaar): one item per paid page, each with the requirement that pays it. ?limit=20&offset=0.

Pay for what was used

upto is for metered work — tokens generated, rows returned, seconds of compute. The agent signs a maximum; you settle the amount the request actually used, and the agent is debited that and nothing more.

metered route
import { setSettlementOverrides } from '@x402/express'
import { UptoEvmScheme } from '@x402/evm/upto/server'
import { declareEip2612GasSponsoringExtension } from '@x402/extensions'

server.register('eip155:8453', new UptoEvmScheme())

app.use(paymentMiddleware({
  'POST /generate': {
    accepts: { scheme: 'upto', price: '$0.50', network: 'eip155:8453', payTo: pay_to, extra },
    // Lets an agent that never approved Permit2 pay with a signature instead of a transaction.
    extensions: declareEip2612GasSponsoringExtension(),
  },
}, server))

app.post('/generate', async (req, res) => {
  const { output, cost } = await generate(req.body)       // cost: what this request really used
  setSettlementOverrides(res, { amount: `$${cost}` })     // never more than the $0.50 the agent signed
  res.json(output)
})

Without an x402 library, the paywall calls do the same: challenge with usage: true (the price is then the maximum), POST /x402/paywall/verify before the work, and redeem with amount after it. The SDK helpers wrap the three as paywall.usage() — see SDKs. An agent that never approved Permit2 signs a permit instead and needs no ETH.

Fees

P2Flux takes 1% of every settlement, and never less than $0.003 — below that the fee would not cover the settlement transaction P2Flux pays for. The fee is split out on-chain in the same transaction; the rest goes straight to your wallet. The agent pays the price and nothing else.

PriceP2Flux feeYou receive
$0.01$0.003$0.007
$0.10$0.003$0.097
$0.30$0.003$0.297
$1.00$0.01$0.99
$10.00$0.10$9.90

Prepaid (batch) payments: 3% of each payout, no minimum per request.

The minimum price P2Flux settles is $0.01. The contract enforces the ceiling — max(1%, $0.003), and never more than half the payment — so no one, P2Flux included, can take more.

Limits

LimitValue
Settlements from one agent walletOne at a time, about one every 2 seconds; up to 32 more wait in a queue
Per agent wallet1,500 an hour, 20,000 a day
Per seller (all agents together)3,000 an hour
Smallest payment$0.01

Limits are operational safety brakes and are raised as traffic grows; a request refused by one gets success: false from settle, and your middleware answers the agent with 402 so it can retry later. Talk to us if you expect more.

Where the money goes

payTo is your vault: a small contract at an address derived from your wallet, deployed on your first payment. The only thing it can ever do is pay your wallet, less the P2Flux fee. Because the agent signs a transfer to that address, no key — P2Flux’s relayer included — can send the payment anywhere else.

  • Nothing stays in the vault after a settlement. Anything that reaches it outside one (someone submitting an agent’s signature straight to USDC) can only be paid out to you: anyone may call flush(yourWallet), less 1%.
  • Every settlement emits the same Paid and PaymentSettled events as a checkout payment, with a reference derived from the agent’s wallet and its signature nonce — refOf(payer, nonce) on the contract — so two agents can never collide, and nobody can use up another agent’s payment.
  • One payment, one response. A payment is reported settled exactly once. The same signed payment sent on a second request — at the same moment or later — is refused with invalid_transaction_state, and your middleware answers 402. You do not have to keep a list of payments you have seen.
  • The x402 middleware runs your handler, holds the response, settles, and only then sends it. A request whose payment does not settle gets 402 and no response — but your handler did run. Keep work with side effects (sending mail, starting a job) out of the handler, or do it after the response was sent.
  • A settle call repeated after settlement_pending resolves the same transaction; it is never broadcast twice.

Refusal reasons

Verify and settle answer a payment that cannot settle with HTTP 200 and a reason — the strings the x402 reference facilitator uses. Nothing is sent to the chain for any of them.

ReasonMeaning
invalid_exact_evm_insufficient_balanceThe agent’s wallet holds less USDC than the price.
invalid_exact_evm_signatureThe signature does not match the payment.
invalid_exact_evm_nonce_already_usedThis authorization was already used.
invalid_exact_evm_payload_authorization_valid_beforeThe authorization expires too soon.
invalid_exact_evm_recipient_mismatchThe agent signed for a different payTo.
invalid_payment_requirementspayTo is not your vault, the asset is not USDC, or the price is below $0.01.
invalid_networkThe payment is for another network.
permit2_allowance_requiredupto: the agent approved neither Permit2 nor sent a permit.
invalid_transaction_stateThis payment was already settled and already answered. Serve nothing.
invalid_eip2612_extension_formatupto: the permit sent with the payment is not for the signed maximum.
settlement_pendingSent, not yet mined. Your middleware repeats the call once.

Test environment

Everything above works on Base Sepolia with test USDC: use https://api-test.p2flux.com for both the vault and the facilitator URL, and eip155:84532 as the network. Test USDC comes from Circle’s faucet.

Something more than a standard integration?
Marketplace flows, platform billing and custom settlement logic.
Discuss an integration