// DEVELOPER API

SafeBrowz Detection API

Phishing and wallet drainer detection for any URL. Pay per request with USDC on Solana or Base via x402 - no signup required. High-volume integrators get a Bearer key and a flat monthly subscription.

// FOR AI AGENTS

Drop-in agent skill

Building a Claude Agent, ChatGPT Custom GPT, Cursor rule, or any LLM-driven app? Paste our skill file into your agent's rules and it will know when and how to call the API.

/skill

Agent Skill (markdown)

Complete skill definition with triggers, payment flow, signal interpretation, code examples. Ready to paste into any agent framework.

Download skill.md
/openapi

OpenAPI 3.1 Spec

Machine-readable endpoint schema. Use with ChatGPT Actions, Postman, Insomnia, or any SDK generator.

View openapi.json
/llms

LLM-friendly Docs

Full plain-text reference optimized for AI crawlers and agent context windows. Includes citation guidance.

View api-llms.txt

Plugin manifest at /.well-known/ai-plugin.json

// PRICING

One price. No tiers.

$0.001

Per request

Pay in USDC on Solana or Base mainnet. No subscription, no commitment. Cache hits are still billed at the same rate - keeps integration simple and covers infrastructure.

Full scan

Extension parity

Every signal the SafeBrowz browser extension detects - credential phishing, pastejacking, ClickFix, wallet drainers, brand impersonation, and 18 more - is returned by the API. No URL-only shortcut.

500+

Brands tracked

Covers wallets (MetaMask, Phantom, Ledger, Trezor), exchanges (Binance, Coinbase, OKX), payment services (PayPal, Venmo, Stripe), and major global consumer brands.

// TRY IT LIVE

Run the full x402 flow in your browser

Connect any wallet, paste a URL, click test. Pay 0.001 USDC on Solana or Base. Works with any SPL or EVM wallet. Solana wallet needs a small SOL balance for the network fee.

Pick a chain below - cost stays the same.

Need 0.001 USDC + a tiny bit of SOL for the network fee on Solana, or 0.001 USDC + ETH gas on Base. No refunds - payment is onchain.

// QUICKSTART

Or curl it in 30 seconds

Every request requires an x402 payment. First call returns 402 with payment instructions. Pay, then retry with the transaction signature.

Step 1 - Get a 402 nonce

curl -s -X POST https://api.safebrowz.com/v1/detect \
  -H "Content-Type: application/json" \
  -d '{"url":"https://app.trezor-io.us.com/"}'

Response (402)

Pick any option inside payment or payment.alternatives. The primary entry is Solana USDC; alternatives include Solana SOL and Base USDC.

{
  "status": 402,
  "error": "payment_required",
  "payment": {
    "amount": "0.001",
    "token": "USDC",
    "token_mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
    "chain": "solana",
    "recipient": "FLQyppmJYbvQvEPAB4Mv8ZGmxkSXmXUwMACeJ79kdozW",
    "nonce": "ed548e77-719f-4f13-9f01-32dc8ed4e213",
    "memo_format": "safebrowz:ed548e77-719f-4f13-9f01-32dc8ed4e213",
    "alternatives": [
      { "token": "SOL",  "amount": "0.00001", "chain": "solana", "nonce_binding": "memo",   "memo_format": "safebrowz:..." },
      { "token": "USDC", "amount": "0.001",   "chain": "base",   "chain_id": 8453,
        "token_contract": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
        "recipient": "0xf3bc3a04646F1D721992AeDC07c98FC52FdFC358",
        "nonce_binding": "eip191",
        "sign_message": "safebrowz:ed548e77-719f-4f13-9f01-32dc8ed4e213" }
    ]
  }
}

Step 2a - Pay on Solana

Transfer 0.001 USDC (or 0.00001 SOL) to the recipient with memo safebrowz:<nonce>. Any Solana wallet or the spl-token CLI works. Nonces expire in 10 minutes.

spl-token transfer EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v 0.001 \
  FLQyppmJYbvQvEPAB4Mv8ZGmxkSXmXUwMACeJ79kdozW \
  --fund-recipient \
  --with-memo "safebrowz:ed548e77-719f-4f13-9f01-32dc8ed4e213"

Step 2b - Pay on Base (EVM wallets)

Send a standard USDC ERC-20 transfer on Base to the recipient, then sign the nonce message off-chain. Base lacks a native memo field, so nonce binding uses EIP-191 personal_sign of safebrowz:<nonce>. The signature must recover to the wallet that paid.

// viem / ethers pseudocode
const txHash = await wallet.writeContract({
  address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // USDC on Base
  abi: erc20Abi, functionName: "transfer",
  args: [ "0xf3bc3a04646F1D721992AeDC07c98FC52FdFC358", 1000n ], // 0.001 USDC (6 dec)
});
const walletSig = await wallet.signMessage({
  message: "safebrowz:ed548e77-719f-4f13-9f01-32dc8ed4e213",
});

Step 3 - Retry with the proof

For Solana, send the tx signature only. For Base, also send the EIP-191 wallet signature and set X-402-Chain: base.

# Solana
curl -s -X POST https://api.safebrowz.com/v1/detect \
  -H "Content-Type: application/json" \
  -H "X-402-Signature: <your_tx_signature>" \
  -H "X-402-Nonce: ed548e77-719f-4f13-9f01-32dc8ed4e213" \
  -d '{"url":"https://app.trezor-io.us.com/"}'

# Base
curl -s -X POST https://api.safebrowz.com/v1/detect \
  -H "Content-Type: application/json" \
  -H "X-402-Chain: base" \
  -H "X-402-Signature: <tx_hash>" \
  -H "X-402-Wallet-Sig: <eip191_signature>" \
  -H "X-402-Nonce: ed548e77-719f-4f13-9f01-32dc8ed4e213" \
  -d '{"url":"https://app.trezor-io.us.com/"}'

Response (200)

{
  "verdict": "danger",
  "trust_score": 5,
  "brand": "Ledger",
  "confidence": 0.95,
  "reason": "Fake Ledger Live login page - potential phishing and crypto scam",
  "threat_types": ["brand_impersonation", "crypto_scam", "credential_phishing"],
  "signals": {
    "brand_impersonation": true,
    "credential_phishing": true,
    "crypto_scam": true,
    "no_contact_info": true,
    "domain_mismatch": true,
    "wallet_drainer": false,
    "seed_phrase_phishing": false,
    "fake_captcha": false,
    "pastejacking": false,
    "tech_support_scam": false
    // ...remaining signals (all booleans) omitted for brevity
  },
  "details": {
    "matched_brand": "Ledger",
    "official_domain": "ledger.com",
    "domain_matches_brand": false,
    "target_country": "Global",
    "page_language": "English"
  }
}

trust_score is a simple 0-100 trustworthiness score (100 = safe, 0 = scam). confidence is how sure we are of the verdict itself - for a danger verdict, 0.95 means "we are 95% sure this is a scam," not "95% fake."

// INTEGRATE

Full programmatic clients

Copy-paste one of these, plug in a wallet, you are done. Each example handles the full x402 flow end-to-end: initial call, parse 402 challenge, pay onchain, retry with X-PAYMENT header. Mix and match languages - the API is identical regardless of which client calls it.

TypeScript + viem (Base)

A ~45-line client that covers the full round trip on Base mainnet. Uses viem for USDC transfer + EIP-191 nonce sig.

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();
}

Python + solana-py (Solana)

Same flow on Solana. Uses solders for keypair + transaction construction and the SPL-memo instruction for nonce binding.

import base64, json, httpx, os
from solana.rpc.api import Client
from solders.keypair import Keypair
from solders.pubkey import Pubkey

USDC_MINT = Pubkey.from_string("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v")
rpc = Client("https://api.mainnet-beta.solana.com")
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 - agentcash CLI

If you do not want to roll your own payment flow, agentcash ships the whole x402 dance. It detects 402, signs and broadcasts the payment, retries with the spec-compliant header, and prints the verdict. One line:

npx agentcash fetch https://api.safebrowz.com/v1/detect \
  --body '{"url":"https://trezor-support.com"}' \
  --network solana

Works on both --network solana and --network eip155:8453. Uses an agentcash-managed wallet - top it up with USDC and it just works.

Agent frameworks - Claude, GPT, LangChain, MCP

Every major agent framework can load our published skill file and use the detection API as a tool without any manual integration code:

# Claude Code / Claude Desktop
#   - Save /safebrowz-api.skill.md locally
#   - Add to your ~/.claude/skills/ directory
#   - Claude loads it automatically

# MCP server config (Claude Desktop, etc.)
#   - Point at the OpenAPI spec: https://api.safebrowz.com/v1/openapi.json
#   - MCP auto-generates a detect() tool

# LangChain
from langchain.tools import OpenAPIToolkit
from langchain.utilities.openapi import OpenAPISpec
spec = OpenAPISpec.from_url("https://api.safebrowz.com/v1/openapi.json")
toolkit = OpenAPIToolkit.from_llm_and_spec(llm, spec)

Enterprise Bearer auth (bypass x402)

High-volume integrators - wallet apps and AI platforms with millions of end users - can request a long-lived Bearer key. No per-call signing; pass the key as an Authorization header and get a normal 200 response immediately. Billing is monthly via flat USDC subscription.

curl -X POST https://api.safebrowz.com/v1/detect \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk_live_YOUR_KEY" \
  -d '{"url":"https://example.com"}'

Email info@safebrowz.com with your expected volume (req/min + monthly total) to provision a key. Typical tier is 10,000 to 100,000 requests per minute, rate-limited per-key so your throughput is isolated from every other enterprise customer.

// REFERENCE

Endpoints

POST/v1/detect

Return a scam/phishing verdict for a URL. Requires x402 payment.

Request body

{"url": "https://example.com"}

Response (200)

FieldTypeDescription
verdictstringsafe / caution / danger
trust_scoreinteger0-100 trustworthiness score (100 = safe, 0 = scam)
brandstring / nullImpersonated brand if detected (e.g., "Ledger", "Trezor", "PayPal")
confidencenumber0.0-1.0. How sure we are of the verdict. Not "fake percentage."
reasonstringHuman-readable explanation
threat_typesstring[]Top-level categories: wallet_drainer, seed_phrase_phishing, brand_impersonation, crypto_scam, crypto_airdrop_scam, credential_phishing, account_phishing, delivery_scam, government_impersonation, invoice_scam, tech_support_scam, fake_captcha, pastejacking
signalsobjectAll 22 boolean flags (includes domain_mismatch, no_contact_info, fake_urgency, too_good_prices, suspicious_payment, etc.)
detailsobjectmatched_brand, official_domain, domain_matches_brand, target_country, page_language, tld, domain_age_days, matched_patterns
GET/v1/status

Health check. No payment required.

{"status": "ok", "version": "1.0.0", "chain": "solana"}
// ERROR CODES

Errors

StatusErrorMeaning
400missing_urlRequest body did not include a url field.
400invalid_urlURL was malformed, too long, or pointed at a private IP.
402payment_requiredNo payment headers. Body contains instructions for all supported chains.
402payment_invalidPayment headers were supplied but verification failed. Get a fresh nonce and retry. Response body re-issues the full payment instructions.
409nonce_already_usedThis nonce was already claimed. Retry with a fresh 402 nonce.
429rate_limitedToo many requests per minute. Back off and retry.
// FAQ

Common questions

Why x402 instead of API keys?

For the public endpoint, x402 means no signup forms, no rate tiers, no billing emails, no support tickets. You pay 0.001 USDC and get a result. No relationship required. For wallet apps and AI platforms serving millions of users behind a proxy, we issue enterprise Bearer keys on request (see the enterprise pricing FAQ below).

What's the latency?

Cached verdicts return in 50-150 ms. URL-pattern matches are similar. Fresh URLs that need a page fetch + AI scan typically take 2-4 seconds end-to-end. Payment verification against Solana or Base RPC adds ~300-500 ms on top of that, regardless of scan depth.

How does this compare to the browser extension?

Every signal the extension detects - credential_phishing, pastejacking, fake_captcha (ClickFix), wallet_drainer, no_contact_info, fake_urgency, and 17 more - is returned by this API. The underlying detection pipeline is shared: cache, URL rules, then a full AI page scan on cache miss. You get the same trust_score, the same brand identification, the same signals object.

Can I request a refund?

No refunds. The payment is non-reversible by design (onchain settlement). If the API returns a 5xx server error, retry with the same nonce - we do not consume nonces on server-side failures.

Do you offer enterprise / flat-rate pricing?

Yes. We provision long-lived Bearer API keys for wallet apps, AI agent platforms, and other high-volume integrators where per-call onchain signing is impractical. Each key gets its own rate limit (typically 10,000 to 100,000 requests per minute) and is billed monthly in USDC. Pass it as Authorization: Bearer sk_live_... and the x402 flow is skipped. Email info@safebrowz.com with expected volume and we will onboard you.

What data do you see?

Only the URL you send. We do not log page contents, cookies, headers, or user identifiers. The onchain transaction signature (Solana or Base) is stored for replay protection and revenue accounting.

Ready to integrate?

No forms to fill. Point any Solana or EVM wallet at api.safebrowz.com/v1/detect and start scanning.