This is a proposal for adding optional counterparty risk verification to the x402 payment protocol. The goal: any agent, any framework, any facilitator can verify counterparty trust before committing funds.
The problem
x402 defines a clean payment flow. An agent requests a resource, gets a 402 Payment Required response with payment details, signs a USDC transaction, and the facilitator verifies it. The resource is served.
What x402 does not define is whether the agent should pay at all. The protocol tells the agent how to pay. It does not tell the agent whether the counterparty is trustworthy.
Today, agents pay blindly. They see a 402 header, they pay. No verification, no risk assessment, no pause. This works when every x402 endpoint is operated by known, trusted parties. It breaks the moment the ecosystem opens up to unknown operators.
The proposal: risk_check_url
Add an optional risk_check_url field to the x402 discovery document (/.well-known/x402.json). This URL points to a risk scoring endpoint that agents can call before paying.
{
"version": 1,
"endpoints": ["/v1/score"],
"payment": {
"network": "eip155:8453",
"currency": "USDC",
"facilitator": "https://x402.org/facilitator"
},
"risk_check_url": "https://revettr.com/v1/score"
}
How it works
When an agent encounters a 402 Payment Required response:
- Agent extracts the payment recipient wallet address from the 402 header
- Agent extracts the service domain from the request URL
- Agent calls the
risk_check_url with the wallet address and domain
- The risk check endpoint returns a score (0 to 100), tier, and flags
- Agent decides whether to proceed based on its risk tolerance threshold
response = http.get("https://api.example.com/data")
if response.status == 402:
payment = parse_x402_header(response)
risk = http.post(risk_check_url, {
"wallet_address": payment.recipient,
"domain": "api.example.com"
})
if risk.score >= agent.min_trust_score:
sign_and_pay(payment)
else:
log(f"Declined: {risk.tier} risk, flags={risk.flags}")
skip()
Request format
The risk check endpoint accepts a JSON POST with any combination of counterparty identifiers:
POST /v1/score
Content-Type: application/json
{
"wallet_address": "0xabc...",
"domain": "api.example.com",
"ip": "104.18.28.72",
"company_name": "Example Corp"
}
More fields means higher confidence. At minimum, provide the wallet address (always available from the 402 header).
Response format
{
"score": 85,
"tier": "low",
"confidence": 0.6,
"flags": ["wallet_contract_active", "wallet_established"],
"signal_scores": {
"wallet": {"score": 85, "available": true},
"domain": {"score": 90, "available": true}
}
}
| Field | Type | Description |
score | int (0 to 100) | Composite risk score. Higher is safer. |
tier | string | low (80 to 100), medium (60 to 79), high (30 to 59), critical (0 to 29) |
confidence | float (0 to 1) | How many signal groups were available |
flags | string[] | Specific risk signals triggered |
signal_scores | object | Per-signal breakdown for transparency |
Discovery endpoint
Risk check providers expose a discovery endpoint at /.well-known/risk-check.json:
{
"name": "Revettr",
"version": "0.1.0",
"endpoint": "/v1/score",
"method": "POST",
"pricing": {
"amount": "0.01",
"currency": "USDC",
"protocol": "x402"
},
"signals": ["wallet", "domain", "ip", "sanctions", "erc8004"],
"chains_supported": ["base", "ethereum", "optimism", "arbitrum"],
"response_schema": "/docs#/ScoreResponse"
}
Design principles
- Optional, not mandatory. Agents choose whether to check. x402 services choose whether to recommend a risk check provider. No protocol changes required.
- Provider agnostic. Any endpoint that implements the request/response format qualifies. The ecosystem can have multiple risk check providers competing on signal quality.
- x402 native. The risk check itself can be paid via x402. No API keys, no subscriptions, no accounts. Agents pay per check with the same protocol they use for everything else.
- Fast. The check must complete in under 3 seconds. Agents should not wait minutes for a risk assessment. Real-time signals only.
Reference implementation
Revettr implements this pattern today:
from revettr import Revettr
client = Revettr()
score = client.score(
wallet_address="0xabc...",
domain="api.example.com"
)
if score["score"] >= 70:
proceed_with_payment()
else:
decline_transaction(reason=score["flags"])
Live at revettr.com/v1/score. $0.01 USDC per check via x402. Discovery at /.well-known/risk-check.json.
The x402 ecosystem is building the payment layer. This RFC proposes the trust layer that sits alongside it. We welcome other implementations.