{"version":2,"resources":[{"resource":"POST /v1/diff","description":"JSON structural diff — compare two JSON values and get a precise list of every difference.\n\nPURPOSE: Deep-compare any two JSON values (objects, arrays, strings, numbers, booleans, null) and return a machine-readable changeset. Ideal for change detection, audit trails, configuration drift checks, comparing API responses, building changelogs, or diffing LLM tool call arguments.\n\nREQUEST FORMAT:\n  Method: POST\n  Content-Type: application/json\n  Body: {\"left\": <original structured JSON>, \"right\": <modified structured JSON>}\n  Both left and right are required. Each must be a JSON object or array. Null, numbers, strings, and booleans are rejected with a 422 error.\n\nOPTIONAL PARAMETERS (in body):\n  options.includeUnchanged (boolean, default false): When true, the stats.unchanged counter includes paths that are identical in both inputs.\n  options.maxDepth (integer 1–256, default 64): Maximum nesting depth to traverse. Beyond this depth, values are compared by reference equality only. Set lower for very deeply nested structures to limit output size.\n\nRESPONSE FORMAT (200 OK, application/json):\n  {\n    \"ok\": true,\n    \"stats\": {\n      \"added\": <number of new paths in right>,\n      \"removed\": <number of paths missing from right>,\n      \"changed\": <number of paths with different values>,\n      \"unchanged\": <count, non-zero only when includeUnchanged is true>,\n      \"processingTimeMs\": <float, typically under 1ms>\n    },\n    \"diff\": [\n      {\"op\": \"add\", \"path\": \"/newField\", \"value\": \"new\"},\n      {\"op\": \"remove\", \"path\": \"/oldField\", \"value\": \"was here\"},\n      {\"op\": \"replace\", \"path\": \"/name\", \"oldValue\": \"Alice\", \"newValue\": \"Bob\"}\n    ]\n  }\n  Each diff entry has: op (one of 'add', 'remove', 'replace'), path (RFC 6901 JSON Pointer, e.g. '/users/0/email'), and value fields.\n\nERROR RESPONSES (all errors use application/problem+json per RFC 9457):\n  400 Bad Request — body is not valid JSON\n  402 Payment Required — x402 payment not provided or invalid\n  422 Unprocessable Entity — missing 'left'/'right', invalid top-level types, or invalid option types\n\nLIMITS: No explicit size limit on the JSON body, but Cloudflare Workers enforce a maximum request size. Typical latency: <1ms for small objects, <50ms for very large structures.\n\nCOST: $0.003 USD per call, paid via x402 protocol (USDC on Base network, eip155:8453).","accepts":[{"scheme":"exact","network":"eip155:8453","price":"$0.003","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","payTo":"0x7e67204eea076e8803b5753e5441ba0e62be13a4","maxTimeoutSeconds":60},{"scheme":"exact","network":"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp","price":"$0.003","asset":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v","payTo":"GXTcDuC5mPnmbWSza92FcX9zSmp8QuPpFh6n1ad9c9zM","maxTimeoutSeconds":60}]},{"resource":"POST /v1/image/exif-summary","description":"EXIF metadata extraction — read all camera, GPS, and image metadata from a JPEG photo.\n\nPURPOSE: Parse the EXIF APP1 segment of a JPEG image and return structured metadata as JSON. Extracts camera make/model, GPS coordinates (latitude, longitude, altitude), timestamps (DateTimeOriginal, DateTimeDigitized, DateTime), exposure settings (aperture/f-number, shutter speed/exposure time, ISO), focal length, image dimensions (width x height in pixels), orientation flag (1-8), and software tag. Only JPEG images with embedded EXIF data are supported; PNG, GIF, WebP, and HEIF are not supported.\n\nREQUEST FORMAT — two upload modes:\n  Mode 1 — Raw binary body:\n    Method: POST\n    Content-Type: image/jpeg\n    Body: raw JPEG bytes\n  Mode 2 — Multipart form:\n    Method: POST\n    Content-Type: multipart/form-data\n    Field name: 'file' (must be exactly this name)\n    Field value: JPEG binary\n\nRESPONSE FORMAT (200 OK, application/json):\n  {\n    \"ok\": true,\n    \"processingTimeMs\": 1.2,\n    \"exif\": {\n      \"make\": \"Apple\",\n      \"model\": \"iPhone 15 Pro\",\n      \"dateTimeOriginal\": \"2024:06:15 14:23:01\",\n      \"gps\": {\"latitude\": 37.7749, \"longitude\": -122.4194, \"altitude\": 12.5},\n      \"fNumber\": 1.78,\n      \"exposureTime\": \"1/120\",\n      \"isoSpeedRatings\": 64,\n      \"focalLength\": 6.86,\n      \"orientation\": 1,\n      \"imageWidth\": 4032,\n      \"imageHeight\": 3024,\n      \"software\": \"17.5.1\"\n    }\n  }\n  GPS coords are decimal degrees (positive = N/E, negative = S/W). gps is null if no GPS IFD is present.\n\nERROR RESPONSES (all errors use application/problem+json per RFC 9457):\n  400 Bad Request — upload too small to be a valid image (<4 bytes), or multipart missing 'file' field\n  402 Payment Required — x402 payment not provided or invalid\n  413 Payload Too Large — upload exceeds the 5 MB limit (5,242,880 bytes)\n  415 Unsupported Media Type — no EXIF data found (not a JPEG, or JPEG has no EXIF segment)\n\nLIMITS: Maximum upload size: 5 MB (5,242,880 bytes). Only JPEG format supported. Images without EXIF return 415. Typical latency: 1-5ms.\n\nCOST: $0.003 USD per call, paid via x402 protocol (USDC on Base network, eip155:8453).","accepts":[{"scheme":"exact","network":"eip155:8453","price":"$0.003","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","payTo":"0x7e67204eea076e8803b5753e5441ba0e62be13a4","maxTimeoutSeconds":60},{"scheme":"exact","network":"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp","price":"$0.003","asset":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v","payTo":"GXTcDuC5mPnmbWSza92FcX9zSmp8QuPpFh6n1ad9c9zM","maxTimeoutSeconds":60}]},{"resource":"POST /v1/image/scrub-metadata","description":"Image metadata scrubber — permanently remove all EXIF, XMP, and IPTC metadata from JPEG or PNG images.\n\nPURPOSE: Strip all embedded metadata from an image file and return the cleaned image as raw binary bytes. Removes EXIF (camera make/model, GPS location, timestamps, lens info, orientation), XMP (Adobe edit history, rights, color profiles), IPTC (captions, keywords, copyright, contact details), ICC color profiles, and all APP0-APP15 marker segments for JPEG. For PNG, strips all ancillary chunks (tEXt, iTXt, zTXt, eXIf, iCCP, etc.), keeping only critical chunks (IHDR, PLTE, IDAT, IEND). The output is pixel-identical to the input — only metadata blobs are removed, image data is never re-encoded or modified.\n\nREQUEST FORMAT — two upload modes:\n  Mode 1 — Raw binary body:\n    Method: POST\n    Content-Type: image/jpeg OR image/png\n    Body: raw image bytes\n  Mode 2 — Multipart form:\n    Method: POST\n    Content-Type: multipart/form-data\n    Field name: 'file' (must be exactly this name)\n    Field value: JPEG or PNG binary\n\nRESPONSE FORMAT (200 OK): Raw binary image bytes.\n  Content-Type: image/jpeg (if input was JPEG) or image/png (if input was PNG).\n  The response body is NOT JSON — it is the cleaned image file ready to save or forward.\n  If no metadata was present, the image is returned unchanged.\n\nERROR RESPONSES (all errors use application/problem+json per RFC 9457):\n  400 Bad Request — upload too small (<8 bytes for valid image), or multipart missing 'file' field\n  402 Payment Required — x402 payment not provided or invalid\n  413 Payload Too Large — upload exceeds the 5 MB limit (5,242,880 bytes)\n  415 Unsupported Media Type — file is not a valid JPEG (missing FFD8 SOI) or PNG (missing 89504E47 header)\n\nLIMITS: Maximum upload size: 5 MB (5,242,880 bytes). Only JPEG and PNG formats supported — not GIF, WebP, HEIF, BMP, TIFF, or AVIF. Typical latency: 2-10ms.\n\nIMPORTANT: The response is raw binary, NOT JSON. Parse the Content-Type header to determine the image format. Write the response body bytes directly to a file to save.\n\nUSE CASES: Privacy protection before publishing photos (strip GPS that reveals home/work), GDPR compliance for user-uploaded images, removing editing history metadata, sanitizing images before feeding to vision models, stripping watermark metadata from stock photos.\n\nCOST: $0.003 USD per call, paid via x402 protocol (USDC on Base network, eip155:8453).","accepts":[{"scheme":"exact","network":"eip155:8453","price":"$0.003","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","payTo":"0x7e67204eea076e8803b5753e5441ba0e62be13a4","maxTimeoutSeconds":60},{"scheme":"exact","network":"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp","price":"$0.003","asset":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v","payTo":"GXTcDuC5mPnmbWSza92FcX9zSmp8QuPpFh6n1ad9c9zM","maxTimeoutSeconds":60}]},{"resource":"POST /v1/html/to-markdown","description":"HTML to Markdown converter — transform an HTML string into clean, readable Markdown.\n\nPURPOSE: Convert raw HTML to Markdown for use in LLM context windows, document storage, downstream text processing, or anywhere you need clean readable text from HTML. The converter handles inline formatting (bold, italic, strikethrough, inline code, links, images, line breaks), block elements (paragraphs, headings h1-h6, blockquotes, horizontal rules, preformatted/code blocks with fenced ``` syntax), ordered and unordered lists with nesting, and GitHub Flavored Markdown tables (GFM pipe syntax). Non-content elements are stripped entirely: script, style, iframe, noscript, svg, canvas, template, object, embed. Block containers (div, section, article, aside, header, footer, nav, form) are collapsed to whitespace, preserving their inner text. HTML entities are decoded (including &amp; &lt; &gt; &nbsp; &mdash; &hellip; and numeric/hex entities).\n\nREQUEST FORMAT — two modes:\n  Mode 1 — JSON body:\n    Method: POST\n    Content-Type: application/json\n    Body: {\"html\": \"<h1>Hello</h1><p>World</p>\"}\n    The 'html' field is required and must be a non-empty string.\n  Mode 2 — Raw HTML body:\n    Method: POST\n    Content-Type: text/html (or any non-JSON content type)\n    Body: raw HTML string bytes\n\nRESPONSE FORMAT (200 OK, application/json):\n  {\n    \"ok\": true,\n    \"processingTimeMs\": 0.3,\n    \"charsBefore\": 4200,\n    \"charsAfter\": 1150,\n    \"markdown\": \"# Hello\\n\\nWorld\"\n  }\n  charsBefore = character count of input HTML, charsAfter = character count of output Markdown. Use these to measure compression ratio.\n\nERROR RESPONSES (all errors use application/problem+json per RFC 9457):\n  400 Bad Request — body is empty, or 'html' field is missing/empty in JSON mode, or body is not valid JSON when Content-Type is application/json\n  402 Payment Required — x402 payment not provided or invalid\n  413 Payload Too Large — input exceeds the 5 MB limit (5,242,880 bytes)\n  422 Unprocessable Entity — JSON body present but missing required 'html' field\n\nLIMITS: Maximum input size: 5 MB (5,242,880 bytes). Designed for <10ms on typical web pages (up to ~500 KB HTML). No external fetching — you must provide the HTML string directly. Use /v1/html/fetch-markdown if you need to fetch a URL first.\n\nCOST: $0.003 USD per call, paid via x402 protocol (USDC on Base network, eip155:8453).","accepts":[{"scheme":"exact","network":"eip155:8453","price":"$0.003","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","payTo":"0x7e67204eea076e8803b5753e5441ba0e62be13a4","maxTimeoutSeconds":60},{"scheme":"exact","network":"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp","price":"$0.003","asset":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v","payTo":"GXTcDuC5mPnmbWSza92FcX9zSmp8QuPpFh6n1ad9c9zM","maxTimeoutSeconds":60}]},{"resource":"POST /v1/html/fetch-markdown","description":"URL to Markdown fetcher — download a web page and convert its HTML to clean Markdown in one step.\n\nPURPOSE: Fetch a remote URL, download the HTML response, strip non-content elements (scripts, styles, nav, ads), and convert to clean Markdown. Follows HTTP redirects automatically. Returns both the Markdown text and the final resolved URL after redirects. Ideal for reading web articles, documentation pages, blog posts, or any public HTML page and getting clean text suitable for LLM context windows, RAG pipelines, or document storage.\n\nREQUEST FORMAT:\n  Method: POST\n  Content-Type: application/json\n  Body: {\"url\": \"https://quotes.toscrape.com/article\"}\n  The 'url' field is required and must be a non-empty string containing a valid http or https URL.\n\nURL RESTRICTIONS (SSRF protection — these will return 400):\n  Blocked: Private/RFC-1918 IPs (10.x.x.x, 172.16-31.x.x, 192.168.x.x), loopback (127.x.x.x, localhost, [::1], 0.0.0.0), link-local (169.254.x.x, fe80::), cloud metadata (169.254.169.254, metadata.google.internal), internal hostnames (*.internal, *.local, *.localhost), URLs with embedded credentials (user:pass@host), non-HTTP protocols (ftp://, file://, data:, javascript:).\n  Allowed: Only http:// and https:// with public hostnames.\n\nRESPONSE FORMAT (200 OK, application/json):\n  {\n    \"ok\": true,\n    \"processingTimeMs\": 145.2,\n    \"sourceUrl\": \"https://quotes.toscrape.com/article\",\n    \"charsBefore\": 58000,\n    \"charsAfter\": 4200,\n    \"markdown\": \"# Article Title\\n\\nContent...\"\n  }\n  sourceUrl reflects the final URL after any redirects (may differ from the requested URL).\n\nERROR RESPONSES (all errors use application/problem+json per RFC 9457):\n  400 Bad Request — invalid URL format, URL points to private/blocked address, remote server returned non-2xx, remote fetch timed out after 5 seconds, or 'url' field missing/empty\n  402 Payment Required — x402 payment not provided or invalid\n  413 Payload Too Large — remote response exceeds the 2 MB download limit (2,097,152 bytes)\n  422 Unprocessable Entity — JSON body present but missing required 'url' field\n\nLIMITS: Remote fetch timeout: 5 seconds. Maximum download size: 2 MB (2,097,152 bytes). Sends Accept: text/html,application/xhtml+xml. Follows redirects. Does NOT execute JavaScript — this is an HTML-only fetch, not a headless browser.\n\nCOST: $0.003 USD per call, paid via x402 protocol (USDC on Base network, eip155:8453).","accepts":[{"scheme":"exact","network":"eip155:8453","price":"$0.003","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","payTo":"0x7e67204eea076e8803b5753e5441ba0e62be13a4","maxTimeoutSeconds":120},{"scheme":"exact","network":"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp","price":"$0.003","asset":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v","payTo":"GXTcDuC5mPnmbWSza92FcX9zSmp8QuPpFh6n1ad9c9zM","maxTimeoutSeconds":120}]},{"resource":"POST /v1/text/fetch-content","description":"Universal URL content fetcher — download any URL and return its text content with automatic format detection.\n\nPURPOSE: Fetch a remote URL, detect the content format from the response Content-Type header (falling back to content sniffing), and return clean text. Supports four formats: HTML (stripped of tags and converted to Markdown), JSON (recursively extracts human-readable text from content fields like title, body, content, description, summary, excerpt, headline, message while skipping metadata fields like id, url, timestamp, type), Markdown (returned as-is), and plain text (returned as-is). Use when you need to read content from any URL without knowing the format in advance.\n\nREQUEST FORMAT:\n  Method: POST\n  Content-Type: application/json\n  Body: {\"url\": \"https://quotes.toscrape.com/readme.md\"}\n  The 'url' field is required and must be a non-empty string containing a valid http or https URL.\n\nURL RESTRICTIONS (SSRF protection — these will return 400):\n  Blocked: Private/RFC-1918 IPs (10.x.x.x, 172.16-31.x.x, 192.168.x.x), loopback (127.x.x.x, localhost, [::1], 0.0.0.0), link-local (169.254.x.x, fe80::), cloud metadata (169.254.169.254, metadata.google.internal), internal hostnames (*.internal, *.local, *.localhost), URLs with embedded credentials (user:pass@host), non-HTTP protocols (ftp://, file://, data:, javascript:).\n  Allowed: Only http:// and https:// with public hostnames.\n\nRESPONSE FORMAT (200 OK, application/json):\n  {\n    \"ok\": true,\n    \"processingTimeMs\": 88.4,\n    \"sourceUrl\": \"https://quotes.toscrape.com/readme.md\",\n    \"contentType\": \"application/json\",\n    \"detectedFormat\": \"markdown\",\n    \"charsBefore\": 3200,\n    \"charsAfter\": 3200,\n    \"content\": \"{\\\"title\\\":\\\"README\\\",...}\",\n    \"text\": \"# README\\n\\nProject documentation...\",\n    \"markdown\": \"# README\\n\\nProject documentation...\"\n  }\n  detectedFormat is one of: 'html', 'json', 'markdown', 'text'.\n  sourceUrl reflects the final URL after any redirects.\n  content is the decoded remote response body as text.\n  text is the normalized readable text representation used for consumers that want extracted content.\n  markdown is a backward-compatible alias of text.\n\nERROR RESPONSES (all errors use application/problem+json per RFC 9457):\n  400 Bad Request — invalid URL, URL points to private/blocked address, remote server returned non-2xx, remote fetch timed out after 5 seconds, or 'url' field missing/empty\n  402 Payment Required — x402 payment not provided or invalid\n  413 Payload Too Large — remote response exceeds the 2 MB download limit (2,097,152 bytes)\n  422 Unprocessable Entity — JSON body present but missing required 'url' field\n\nLIMITS: Remote fetch timeout: 5 seconds. Maximum download size: 2 MB (2,097,152 bytes). Follows redirects. Does NOT execute JavaScript. Sends Accept: text/markdown,text/plain,application/json,*/*.\n\nCOMPARISON WITH OTHER ENDPOINTS:\n  /v1/html/to-markdown — use when you already have HTML in memory (no fetching).\n  /v1/html/fetch-markdown — use when you know the URL serves HTML and want Markdown.\n  /v1/text/fetch-content — use when you don't know the format and want the best text extraction automatically.\n  /v1/url/metadata — use when you only need metadata (title, OG tags, etc.) not the full page content.\n\nCOST: $0.003 USD per call, paid via x402 protocol (USDC on Base network, eip155:8453).","accepts":[{"scheme":"exact","network":"eip155:8453","price":"$0.003","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","payTo":"0x7e67204eea076e8803b5753e5441ba0e62be13a4","maxTimeoutSeconds":120},{"scheme":"exact","network":"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp","price":"$0.003","asset":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v","payTo":"GXTcDuC5mPnmbWSza92FcX9zSmp8QuPpFh6n1ad9c9zM","maxTimeoutSeconds":120}]},{"resource":"POST /v1/url/metadata","description":"URL metadata extractor — fetch a web page and extract structured metadata from its HTML head.\n\nPURPOSE: Download a URL's HTML and parse all metadata from the <head> section, returning structured JSON without the full page content. Extracts title (<title> tag, with og:title fallback), description (<meta name='description'>, with og:description fallback), canonical URL (<link rel='canonical'>), language (<html lang>), favicon (resolved absolute URL from <link rel='icon'>, <link rel='shortcut icon'>, or <link rel='apple-touch-icon'>), RSS/Atom feed links (<link rel='alternate' type='application/rss+xml' or application/atom+xml>), Open Graph properties (all og:* meta tags: title, description, image, image:width, image:height, type, url, site_name, locale, video, audio, etc.), Twitter Card properties (all twitter:* meta tags: card, title, description, image, site, creator, player, etc.), and standard meta tags (author, keywords, robots, generator, theme-color, application-name).\n\nREQUEST FORMAT:\n  Method: POST\n  Content-Type: application/json\n  Body: {\"url\": \"https://quotes.toscrape.com\"}\n  The 'url' field is required and must be a non-empty string containing a valid http or https URL.\n\nURL RESTRICTIONS (SSRF protection — these will return 400):\n  Blocked: Private/RFC-1918 IPs (10.x.x.x, 172.16-31.x.x, 192.168.x.x), loopback (127.x.x.x, localhost, [::1], 0.0.0.0), link-local (169.254.x.x, fe80::), cloud metadata (169.254.169.254, metadata.google.internal), internal hostnames (*.internal, *.local, *.localhost), URLs with embedded credentials (user:pass@host), non-HTTP protocols (ftp://, file://, data:, javascript:).\n  Allowed: Only http:// and https:// with public hostnames.\n\nRESPONSE FORMAT (200 OK, application/json):\n  {\n    \"ok\": true,\n    \"processingTimeMs\": 95.0,\n    \"sourceUrl\": \"https://quotes.toscrape.com\",\n    \"metadata\": {\n      \"title\": \"Example Domain\",\n      \"description\": \"This domain is for illustrative examples.\",\n      \"canonical\": \"https://quotes.toscrape.com\",\n      \"language\": \"en\",\n      \"favicon\": \"https://quotes.toscrape.com/favicon.ico\",\n      \"feeds\": [{\"type\": \"application/rss+xml\", \"href\": \"https://quotes.toscrape.com/feed\", \"title\": \"Blog\"}],\n      \"openGraph\": {\"title\": \"Example\", \"image\": \"https://quotes.toscrape.com/og.png\", \"type\": \"website\"},\n      \"twitterCard\": {\"card\": \"summary_large_image\", \"site\": \"@example\"},\n      \"meta\": {\"author\": \"Jane Doe\", \"keywords\": \"example, demo\", \"robots\": \"index, follow\"}\n    }\n  }\n  All metadata fields (title, description, canonical, language, favicon) are null when not present in the HTML. openGraph, twitterCard, and meta are empty objects {} when no matching tags are found. feeds is an empty array [] when no feed links are found.\n\nERROR RESPONSES (all errors use application/problem+json per RFC 9457):\n  400 Bad Request — invalid URL, URL points to private/blocked address, remote server returned non-2xx, remote fetch timed out after 5 seconds, or 'url' field missing/empty\n  402 Payment Required — x402 payment not provided or invalid\n  413 Payload Too Large — remote response exceeds the 2 MB download limit (2,097,152 bytes)\n  422 Unprocessable Entity — JSON body present but missing required 'url' field\n\nLIMITS: Remote fetch timeout: 5 seconds. Maximum download size: 2 MB (2,097,152 bytes). Follows redirects. Sends Accept: text/html,application/xhtml+xml. Does NOT execute JavaScript — only parses the raw HTML response.\n\nUSE CASES: Generating social sharing preview cards, checking Open Graph and Twitter Card setup for SEO tools, discovering RSS feed URLs, extracting canonical URLs for deduplication, building link unfurler/preview tools, getting page metadata for search indexing.\n\nCOST: $0.003 USD per call, paid via x402 protocol (USDC on Base network, eip155:8453).","accepts":[{"scheme":"exact","network":"eip155:8453","price":"$0.003","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","payTo":"0x7e67204eea076e8803b5753e5441ba0e62be13a4","maxTimeoutSeconds":120},{"scheme":"exact","network":"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp","price":"$0.003","asset":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v","payTo":"GXTcDuC5mPnmbWSza92FcX9zSmp8QuPpFh6n1ad9c9zM","maxTimeoutSeconds":120}]},{"resource":"POST /v1/utilities/count-tokens","description":"Token counter — count the number of tokens in a text string for any major LLM tokenizer.\n\nPURPOSE: Determine the exact or estimated token count of a text string using a specified tokenizer encoding. Use before sending text to an LLM to check context window fit, estimate API cost, enforce token budgets in agent pipelines, or split documents at token boundaries.\n\nSUPPORTED ENCODINGS (pass via 'encoding' field):\n  'cl100k_base' — GPT-4, GPT-4-turbo, GPT-3.5-turbo, text-embedding-ada-002. EXACT count via WASM-compiled BPE tokenizer (tiktoken). Default if encoding is omitted.\n  'o200k_base' — GPT-4o, GPT-4o-mini. EXACT count via WASM-compiled BPE tokenizer.\n  'claude' — Anthropic Claude 3, Claude 3.5, Claude 4 models. ESTIMATED count: ceil(character_count / 3.5).\n  'gemini' — Google Gemini 1.5, Gemini 2 models. ESTIMATED count: ceil(character_count / 4).\n\nIMAGE TOKEN ESTIMATION:\n  Set content_type='image' when the text field contains a base64-encoded image. Uses tile-based estimation: ceil(raw_bytes / 750) where raw_bytes = base64_length * 0.75. Auto-detection: base64 strings starting with /9j/ (JPEG), iVBOR (PNG), or R0lGO (GIF) are automatically treated as images even if content_type is not set.\n\nREQUEST FORMAT:\n  Method: POST\n  Content-Type: application/json\n  Body: {\"text\": \"Your text here\", \"encoding\": \"cl100k_base\"}\n  Required fields: 'text' (non-empty string).\n  Optional fields: 'encoding' (string, default 'cl100k_base'), 'content_type' (string: 'text' or 'image', default 'text').\n\nRESPONSE FORMAT (200 OK, application/json):\n  {\n    \"ok\": true,\n    \"processingTimeMs\": 1.23,\n    \"encoding\": \"cl100k_base\",\n    \"method\": \"exact\",\n    \"tokenCount\": 4,\n    \"characterCount\": 13,\n    \"utf8Sanitized\": false\n  }\n  method is 'exact' for cl100k_base and o200k_base (real BPE tokenization), or 'estimate' for claude, gemini, and image content.\n  utf8Sanitized is true if the input contained invalid UTF-8 byte sequences that were cleaned before counting (characterCount reflects the sanitized length).\n\nERROR RESPONSES (all errors use application/problem+json per RFC 9457):\n  400 Bad Request — 'text' field is missing, empty, or not a string; invalid encoding name; body is not valid JSON\n  402 Payment Required — x402 payment not provided or invalid\n  413 Payload Too Large — text input exceeds the 50 MB limit (52,428,800 bytes)\n  422 Unprocessable Entity — JSON body present but missing required 'text' field\n\nLIMITS: Maximum text size: 50 MB (52,428,800 bytes). Both the Content-Length header and the actual text byte length are checked against this limit. Typical latency: <2ms for estimates (claude, gemini, image), 5-50ms for exact BPE tokenization (cl100k_base, o200k_base) depending on text length.\n\nCOMMON MISTAKES:\n  Sending encoding='gpt-4' — use 'cl100k_base' or 'o200k_base' instead (these are tokenizer names, not model names).\n  Sending an empty text field — will return 400.\n  Sending a number or array as text — must be a string.\n\nCOST: $0.003 USD per call, paid via x402 protocol (USDC on Base network, eip155:8453).","accepts":[{"scheme":"exact","network":"eip155:8453","price":"$0.003","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","payTo":"0x7e67204eea076e8803b5753e5441ba0e62be13a4","maxTimeoutSeconds":60},{"scheme":"exact","network":"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp","price":"$0.003","asset":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v","payTo":"GXTcDuC5mPnmbWSza92FcX9zSmp8QuPpFh6n1ad9c9zM","maxTimeoutSeconds":60}]}]}