Paid API for AI agents: pay per call in USDC (x402)
Bulk versions of the free tools for agents and scripts, with more domains, URLs and results per call and no visitor rate limit, plus agent utilities: web page to clean Markdown, domain WHOIS (RDAP) with DNS and email security, a robots.txt crawl-permission check, PDF and document to Markdown, short audio transcription with Whisper, and website screenshots. There is no account and no API key: each call is paid with USDC on Base through the open x402 protocol (version 2), from $0.001 to $0.01 a call.
Endpoints and prices
| Endpoint | Price (USDC) | What one call returns | Free single-item version |
|---|---|---|---|
GET /x402/v1/tech-stack | $0.005 | Technologies, CMS, CDN, hosting, security-header grade and email/DNS providers for up to 3 domains per call. | Website tech stack checker |
GET /x402/v1/meta-tags | $0.004 | Title, description, canonical, robots, H1/H2, hreflang, Open Graph, Twitter and JSON-LD checks with issue codes for up to 3 pages per call. | 1 item at /api/meta-tags |
GET /x402/v1/url-status | $0.003 | HTTP status, redirect chain and broken/blocked/restricted classification for up to 10 URLs per call. | 1 item at /api/url-status |
GET /x402/v1/sitemap-urls | $0.004 | Every URL in a site's XML, text or feed sitemaps (robots.txt discovery, indexes, gzip): up to 5,000 URLs from 20 sitemap files, JSON or CSV. | Sitemap URL extractor |
GET /x402/v1/rss-to-json | $0.003 | RSS 0.9x/2.0, RDF, Atom and JSON Feed normalised to one item format, with feed discovery from a page, for up to 5 feeds per call. | RSS to JSON converter |
GET /x402/v1/ted-search | $0.002 | Search EU procurement notices on TED (official API v3) by keywords, buyer country and open deadline: 100 notices per call with paging. | TED tender search |
GET /x402/v1/page-markdown | $0.002 | The main content of up to 3 web pages as clean Markdown (headings, lists, links, tables, code), with title, description and word count. | none (paid only) |
GET /x402/v1/domain-intel | $0.003 | Registrar, creation and expiry dates, status and nameservers from RDAP, plus A/AAAA/MX/NS/TXT/CAA records, email provider, SPF and DMARC for up to 3 domains per call. | none (paid only) |
GET /x402/v1/robots-check | $0.001 | Whether GPTBot, ClaudeBot, PerplexityBot, Googlebot and other user agents may fetch up to 5 URLs under robots.txt, with crawl-delay, sitemaps and llms.txt presence. | none (paid only) |
GET /x402/v1/document-markdown | $0.004 | One PDF, DOCX, XLSX/XLS, ODS/ODT, CSV, HTML, XML or Numbers file (public URL, up to 10 MB) converted to Markdown from its text layer; no OCR. | none (paid only) |
GET /x402/v1/transcribe-short | $0.01 | One audio file (MP3, WAV, M4A, OGG, FLAC or WebM, public URL, up to 2 MB and 20 minutes) transcribed or translated to English with Whisper large-v3-turbo: text, timed segments and WebVTT. | none (paid only) |
GET /x402/v1/screenshot | $0.01 | A PNG or JPEG screenshot of one public web page at 1440×900 (desktop) or 390×844 (mobile), rendered in a headless browser; image or JSON with base64. | none (paid only) |
Prices are per call, flat, whatever the number of items up to the limit. The free tools stay free.
How paying works
- Call an endpoint with GET. Without payment it answers
402 Payment Required; thePAYMENT-REQUIREDheader holds the terms as base64 JSON (repeated in the body): schemeexact, networkeip155:8453(Base), asset USDC0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913, the amount in atomic units (6 decimals) andpayTo0x491Fcf30a5aa0483B3cd8C0041d21801F195B3AF. - Your client signs an EIP-3009 authorization for exactly that amount and repeats the request with a
PAYMENT-SIGNATUREheader. Any x402 v2 client does this for you. - The server checks the payment with a facilitator, runs the lookup, and settles only if it succeeded. The
PAYMENT-RESPONSEheader of the 200 answer carries the settlement receipt with the transaction hash.
import { x402Client, wrapFetchWithPayment } from "@x402/fetch";
import { ExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";
const client = new x402Client();
client.register("eip155:*", new ExactEvmScheme(privateKeyToAccount(process.env.PRIVATE_KEY)));
client.setSpendControls({ maxAmountPerPayment: "$0.01" });
const payFetch = wrapFetchWithPayment(fetch, client);
const res = await payFetch("https://tools.adamhaleworks.workers.dev/x402/v1/tech-stack?domains=wordpress.org,stripe.com");
console.log(await res.json());
To see the terms without paying:
curl -si "https://tools.adamhaleworks.workers.dev/x402/v1/ted-search?q=cloud%20hosting" | grep -i payment-required
Payments are verified and settled by the public PayAI facilitator, with the open XPay facilitator as a fallback; neither holds funds, and the USDC goes straight to the address above.
Parameters
Bulk website tech stack lookup
Use when you need to know what a website is built with (CMS, frameworks, analytics, CDN, hosting), who hosts its email and DNS, and how good its security headers are. Up to 3 domains per call; fetches each homepage once, follows robots.txt.
| Parameter | Required | Description |
|---|---|---|
domains | yes | Up to 3 domains or homepage URLs, comma-separated. Public hosts only. |
GET https://tools.adamhaleworks.workers.dev/x402/v1/tech-stack?domains=wordpress.org%2Cstripe.com
Bulk SEO meta tag and schema check
Use when you need an on-page SEO audit of specific URLs: title and meta description lengths, canonical, robots/noindex, headings, hreflang, Open Graph, Twitter card and JSON-LD rich-result checks, with machine-readable issue codes. Up to 3 URLs per call.
| Parameter | Required | Description |
|---|---|---|
urls | yes | Up to 3 URLs, comma-separated. A bare domain means its https:// homepage. Public hosts only (no IPs, no internal names), ports 80/443. |
GET https://tools.adamhaleworks.workers.dev/x402/v1/meta-tags?urls=https%3A%2F%2Fwww.python.org%2F%2Chttps%3A%2F%2Fapify.com%2F
Bulk URL status and redirect checker
Use when you need to know whether links are alive: HTTP status, every redirect hop, final URL and a classification (ok, redirect, broken, restricted, blocked_by_site, disallowed_by_robots_txt, timeout). Up to 10 URLs per call; HEAD first, GET to confirm errors.
| Parameter | Required | Description |
|---|---|---|
urls | yes | Up to 10 URLs, comma-separated. A bare domain means its https:// homepage. Public hosts only (no IPs, no internal names), ports 80/443. |
GET https://tools.adamhaleworks.workers.dev/x402/v1/url-status?urls=http%3A%2F%2Fapify.com%2Chttps%3A%2F%2Fhttpbin.org%2Fstatus%2F404
Sitemap URL extractor (5,000 URLs)
Use when you need the list of pages on a website: finds sitemaps via robots.txt or common paths, follows sitemap indexes, reads gzip, text and feed sitemaps, and returns up to 5,000 URLs with lastmod from up to 20 files. format=csv returns CSV.
| Parameter | Required | Description |
|---|---|---|
url | yes | A domain (sitemaps found via robots.txt or common paths) or the URL of one sitemap file. |
format | no | json (default) or csv. |
GET https://tools.adamhaleworks.workers.dev/x402/v1/sitemap-urls?url=github.blog
RSS, Atom and JSON Feed to JSON (5 feeds)
Use when you need the latest items of news feeds or blogs as clean JSON: accepts feed URLs or plain site URLs (finds the feed via <link rel=alternate>), normalises RSS, RDF, Atom and JSON Feed to one item schema (title, url, publishedAt, author, categories, summary). Up to 5 feeds, 100 items each.
| Parameter | Required | Description |
|---|---|---|
urls | yes | Up to 5 feed or site URLs, comma-separated. A bare domain means its https:// homepage. Public hosts only (no IPs, no internal names), ports 80/443. |
GET https://tools.adamhaleworks.workers.dev/x402/v1/rss-to-json?urls=github.blog%2Chttps%3A%2F%2Fhnrss.org%2Ffrontpage
EU public tender search (TED), 100 per page
Use when you need EU public procurement notices (tenders, contract notices, awards) from TED: keyword search (comma = OR), optional buyer country (ISO-2) and open-deadline filter, newest first, 100 notices per page, page up to 50.
| Parameter | Required | Description |
|---|---|---|
q | yes | Keywords; a comma separates alternatives (OR), up to 5. |
country | no | Buyer country as ISO 3166-1 alpha-2 (EU/EEA + CH), e.g. FR, DE. |
open | no | 1 = only notices whose tender deadline has not passed. |
page | no | Result page, 1-50 (100 notices per page). |
GET https://tools.adamhaleworks.workers.dev/x402/v1/ted-search?q=cloud%20hosting%2Cdata%20centre
Web page to clean Markdown (3 URLs)
Use when you need to read a web page: returns its main content as clean Markdown without navigation, scripts or ads (headings, lists, absolute links, tables, code blocks), plus title, description, language, canonical URL and word count. Up to 3 URLs per call, 100,000 characters each; follows robots.txt and does not get past bot walls.
| Parameter | Required | Description |
|---|---|---|
urls | yes | Up to 3 page URLs, comma-separated. A bare domain means its https:// homepage. Public hosts only (no IPs, no internal names), ports 80/443. |
GET https://tools.adamhaleworks.workers.dev/x402/v1/page-markdown?urls=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FWeb%2FHTTP%2FStatus%2F402
Domain WHOIS (RDAP), DNS and email security lookup (3 domains)
Use when you need to know who a domain is registered with and since when (RDAP: registrar, created, expires, age, status, DNSSEC), what its DNS says (A, AAAA, MX, NS, TXT, CAA) and how its email is set up (provider, SPF policy, DMARC policy). No registrant personal data. Up to 3 domains per call.
| Parameter | Required | Description |
|---|---|---|
domains | yes | Up to 3 domains, comma-separated (a URL or email address is reduced to its domain). Public names only. |
GET https://tools.adamhaleworks.workers.dev/x402/v1/domain-intel?domains=wordpress.org%2Cstripe.com
robots.txt crawl permission check for AI agents (5 URLs)
Use when you are about to crawl or scrape a URL: tells whether each user agent (default: 13 common AI and search crawlers, or your own tokens) may fetch it under the site's robots.txt (RFC 9309, longest match, '*' fallback), with crawl-delay, the sitemaps robots.txt lists and whether the site publishes /llms.txt. Up to 5 URLs per call.
| Parameter | Required | Description |
|---|---|---|
urls | yes | Up to 5 URLs, comma-separated. A bare domain means its https:// homepage. Public hosts only (no IPs, no internal names), ports 80/443. |
agents | no | User-agent product tokens to check, comma-separated, up to 15 (default: GPTBot, ChatGPT-User, OAI-SearchBot, ClaudeBot, Claude-User, PerplexityBot, Google-Extended, Googlebot, Bingbot, CCBot, Applebot-Extended, Bytespider, *). |
GET https://tools.adamhaleworks.workers.dev/x402/v1/robots-check?urls=https%3A%2F%2Fwww.nytimes.com%2Fsection%2Ftechnology%2Chttps%3A%2F%2Fgithub.com%2Fabout
PDF and document to Markdown (10 MB)
Use when you need the text of a document as Markdown: give the public URL of a PDF (with a text layer), Word DOCX, Excel XLSX/XLSM/XLSB/XLS, OpenDocument ODS/ODT, CSV, HTML, XML or Apple Numbers file up to 10 MB and get Markdown (tables kept), up to 250,000 characters. Text-layer conversion only: scanned PDFs, images, PPTX and encrypted files are refused and not charged.
- One file per call, public http(s) URL, up to 10 MB (Content-Length checked, then a streamed hard cap).
- Formats are detected from the file's bytes: PDF, DOCX, XLSX, XLSM, XLSB, XLS, ODS, ODT, CSV, HTML, XML, Numbers. Images, PPTX, DOC, EPUB and encrypted files are refused.
- Text layer only, no OCR: a PDF without extractable text gets NO_TEXT_LAYER and is not charged.
- Markdown is capped at 250,000 characters (truncated: true). The file is never stored.
- Daily capacity: 1,000 conversions a day on free compute; when it is used up the endpoint answers 503 with
Retry-Afterbefore any payment.
| Parameter | Required | Description |
|---|---|---|
url | yes | Public URL of the document (PDF, DOCX, XLSX/XLSM/XLSB/XLS, ODS, ODT, CSV, HTML, XML or Numbers), up to 10 MB. No IPs or internal names. |
filename | no | Optional file name, used as a format hint and in the result. |
metadata | no | 1 (default) keeps the PDF's metadata block at the top of the Markdown; 0 drops it. |
GET https://tools.adamhaleworks.workers.dev/x402/v1/document-markdown?url=https%3A%2F%2Fbitcoin.org%2Fbitcoin.pdf
Short audio transcription (Whisper, 2 MB)
Use when you need a transcript of a short audio clip: give the direct public URL of an MP3, WAV, M4A, OGG, FLAC or WebM file up to 2 MB (and 20 minutes) and get the text, word count, timed segments, WebVTT subtitles and the detected language, from Whisper large-v3-turbo. task=translate returns English. No YouTube or social media pages.
- One audio file per call: MP3, WAV, M4A, OGG, FLAC or WebM, detected from its bytes; direct file URLs only (no YouTube, TikTok, SoundCloud and similar pages).
- Up to 2 MB (streamed hard cap) and 20 minutes (read from the file header where it has one).
- Fixed model @cf/openai/whisper-large-v3-turbo; no model choice and no prompts.
- Charged when text comes back, or when the file is valid audio with no speech (noSpeech: true). The file is never stored.
- Daily capacity: about 120 audio minutes a day on free compute; when it is used up the endpoint answers 503 with
Retry-Afterbefore any payment.
| Parameter | Required | Description |
|---|---|---|
url | yes | Direct public URL of an audio file (MP3, WAV, M4A, OGG, FLAC or WebM), up to 2 MB. No YouTube or social media pages. |
task | no | transcribe (default) or translate (into English). |
language | no | Spoken language as an ISO 639-1 code (en, de, es…); detected when omitted. |
vad | no | 1 (default) filters silence with voice activity detection first; 0 turns it off. |
GET https://tools.adamhaleworks.workers.dev/x402/v1/transcribe-short?url=https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fcommons%2F4%2F46%2F1941_Roosevelt_speech_pearlharbor_p1.ogg
Website screenshot (desktop or mobile)
Use when you need to see a web page as a browser renders it: one public URL, desktop (1440x900) or mobile (390x844) viewport, PNG or JPEG, returned as the image itself or as JSON with base64 (response=json). Viewport only, no full-page capture, no scripts, cookies or logins; follows robots.txt and does not get past bot walls. Capacity is limited per day.
- One URL per call, viewport only: desktop 1440x900 or mobile 390x844. No full-page capture, custom scripts, headers, cookies or logins.
- The page must answer 200 with HTML to our robots.txt-respecting check first; bot walls, 4xx/5xx and non-HTML URLs are refused and not charged.
- 15-second navigation timeout; media, WebSocket and event-stream requests and requests to IP addresses or local names are blocked in the browser.
- At most one screenshot every 10 seconds (429 with Retry-After before payment) and about 7 browser-minutes a day (503 when used up). Images up to 10 MB.
- Daily capacity: 7 browser-minutes a day on free compute; when it is used up the endpoint answers 503 with
Retry-Afterbefore any payment.
| Parameter | Required | Description |
|---|---|---|
url | yes | Public URL of the web page. No IPs or internal names; ports 80/443. |
device | no | desktop (1440x900, default) or mobile (390x844). |
format | no | png (default) or jpeg (quality 80, smaller). |
response | no | image (default: the image bytes) or json (metadata plus imageBase64). |
GET https://tools.adamhaleworks.workers.dev/x402/v1/screenshot?url=https%3A%2F%2Fexample.comRules that protect you and the sites checked
- No charge for bad input. Invalid, private or too many inputs get HTTP 400 before the 402 challenge.
- No charge when nothing worked. If every item fails, the error comes back and the payment is not settled.
- Same honest fetching as the free tools. robots.txt is read and followed, the User-Agent is
AdamHaleTools/1.0, there are no proxies and no attempts to get past bot protection, and private or internal addresses are never fetched (details). - Per-site politeness. Each target host is limited to about 20 lookups a minute across all callers; over it you get 429 with
Retry-After, before paying. - Heavy endpoints fail closed. Documents, transcription and screenshots run on a fixed daily allocation of free compute. When the day's share is used up they answer 503 with
Retry-Afterbefore the 402 challenge, and a conversion, transcription or screenshot that fails is not settled. Files and images are processed in memory and never stored.
Machine-readable discovery
- OpenAPI 3.1 with
x-payment-infofor every paid operation: https://tools.adamhaleworks.workers.dev/openapi.json - x402 resource list: https://tools.adamhaleworks.workers.dev/.well-known/x402
- Every 402 challenge carries the x402 Bazaar extension (input schema, example call and example output), so facilitators that run a Bazaar catalog the endpoints from the first payment.
- MCP server card: https://tools.adamhaleworks.workers.dev/.well-known/mcp/server-card.json
Use it as an MCP server
The same lookups are available to MCP clients (Claude, Cursor, VS Code, agent frameworks) as a remote server: https://tools.adamhaleworks.workers.dev/mcp, Streamable HTTP, stateless, with no account and no API key. Single items of the free tools run free under the same limits as the free tools (10 calls a minute per IP). Bulk calls and the paid-only tools answer with the x402 PaymentRequired object (price, network, payTo and the HTTP endpoint) as an error result; an x402-capable client signs it and repeats the tool call with the signed payload in params._meta["x402/payment"], following the x402 MCP transport. The server never asks for or accepts private keys.
{
"mcpServers": {
"adam-hale-tools": {
"url": "https://tools.adamhaleworks.workers.dev/mcp"
}
}
}
| MCP tool | Free | Paid tier | Price |
|---|---|---|---|
tech_stack_lookup | 1 domain | 2-3 domains | $0.005 |
seo_meta_tags_check | 1 URL (when the free tool is live) | up to 3 URLs | $0.004 |
url_status_check | 1 URL (when the free tool is live) | up to 10 URLs | $0.003 |
sitemap_urls | 2,000 URLs, 12 files | bulk=true: 5,000 URLs, 20 files | $0.004 |
rss_to_json | 1 feed | up to 5 feeds | $0.003 |
ted_tender_search | 25 newest notices | bulk=true or page: 100 per page, pages 1-50 | $0.002 |
page_to_markdown | no | up to 3 URLs | $0.002 |
domain_intel | no | up to 3 domains | $0.003 |
robots_txt_check | no | up to 5 URLs × 15 agents | $0.001 |
document_to_markdown | no | 1 file up to 10 MB | $0.004 |
transcribe_short_audio | no | 1 file up to 2 MB, 20 min | $0.01 |
website_screenshot | no | 1 page, viewport | $0.01 |
npx @modelcontextprotocol/inspector --cli https://tools.adamhaleworks.workers.dev/mcp --transport http --method tools/call --tool-name tech_stack_lookup --tool-arg 'domains=["wordpress.org"]'FAQ
Do I need an account or API key?
No. The payment is the authentication: each call carries a signed USDC authorization in the PAYMENT-SIGNATURE header, and nothing else is needed.
What happens if a lookup fails?
Invalid input is refused with HTTP 400 before any payment is asked for. If every item in a call fails (for example the site disallows it in robots.txt or the name points to a private address), the call returns an error and the payment is not settled. If at least one item succeeds, the flat price is charged and failed items carry their error.
Who pays the gas?
Nobody on your side: the client signs an EIP-3009 transferWithAuthorization for the exact price, and the facilitator submits it on Base and pays the gas. Your wallet only needs USDC.
Are there rate limits?
The 10-per-minute visitor limit of the free tools does not apply. To stay polite to the sites being checked, each target host can still be looked up about 20 times a minute across all callers, and each IP address can make about 60 paid calls a minute. Over a limit you get HTTP 429 before paying.
Is there a test network?
The live service charges on Base mainnet only. The code supports Base Sepolia for development, and an unpaid request always shows the current terms in the 402 challenge, so check it before paying.