The one-sentence pitch
An AI agent, wallet app, or browser extension sends us any URL. We return a scam verdict plus 23 threat signals. Every request costs $0.001 USDC, paid onchain on Solana or Base. No signup, no API keys, no sales call. That is the entire product.
The interesting part is not the detection engine. The interesting part is what happens when an HTTP API quietly becomes a standalone onchain business. x402 is the primitive that makes that possible, and the rest of this post explains it.
What x402 actually is
HTTP 402 has been reserved as Payment Required since the original HTTP/1.1 specification in 1999. For twenty-six years it sat there, waiting for a payment protocol the internet actually wanted to adopt. In 2025, Coinbase published a concrete shape that finally makes it usable, and x402 is the result.
The idea is simple. A client calls any HTTP endpoint. If the server needs payment, it responds with status 402 and a JSON body describing the accepted payment options: chains, tokens, amounts, receiver addresses, and a server-issued nonce. The client pays onchain, retries the same request with a signature header proving the payment happened, and the server verifies + serves the real response.
That single pattern replaces an entire stack of developer-experience boilerplate: signup forms, billing portals, usage dashboards, rate-limit tiers, API key rotation, and dunning emails. One endpoint, one price, one onchain settlement. The credit card flow, but for machines.
Two observations from building this:
- Latency is fine. Solana settles in ~400ms, Base in ~2 seconds for a USDC transfer. The overall request takes 1โ3 seconds including server verification. That is slower than a normal API call but faster than any signup flow, and agents do not blink at a few seconds.
- The "Payment Required" is a real HTTP primitive. It is not a workaround. Any HTTP-aware client can parse a 402, read the accepts array, and decide to pay. Agent frameworks fit in natively because they already handle HTTP status codes โ they just need a wallet.
Why it matters now (AI agents have no credit cards)
AI agents in 2026 have a structural problem. They are great at calling APIs, terrible at signing up for them. An agent building a product research workflow needs to pull from twenty specialised data sources, and nineteen of them require an email, a password, a credit card, and a human's consent. That friction compounds.
x402 gives the agent a different shape: here is a wallet, here is a budget, here is a list of endpoints that accept payment โ go do your job. Every company shipping agentic software hits this wall eventually. We chose to build for it first.
One endpoint, one price
The surface is deliberately minimal.
curl -X POST https://api.safebrowz.com/v1/detect \
-H "Content-Type: application/json" \
-d '{"url":"https://trezor-support.com"}'
First call, no payment headers โ server responds with a 402 challenge:
HTTP/2 402 Payment Required
Payment-Required: eyJ4NDAyVmVyc2lvbiI6Mi... (base64 v2 payload)
{
"x402Version": 1,
"status": 402,
"error": "payment_required",
"accepts": [
{
"scheme": "exact",
"network": "solana",
"networkCaip2": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
"maxAmountRequired": "1000",
"asset": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"payTo": "FLQyppmJYbvQvEPAB4Mv8ZGmxkSXmXUwMACeJ79kdozW",
"maxTimeoutSeconds": 60,
"extra": {
"token": "USDC", "decimals": 6,
"nonce_binding": "memo",
"memo_template": "safebrowz:87d311de-..."
}
},
{
"scheme": "exact",
"network": "base",
"networkCaip2": "eip155:8453",
"maxAmountRequired": "1000",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"payTo": "0xf3bc3a04646F1D721992AeDC07c98FC52FdFC358",
"extra": {
"token": "USDC", "decimals": 6, "chainId": 8453,
"nonce_binding": "eip191",
"sign_message_template": "safebrowz:87d311de-..."
}
}
]
}
Client picks a chain, pays 0.001 USDC onchain binding the nonce (SPL-memo on Solana or EIP-191 off-chain signature on Base), and retries with an X-PAYMENT header:
POST /v1/detect
Content-Type: application/json
X-PAYMENT: eyJ4NDAyVmVyc2lvbiI6MSwic2NoZW1lIjoiZXhhY3QiLC...
{"url":"https://trezor-support.com"}
Server verifies the onchain transaction, enforces nonce uniqueness (replay defense), and returns the full verdict:
HTTP/2 200 OK
{
"verdict": "danger",
"trust_score": 8,
"brand": "Trezor",
"confidence": 0.97,
"reason": "This page impersonates Trezor and does not belong to the real brand.",
"threat_types": [
"brand_impersonation",
"credential_phishing",
"wallet_drainer"
],
"signals": {
"brand_impersonation": true,
"credential_phishing": true,
"wallet_drainer": true,
"fresh_domain": true,
"fake_captcha": false,
"pastejacking": false,
...
},
"details": {
"matched_brand": "Trezor",
"official_domain": "trezor.io"
}
}
Twenty-three boolean signals in the full response, covering every threat category SafeBrowz tracks across 500+ brands and 100+ languages.
Inside the detection pipeline
The endpoint looks trivial from outside, but every request runs through a five-layer pipeline. Each layer is designed to exit as early as possible โ the closer a verdict is to the cheap end, the faster and less expensive the response.
Layer by layer:
- URL validation + well-known safe fast-path. SSRF guard (block private IP literals and reserved names), scheme check, length cap. Then a curated list of 80+ household-name domains (google.com, trezor.io, metamask.io, github.com, coinbase.com, every top wallet and exchange) short-circuits to a SAFE verdict with zero downstream work.
- Shared Redis cache. Verdicts for popular domains are cached across all callers โ 14 days for safe, 30 days for danger, 7 days for caution. Cache hit rate sits above 80% in production, keeping per-request cost rounding-error small.
- URL pattern engine. Thirty-plus scam URL signatures (wallet drainer paths, crypto airdrop patterns, common phish shapes), disposable TLD list, brand-keyword check with homograph normalization (rnโm, 0โo, etc.) and Levenshtein-1 edit-distance (catches
gooogle,microsooft,rnetamask). - Page fetch + AI content analysis. HTML fetched with a 5-second timeout and the same SSRF guard applied to every redirect. A language model extracts signals from the page: brand claimed vs brand owned, wallet drainer script patterns, fake captcha (ClickFix) copy, pastejacking patterns, credential phishing structure. 23 booleans plus a human-readable reason in under 500ms. Only about 20% of traffic reaches this layer โ everything else has been resolved by earlier steps.
- Decision engine. Signal counts + force-danger rules (any wallet_drainer, seed_phrase_phishing, fake_captcha, pastejacking, or brand_impersonation signal forces danger regardless of the positive count), plus a DNS probe for the "domain does not resolve" case. Output the final verdict, trust_score, confidence, and enriched details.
End-to-end latency: median ~240ms (dominated by cache hits), p95 ~900ms (AI content layer), p99 ~2.5s (page fetch timeouts on hostile servers).
Multi-chain from day one
We support x402 on both Solana mainnet and Base mainnet. Same endpoint, same response shape, client picks the chain its wallet stack is already on.
| Chain | Token | Nonce binding | Settles in | Typical fee |
|---|---|---|---|---|
| Solana mainnet | USDC (0.001) or SOL (0.00001) | SPL-memo instruction | ~400ms | ~$0.0002 |
| Base mainnet | USDC (0.001) | EIP-191 off-chain sig | ~2 seconds | ~$0.002 |
Solana was the obvious starting point. The transferChecked SPL token instruction plus an spl-memo instruction binding the nonce to exactly one transaction makes replay defense trivial โ the memo is onchain, unique per tx, and cannot be detached. Sub-second settlement pairs well with agent workloads.
Base covers every builder already operating in the EVM ecosystem โ anyone using viem, wagmi, MetaMask integrations, or the Coinbase Developer Platform. A pure-onchain nonce is not a thing for ERC-20 transfers (there is no memo field), so nonce binding is done off-chain: the payer EIP-191 personal_signs the message safebrowz:<nonce>, and the recovered address must match the on-chain Transfer event sender. No extra transaction, full replay defense.
Complete client โ TypeScript + viem (Base)
This is a working implementation. It fits on one screen.
import { createWalletClient, http, parseUnits, erc20Abi } from "viem";
import { base } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";
const USDC_BASE = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
const URL = "https://api.safebrowz.com/v1/detect";
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const wallet = createWalletClient({ account, chain: base, transport: http() });
export async function detect(target: string) {
// 1. First call โ expect 402
const first = await fetch(URL, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ url: target }),
});
if (first.status !== 402) return first.json();
const challenge = await first.json();
const baseEntry = challenge.accepts.find((a: any) => a.network === "base");
// 2. Pay USDC onchain to the configured receiver
const txHash = await wallet.writeContract({
address: USDC_BASE, abi: erc20Abi, functionName: "transfer",
args: [baseEntry.payTo, parseUnits("0.001", 6)],
});
// 3. Sign the off-chain nonce binding (EIP-191 personal_sign)
const walletSig = await wallet.signMessage({
message: baseEntry.extra.sign_message_template,
});
// 4. Retry with the spec-compliant X-PAYMENT header
const xPayment = Buffer.from(JSON.stringify({
x402Version: 1, scheme: "exact", network: "base",
payload: {
txHash,
walletSig,
nonce: baseEntry.extra.sign_message_template.split(":")[1],
},
})).toString("base64");
const verdict = await fetch(URL, {
method: "POST",
headers: { "Content-Type": "application/json", "X-PAYMENT": xPayment },
body: JSON.stringify({ url: target }),
});
return verdict.json();
}
Complete client โ Python on Solana
Same flow on Solana with solana-py. The memo binding replaces the off-chain signature step.
import base64, json, httpx
from solana.rpc.api import Client
from solders.keypair import Keypair
from solders.transaction import Transaction
from solders.pubkey import Pubkey
from spl.token.instructions import transfer_checked, TransferCheckedParams
from spl.token.constants import TOKEN_PROGRAM_ID
USDC_MINT = Pubkey.from_string("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v")
RPC_URL = "https://api.mainnet-beta.solana.com"
rpc = Client(RPC_URL)
kp = Keypair.from_base58_string(os.environ["SOLANA_SECRET"])
def detect(target: str) -> dict:
# 1. Challenge
r = httpx.post("https://api.safebrowz.com/v1/detect",
json={"url": target})
if r.status_code != 402:
return r.json()
sol_entry = next(a for a in r.json()["accepts"] if a["network"] == "solana")
# 2. Build USDC transferChecked + spl-memo binding the nonce
memo = sol_entry["extra"]["memo_template"] # "safebrowz:<nonce>"
tx = build_usdc_transfer_with_memo(
payer=kp.pubkey(),
receiver=Pubkey.from_string(sol_entry["payTo"]),
amount_atomic=int(sol_entry["maxAmountRequired"]),
memo_text=memo,
)
tx.sign([kp], rpc.get_latest_blockhash().value.blockhash)
tx_sig = rpc.send_transaction(tx).value
# 3. Retry with X-PAYMENT
x_payment = base64.b64encode(json.dumps({
"x402Version": 1, "scheme": "exact", "network": "solana",
"payload": {"txSignature": str(tx_sig), "nonce": memo.split(":")[1]},
}).encode()).decode()
return httpx.post(
"https://api.safebrowz.com/v1/detect",
headers={"X-PAYMENT": x_payment},
json={"url": target},
).json()
Zero-config clients with agentcash
If you do not want to roll your own payment flow, the x402 ecosystem already ships CLI and library clients that handle the whole dance automatically:
npx agentcash fetch https://api.safebrowz.com/v1/detect \
--body '{"url":"https://trezor-support.com"}' \
--network solana
The CLI detects the 402, signs and broadcasts the USDC payment from a configured wallet, retries with the spec-compliant X-PAYMENT header, and prints the verdict. One-liner.
Agent-native discovery
Beyond the endpoint itself, we published every artifact an AI agent needs to discover, understand, and integrate with the API without a human in the loop:
| Artifact | Path | Consumed by |
|---|---|---|
| OpenAPI 3.1 spec | /v1/openapi.json | SDK generators, Postman, ChatGPT Actions |
| x402 discovery doc | /.well-known/x402 | x402scan, Coinbase Bazaar, agentcash |
| Agent skill file | /safebrowz-api.skill.md | Claude skills, GPT tool use, LangChain, MCP servers |
| AI plugin manifest | /.well-known/ai-plugin.json | Legacy GPT plugins, ChatGPT connectors |
| llms.txt | /api-llms.txt | ChatGPT-style retrieval crawlers |
An agent framework can read any one of these, build a tool definition, and start paying for scans inside a single conversation turn. That is the bar for "agent-ready" in 2026.
Why $0.001 and not more
Pricing a new API is guesswork until real data arrives. We looked at it from three angles and all three pointed at the same number.
Margin angle. Amortised upstream cost per scan (cache hits subsidise AI content calls) sits below $0.0002. At $0.001 we keep healthy margin even with the buyer paying their own gas, which on Solana is a rounding error and on Base is a couple of cents.
Market angle. Commercial URL-safety APIs price between $2 and $10 per 1,000 calls when you can even sign up for them. $0.001 per call is $1 per 1,000. We priced to be the first dependency a builder reaches for, not the third.
Agent economics angle. An agent sending 100 URL checks in one session at $0.001 each is $0.10 total. That is the price point where integrating us becomes a no-brainer for any agent that does not want to be the vector that drains its user.
Buyer pays gas, on purpose
The x402 ecosystem has two schools on gas. In the facilitator-settled model, the server (or a shared relayer) submits the onchain transfer on behalf of the buyer, absorbing gas and reclaiming it from the payment amount. In the buyer-pays-gas model, the client itself broadcasts the transfer. We chose the second.
At $0.001 per request the math is unforgiving. Base gas for a typical USDC transfer during normal conditions is $0.002โ0.005. If we absorb it, the payment is underwater before we have done any work. Across meaningful volume we would be operating the API at a loss.
The buyer-pays-gas model flips that. The client is already building with a wallet stack and broadcasting is cheap for them. We verify the onchain result, return the verdict, and keep margin intact. For every real integration path โ developer with their own wallet, agent pre-funded by its operator, wallet-app running a backend proxy โ gas is not a meaningful cost.
We do have the relayer path implemented and gated behind a feature flag. For now, buyer-pays-gas keeps the economics clean. If enterprise demand shifts, we can flip the flag in 15 seconds.
Two tiers: x402 for everyone, Bearer keys for enterprise
The public endpoint runs x402 pay-per-request. That works beautifully for one-off dev integrations, AI agents calling a handful of URLs per session, and anyone who wants to kick the tires without a signup form.
For wallet apps and platforms with millions of end users behind a backend proxy, per-call onchain signing is impractical. MetaMask is not going to make their extension sign a USDC transaction every time a user hovers a link. So there is a second tier.
Enterprise Bearer keys are provisioned on request for high-volume integrators. A single long-lived token of the form sk_live_..., passed as Authorization: Bearer sk_live_..., skips the x402 flow entirely. Each key has its own rate limit (negotiated at provisioning, typically 10,000 to 100,000 requests per minute) and its own usage ledger. Billing is monthly in USDC via flat subscription.
Who this is for
- AI agent frameworks โ Claude skills, GPT tool use, LangChain, MCP servers. Any agent that parses URLs from user input or the web needs a safety check before it clicks.
- Wallet apps โ MetaMask snaps, Phantom extensions, Trust Wallet, Rainbow, Rabby. Pre-connect URL safety would stop the majority of wallet drains we see every month.
- dApp frontends โ anyone embedding third-party links, community submissions, marketplace listings. A $0.001 per-click safety verdict is cheaper than one angry tweet from a drained user.
- Browser extensions โ productivity and security tools that want to outsource URL reasoning instead of running their own detection.
- Agentic search engines โ Perplexity-style clones, Arc-style browsers, personal research agents. Every surfaced link is a potential drain if unfiltered.
- Telegram / Discord bots โ community moderation tools. We ship one ourselves at
@SafeBrowzbot.
What comes next
- More chains โ Arbitrum + Optimism by Q3, Polygon once demand proves. Same endpoint, same response, additional entries in the 402 accepts array.
- Batch scanning โ
POST /v1/detect/batchfor workflows that need 50+ URLs in one shot. Linear price, small concurrency discount. - Webhook streaming tier โ for enterprise customers wanting real-time alert streams instead of polling. Same Bearer auth, persistent WebSocket, higher rate limits.
We are also listed on x402scan, the ecosystem directory for x402-enabled services. As more clients (agentcash, Coinbase Bazaar, CDP wallets) ship, the directory is becoming the agent-native equivalent of an API marketplace.
Try it now
The live demo runs at safebrowz.com/api-docs. Connect Phantom or MetaMask, scan any URL, see the verdict. End-to-end integration takes under an hour even for someone who has never touched x402 before โ and you only pay for what you actually use.
We believe the open payment endpoint is going to be the dominant shape of machine-to-machine commerce within two years. We would rather be the phishing safety layer that ships first than the one that shows up late. If you are building anything that touches URLs or wallets, give it a try and tell us what breaks.
Start integrating in under an hour
SafeBrowz Detection API is live at api.safebrowz.com/v1/detect. Pay-per-request URL safety, $0.001 USDC on Solana or Base. No signup, no API keys. Enterprise Bearer keys available on request.
Read the API docs OpenAPI spec Agent skill file Telegram bot
Built by the same team behind the SafeBrowz browser extension blocking phishing and wallet drainers in Chrome, Firefox, and Edge.