HTTP already has a 402 Payment Required status code. It's been sitting there since 1999, unused, waiting. x402 finally puts it to work: a server returns 402, the client signs a USDC payment, retries with a payment header, and gets the resource.
No API keys. No subscriptions. No OAuth dance. Just money in, data out.
It is elegant because it collapses authentication and authorization into a single act: payment. If you can pay, you're in. The merchant doesn't care who you are. They care that you paid.
This works really well. Until it doesn't.
The Vending Machine Analogy
Think of x402 like a vending machine.
You walk up. You put in a coin. You get a Coke.
The machine doesn't ask your name. It doesn't check your ID. It doesn't need to know a single thing about you. The coin is the credential.
But here is where it gets interesting. What happens when the vending machine sells alcohol?
You can't just... put in more coins. You can't "pay harder."
The problem isn't financial; it's categorical. The machine needs to know something about you that money cannot communicate: Are you old enough?
This is not a contrived edge case. As AI agents begin transacting in the real world--buying compute, accessing regulated data, or operating across borders--the question shifts from "Can this agent pay?" to "Should this agent be allowed to?"
- Pharmaceutical APIs need to know you are in a legal jurisdiction.
- Financial services need to verify accreditation.
- Age-restricted marketplaces need proof you aren't a minor's agent acting unsupervised.
x402 has no answer for this.
The Naive Solution (And Why It Fails)
The obvious fix is: "Just add identity to the payment." Make agents register, get API keys, and attach credentials.
But this breaks exactly what makes x402 beautiful.
The whole point is that it is stateless and permissionless. The merchant shouldn't need to know you before you show up. There is no enrollment. No relationship. You pay, you're in. If we bolt on a traditional identity system, we have just rebuilt OAuth with extra steps.
So the engineering challenge becomes: Can you prove something about yourself without identifying yourself?
The Fix: Selective Disclosure
We solved this by introducing a layer of KYA (Know Your Agent) via selective disclosure.
When a merchant returns a 402 response, they can now include a `kyaRequirements` field alongside the payment terms.
{
"x402Version": 1,
"accepts": [
{
"scheme": "exact",
"network": "base",
"maxAmountRequired": "1800000"
}
],
"kyaRequirements": {
"require_age_over_21": true
}
}The agent holds an SD-JWT credential--a signed, selectively-disclosable token issued by a trust service. It contains many claims: age verification, jurisdiction, email, spending limits, and categories.
But here is the breakthrough: The agent only reveals the claims the merchant asked for.
If a wine merchant asks for age verification, the agent discloses `age_over_21: true`. The merchant sees exactly one fact: this agent is authorized to purchase age-restricted goods. The credential travels alongside the payment header. One request. Two proofs: "I can pay" and "I'm allowed to."
No Phone-Home (The "Turtles" Problem)
We were obsessive about one constraint: no central dependencies.
The merchant verifies the credential entirely locally. There is no API call to the issuer and no central verification service.
They fetch two public, cacheable, W3C-standard documents: a DID document (`did:web`) with the issuer's public key, and a bitstring status list for lightweight revocation checks. Both are static. Both are cacheable. If the issuer goes offline, verification still works from the cache. The issuer never learns when or where a credential is used. The identity layer is as stateless as the payment layer.
This matters because the alternative--merchant calls issuer to verify every transaction--creates a circular dependency. You'd need the identity service to be paid (via x402?) to verify a payment. It's turtles all the way down.
The New Vending Machine
The flow is no longer just "pay to enter." It allows for a natural browsing experience that seamlessly upgrades to a transaction when needed.
1. The Open Door (Browsing)
Agent -> Merchant: GET /api/wine
Merchant -> Agent: 200 OK. Here is the catalog. Browse freely.
2. The Challenge (Attempting to Buy)
Agent -> Merchant: POST /api/wine/purchase
{ items: [{ id: 3, quantity: 1 }] }
Merchant -> Agent: 402 Payment Required.
Error: Payment required.
Cost is $1.80 USDC on Base.
Requirement: Prove you are 21+.
3. The Human Check (Authorization)
Agent -> User: "Purchase request: $1.80 USDC on Base. Merchant also requires Age Verification (21+). Proceed?"
User -> Agent: "Yes."
4. The Settlement (Execution)
Agent -> Merchant: Retries POST with [Payment Signature] + [Age_Over_21 Credential]
Merchant: Verifies payment OK. Verifies age credential OK.
Merchant -> Agent: 200 OK. Order confirmed. Transaction ID: fc8f99d3...Identity as Delegation: The AgnicPay Approach
In AgnicPay, we give your agent both capabilities:
- A wallet--so it can pay any x402-based service, on any supported chain, without you signing every transaction.
- An identity--so it can prove things about you without being you.
We combined them because here is the tension: "Acting on your behalf" is a dangerous phrase. You don't want your agent revealing your full identity to every API it hits. You want it to carry just enough authority, scoped to exactly what it needs.
So the credential your agent carries isn't a copy of your identity. It's a delegation. It is scoped, revocable, and selectively disclosable. When the wine merchant asks for age, the agent reveals: "My owner is over 21." Nothing else. One fact. Cryptographically signed. Verifiable without calling anyone.
Every merchant gets the minimum slice of identity needed for that specific transaction. The rest stays cryptographically absent from what the merchant receives. And the owner stays in control. Revoke the credential, and the agent goes back to being a wallet with no name.
