{"openapi":"3.1.0","info":{"title":"Agent Ready API","version":"1.0.0","contact":{"name":"Agent Ready","url":"https://agent-ready.dev/about","email":"hello@agent-ready.dev"},"description":"Programmatic access to agent-ready.dev scans. Available to Pro subscribers. Auth via `Authorization: Bearer ar_live_...` issued from the dashboard.\n\n## Versioning and deprecation policy\n\nThe REST API uses URL-based versioning. Stable endpoints live under `/api/v1`; breaking changes ship behind a new version prefix (`/api/v2`, …) and never on the existing one. When an endpoint is scheduled for removal we set [`Sunset`](https://datatracker.ietf.org/doc/html/rfc8594) and [`Deprecation`](https://datatracker.ietf.org/doc/html/rfc9745) response headers with the planned removal date, mark the operation `deprecated: true` in this spec, and announce the deprecation in the changelog at least 90 days before removal. No `/api/v1` endpoint is currently deprecated."},"servers":[{"url":"https://agent-ready.dev"}],"security":[{"ApiKey":[]}],"components":{"securitySchemes":{"ApiKey":{"type":"http","scheme":"bearer","bearerFormat":"ar_live_<prefix>_<secret>","description":"API key issued from /dashboard/api-keys. Pro subscription required."}},"schemas":{"AskRequest":{"type":"object","properties":{"query":{"anyOf":[{"type":"string","minLength":1,"maxLength":2000},{"type":"object","properties":{"q":{"type":"string","minLength":1,"maxLength":2000},"itemType":{"type":"string","enum":["methodology","checks","specs","llms-txt","check","page","any"],"description":"Optional filter mapping to an Agent Ready corpus type. 'any' (default) searches everything."},"site":{"type":"string"}},"required":["q"]}],"example":"how is the agent readability score calculated?"},"mode":{"type":"string","enum":["list","summarize","generate"]},"streaming":{"anyOf":[{"type":"boolean"},{"type":"string"}]},"itemType":{"type":"string","enum":["methodology","checks","specs","llms-txt","check","page","any"],"description":"Optional filter mapping to an Agent Ready corpus type. 'any' (default) searches everything."},"site":{"type":"string"},"query_id":{"type":"string"},"prev":{"type":"string"},"decontextualized_query":{"type":"string"},"prefer":{"type":"object","properties":{"streaming":{"type":"boolean"},"format":{"type":"string","enum":["json"]},"mode":{"type":"string","enum":["list","summarize"]},"language":{"type":"string"}}},"context":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["user","assistant"]},"content":{"type":"string"}},"required":["role","content"]}},"meta":{"type":"object","properties":{"version":{"type":"string"},"session":{"type":"string"},"user":{"type":"string"}}}},"required":["query"],"description":"NLWeb /ask request. `query` is the natural-language string; flat `mode`/`streaming` follow the github.com/nlweb-ai/NLWeb REST API. The object form `{ query: { q } }` plus a `prefer` envelope is also accepted."},"SchemaObject":{"type":"object","properties":{"@context":{"type":"string","enum":["https://schema.org"]},"@type":{"type":"string","enum":["Article","TechArticle","WebPage"]},"name":{"type":"string"},"url":{"type":"string"},"description":{"type":"string"}},"required":["@context","@type","name","url"],"description":"Schema.org JSON-LD for a result."},"AskResult":{"type":"object","properties":{"url":{"type":"string"},"name":{"type":"string"},"site":{"type":"string"},"score":{"type":"number","description":"Relevance score (BM25)."},"description":{"type":"string"},"schema_object":{"$ref":"#/components/schemas/SchemaObject"}},"required":["url","name","site","score","description","schema_object"],"description":"An NLWeb result object."},"AskMeta":{"type":"object","properties":{"response_type":{"type":"string","enum":["answer","failure","elicitation","promise"]},"version":{"type":"string","enum":["0.1"]},"mode":{"type":"string","enum":["list","summarize"]}},"required":["response_type","version","mode"],"description":"NLWeb response envelope metadata."},"AskAnswer":{"type":"object","properties":{"_meta":{"$ref":"#/components/schemas/AskMeta"},"query_id":{"type":"string"},"site":{"type":"string"},"mode":{"type":"string","enum":["list","summarize"]},"query":{"type":"string"},"results":{"type":"array","items":{"$ref":"#/components/schemas/AskResult"}},"summary":{"type":"string","description":"Present when mode is 'summarize'."}},"required":["_meta","query_id","site","mode","query","results"],"description":"Successful NLWeb answer."},"AskFailure":{"type":"object","properties":{"_meta":{"$ref":"#/components/schemas/AskMeta"},"error":{"type":"object","properties":{"code":{"type":"string","enum":["NO_RESULTS","INVALID_QUERY","RATE_LIMITED","TIMEOUT","INTERNAL"]},"message":{"type":"string"}},"required":["code","message"]}},"required":["_meta","error"],"description":"NLWeb failure envelope."},"AskResponse":{"anyOf":[{"$ref":"#/components/schemas/AskAnswer"},{"$ref":"#/components/schemas/AskFailure"}],"description":"Either an answer or a failure."},"CheckResult":{"type":"object","properties":{"checkId":{"type":"string","example":"S1"},"name":{"type":"string","example":"llms.txt exists"},"status":{"type":"string","enum":["pass","fail","warn","error"],"description":"Outcome of a single check."},"message":{"type":"string"},"howToFix":{"type":["string","null"]},"details":{"type":"object","additionalProperties":{}}},"required":["checkId","name","status","message","howToFix","details"],"description":"Result of a single check."},"PageResult":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"checks":{"type":"array","items":{"$ref":"#/components/schemas/CheckResult"}}},"required":["url","checks"],"description":"Per-page check results."},"Scan":{"type":"object","properties":{"id":{"type":"string","example":"V1StGXR8_Z"},"rootUrl":{"type":"string","format":"uri"},"status":{"type":"string","enum":["running","completed","failed"],"description":"Lifecycle state of a scan. Poll until status is 'completed' or 'failed'."},"createdAt":{"type":"string","format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"pagesDiscovered":{"type":"integer","minimum":0},"pagesScanned":{"type":"integer","minimum":0},"vercelScore":{"type":"integer","minimum":0,"maximum":100},"vercelRating":{"type":"string","enum":["excellent","good","fair","needs_improvement"],"description":"Coarse rating bucket derived from the Vercel Agent Readability score."},"llmstxtScore":{"type":"integer","minimum":0,"maximum":100},"percentile":{"type":["integer","null"],"minimum":0,"maximum":100,"description":"Corpus percentile: share of scanned sites this score beats. Null when the corpus is too small to quote."},"corpusTotal":{"type":["integer","null"],"minimum":0,"description":"Number of sites the percentile is measured against. Null with percentile."},"siteChecks":{"type":"array","items":{"$ref":"#/components/schemas/CheckResult"}},"llmstxtChecks":{"type":"array","items":{"$ref":"#/components/schemas/CheckResult"}},"pageResults":{"type":"array","items":{"$ref":"#/components/schemas/PageResult"}},"shareToken":{"type":"string"}},"required":["id","rootUrl","status","createdAt","completedAt","pagesDiscovered","pagesScanned","vercelScore","vercelRating","llmstxtScore","percentile","corpusTotal","siteChecks","llmstxtChecks","pageResults","shareToken"],"description":"Full scan result. Same shape returned for sync, async, and cached reads."},"ScanSummary":{"type":"object","properties":{"id":{"type":"string"},"shareToken":{"type":"string"},"domain":{"type":"string"},"rootUrl":{"type":"string","format":"uri"},"vercelScore":{"type":["integer","null"]},"vercelRating":{"type":["string","null"],"enum":["excellent","good","fair","needs_improvement",null],"description":"Coarse rating bucket derived from the Vercel Agent Readability score."},"llmstxtScore":{"type":["integer","null"]},"percentile":{"type":["integer","null"],"minimum":0,"maximum":100},"corpusTotal":{"type":["integer","null"],"minimum":0},"pagesScanned":{"type":["integer","null"]},"createdAt":{"type":"string","format":"date-time"}},"required":["id","shareToken","domain","rootUrl","vercelScore","vercelRating","llmstxtScore","percentile","corpusTotal","pagesScanned","createdAt"],"description":"Lightweight scan listing entry."},"StartScanRequest":{"type":"object","properties":{"url":{"type":"string","maxLength":2000,"format":"uri","example":"https://example.com"},"pageLimit":{"type":"integer","minimum":1,"maximum":2000}},"required":["url"],"description":"Body for POST /api/v1/scans."},"StartScanResponse":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["running","completed","failed"],"description":"Lifecycle state of a scan. Poll until status is 'completed' or 'failed'."},"url":{"type":"string","format":"uri"},"pollUrl":{"type":"string"}},"required":["id","status","url","pollUrl"],"description":"Async-job acknowledgement returned with 202."},"ScanListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ScanSummary"}},"nextCursor":{"type":"string"}},"required":["data"],"description":"Paginated list of scans owned by the API key."},"McpScan":{"type":"object","properties":{"id":{"type":"string","example":"bUqzgS67CE"},"shareToken":{"type":"string"},"endpoint":{"type":"string","format":"uri","example":"https://mcp.example.com/mcp"},"host":{"type":"string","example":"mcp.example.com"},"status":{"type":"string","enum":["completed","failed"]},"mcpScore":{"type":"integer","minimum":0,"maximum":100},"mcpRating":{"type":"string","enum":["excellent","good","fair","needs_improvement"],"description":"Coarse rating bucket derived from the Vercel Agent Readability score."},"serverName":{"type":["string","null"]},"serverVersion":{"type":["string","null"]},"toolCount":{"type":["integer","null"]},"resourceCount":{"type":["integer","null"]},"promptCount":{"type":["integer","null"]},"checks":{"type":"array","items":{"$ref":"#/components/schemas/CheckResult"}}},"required":["id","shareToken","endpoint","host","status","mcpScore","mcpRating","serverName","serverVersion","toolCount","resourceCount","promptCount","checks"],"description":"Full MCP server scan result: the M-series checks plus a weighted mcpScore (0–100). Independent of the site Vercel score."},"McpScanRequest":{"type":"object","properties":{"endpoint":{"type":"string","maxLength":2000,"format":"uri","example":"https://mcp.example.com/mcp"}},"required":["endpoint"],"description":"Body for POST /api/v1/scan/mcp. A remote http(s) MCP endpoint (Streamable HTTP)."},"McpScanResponse":{"type":"object","properties":{"scan":{"$ref":"#/components/schemas/McpScan"},"shareUrl":{"type":"string","example":"/mcp-server-scanner/bUqzgS67CE"}},"required":["scan","shareUrl"],"description":"Result of POST /api/v1/scan/mcp."},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"subscription_required"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"],"description":"Structured error envelope."}},"parameters":{}},"paths":{"/api/v1/scans":{"post":{"operationId":"startScan","summary":"Start a scan","description":"Queues an asynchronous scan and returns a 202 with the scan id. Poll GET /api/v1/scans/{id} until status is 'completed' or 'failed'.\n\nSupply an optional `Idempotency-Key` header to make retries safe: the first request runs the scan and any retry carrying the same key replays the original 202 (with `Idempotency-Replayed: true`) instead of starting a duplicate. Reusing a key with a different request body returns 422; a retry that arrives while the first is still in flight returns 409. Keys are retained for 24 hours.","tags":["Scans"],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Optional client-generated key (1-255 chars, [A-Za-z0-9_-]) that makes this POST safe to retry. The same key replays the original response.","example":"scan-2026-06-01-abc123"},"required":false,"description":"Optional client-generated key (1-255 chars, [A-Za-z0-9_-]) that makes this POST safe to retry. The same key replays the original response.","name":"Idempotency-Key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartScanRequest"}}}},"responses":{"202":{"description":"Scan queued. The `Location` response header carries the polling URL (per RFC 7231 §6.3.3); the same URL is also returned as `pollUrl` in the body.","headers":{"Location":{"description":"Absolute or root-relative URL to poll for the scan result.","schema":{"type":"string","example":"/api/v1/scans/V1StGXR8_Z"}},"Idempotency-Key":{"description":"Echoed back when the request carried an `Idempotency-Key`.","schema":{"type":"string","example":"scan-2026-06-01-abc123"}},"Idempotency-Replayed":{"description":"`true` when this response is a replay of an earlier request with the same `Idempotency-Key` (the scan was not started again).","schema":{"type":"string","example":"true"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartScanResponse"}}}},"400":{"description":"Invalid request body, URL, or Idempotency-Key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Subscription required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A request with the same `Idempotency-Key` is still in progress.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The `Idempotency-Key` was already used with a different request body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded. Response carries `Retry-After` (seconds) plus `X-RateLimit-Limit` and `X-RateLimit-Remaining`. Back off using exponential delay with jitter — see the Rate limits & retry section in the docs.","headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests permitted in the current window.","schema":{"type":"integer","example":10}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current window. `0` on a 429 response.","schema":{"type":"integer","example":0}},"Retry-After":{"description":"Seconds until a slot frees in the sliding window (RFC 7231 §7.1.3). Honour this before retrying.","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Service temporarily unavailable. Retry with backoff.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"operationId":"listScans","summary":"List recent scans","description":"Returns scans owned by the API key's user, newest first. Cursor-paginate by passing the `nextCursor` value from a previous response as the `cursor` query parameter on the next request; `nextCursor` is only returned when the page filled exactly to `limit`.","tags":["Scans"],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"date-time","description":"Opaque pagination cursor (ISO 8601 datetime returned as `nextCursor` by a previous response). Returns scans strictly older than the cursor.","example":"2026-04-19T00:00:00.000Z"},"required":false,"description":"Opaque pagination cursor (ISO 8601 datetime returned as `nextCursor` by a previous response). Returns scans strictly older than the cursor.","name":"cursor","in":"query"}],"responses":{"200":{"description":"Scan list.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanListResponse"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Subscription required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Service temporarily unavailable. Retry with backoff.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/scans/{id}":{"get":{"operationId":"getScan","summary":"Get a scan","description":"Returns the full scan including per-check results. Returns 404 if the scan does not exist or is not owned by the API key's user.","tags":["Scans"],"parameters":[{"schema":{"type":"string","description":"Scan id."},"required":true,"description":"Scan id.","name":"id","in":"path"}],"responses":{"200":{"description":"Scan.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Scan"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Subscription required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Scan not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Polling too frequently. Response carries `Retry-After` (seconds) plus `X-RateLimit-Limit` and `X-RateLimit-Remaining`.","headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests permitted in the current window.","schema":{"type":"integer","example":10}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current window. `0` on a 429 response.","schema":{"type":"integer","example":0}},"Retry-After":{"description":"Seconds until a slot frees in the sliding window (RFC 7231 §7.1.3). Honour this before retrying.","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Service temporarily unavailable. Retry with backoff.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/ask":{"get":{"operationId":"askGet","summary":"Ask in natural language (NLWeb)","description":"NLWeb /ask endpoint, conventional GET form: /ask?query=<text>. Natural-language search over Agent Ready's own content (methodology, check registry, specs, and the content library — explainers, comparisons, how-to guides, glossary). Public — no API key required. Returns NLWeb result objects with a nested Schema.org `schema_object`. Set stream=true for Server-Sent Events. Also served at the root path /ask.","tags":["NLWeb"],"security":[],"parameters":[{"schema":{"type":"string","example":"how is the score calculated?"},"required":true,"name":"query","in":"query"},{"schema":{"type":"string","enum":["list","summarize"]},"required":false,"name":"mode","in":"query"},{"schema":{"type":"string","enum":["methodology","checks","specs","llms-txt","check","page"]},"required":false,"name":"itemType","in":"query"},{"schema":{"type":"string","enum":["true","false"]},"required":false,"name":"stream","in":"query"}],"responses":{"200":{"description":"An NLWeb answer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AskResponse"}}}},"400":{"description":"Missing or invalid query.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded. Response carries `Retry-After` (seconds) plus `X-RateLimit-Limit` and `X-RateLimit-Remaining`. Back off using exponential delay with jitter — see the Rate limits & retry section in the docs.","headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests permitted in the current window.","schema":{"type":"integer","example":10}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current window. `0` on a 429 response.","schema":{"type":"integer","example":0}},"Retry-After":{"description":"Seconds until a slot frees in the sliding window (RFC 7231 §7.1.3). Honour this before retrying.","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Service temporarily unavailable. Retry with backoff.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"askPost","summary":"Ask in natural language (NLWeb), JSON-body form","description":"NLWeb /ask endpoint, JSON-body form: { query: { q }, prefer: { mode, streaming } }. Same response as the GET form. Public — no API key required.","tags":["NLWeb"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AskRequest"}}}},"responses":{"200":{"description":"An NLWeb answer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AskResponse"}}}},"400":{"description":"Invalid /ask request body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No results (NLWeb failure envelope).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AskResponse"}}}},"429":{"description":"Rate limit exceeded. Response carries `Retry-After` (seconds) plus `X-RateLimit-Limit` and `X-RateLimit-Remaining`. Back off using exponential delay with jitter — see the Rate limits & retry section in the docs.","headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests permitted in the current window.","schema":{"type":"integer","example":10}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current window. `0` on a 429 response.","schema":{"type":"integer","example":0}},"Retry-After":{"description":"Seconds until a slot frees in the sliding window (RFC 7231 §7.1.3). Honour this before retrying.","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Service temporarily unavailable. Retry with backoff.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/scan/mcp":{"post":{"operationId":"scanMcp","summary":"Scan a live MCP server","description":"Connects to a remote MCP endpoint over Streamable HTTP, runs the handshake, and grades the tools, resources, and prompts it advertises against MCP best practices. Returns a weighted mcpScore (0–100) with per-check findings. Synchronous (no polling). Public — no API key required. Remote http(s) endpoints only; stdio servers aren't reachable. This is a standalone tool: its score is independent of the site agent-readability score.","tags":["MCP"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpScanRequest"}}}},"responses":{"201":{"description":"The MCP server scan result and its shareable report URL.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpScanResponse"}}}},"400":{"description":"Invalid or blocked endpoint (bad URL, non-http(s), or a private/reserved address).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded. Response carries `Retry-After` (seconds). Back off with exponential delay + jitter.","headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests permitted in the current window.","schema":{"type":"integer","example":10}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current window. `0` on a 429 response.","schema":{"type":"integer","example":0}},"Retry-After":{"description":"Seconds until a slot frees in the sliding window (RFC 7231 §7.1.3). Honour this before retrying.","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"The MCP server could not be scanned. Retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/x402/scan":{"get":{"operationId":"x402ScanChallenge","summary":"x402 payment challenge for a paid scan","description":"Returns an HTTP 402 payment-requirements challenge for the paid scan resource (x402 v2). This is the discovery/probe surface: it always 402s with the v2 PaymentRequired delivered in the base64 `PAYMENT-REQUIRED` response header (and mirrored in the JSON body) — x402Version 2 + resource + accepts[] + Bazaar discovery extensions. To run a scan, POST to this path with a signed X-PAYMENT header.","tags":["Scans"],"security":[],"responses":{"402":{"description":"Payment required. The `PAYMENT-REQUIRED` header (and JSON body) carry an x402 v2 PaymentRequired object: { x402Version: 2, resource, accepts: [...] }. Each `accepts` entry uses `amount` (atomic units) and a CAIP-2 `network` (eip155:8453 = Base mainnet). Two tiers — $0.02 USDC (25 pages), $0.25 (250 pages).","headers":{"PAYMENT-REQUIRED":{"description":"Base64-encoded x402 v2 PaymentRequired object (HTTP transport spec). Carries the same { x402Version, resource, accepts[], extensions } as the JSON body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"x402Scan","summary":"Run a scan, paid via x402","description":"Runs an agent-readability scan paid via x402 v2 (no account or subscription). Without a valid `X-PAYMENT` header this returns a v2 402 challenge; sign the EIP-3009 USDC authorization for one of the advertised tiers and resend the v2 payment payload in the `X-PAYMENT` header to run the scan. Settlement is on Base mainnet (CAIP-2 eip155:8453; the facilitator pays gas); the response carries an `X-PAYMENT-RESPONSE` header. Tiers: $0.02 (25 pages), $0.25 (250 pages).","tags":["Scans"],"security":[],"parameters":[{"schema":{"type":"string","description":"Base64-encoded signed x402 payment authorization. Omit it to receive the 402 challenge."},"required":false,"description":"Base64-encoded signed x402 payment authorization. Omit it to receive the 402 challenge.","name":"X-PAYMENT","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"}},"required":["url"],"description":"The website URL to scan."}}}},"responses":{"201":{"description":"Payment verified and the scan completed. The `X-PAYMENT-RESPONSE` header carries the settlement."},"400":{"description":"Invalid JSON body, URL, or a blocked address.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Payment required or verification failed. The `PAYMENT-REQUIRED` header (and JSON body) carry the x402 v2 challenge ({ x402Version, resource, accepts, error }).","headers":{"PAYMENT-REQUIRED":{"description":"Base64-encoded x402 v2 PaymentRequired object (HTTP transport spec). Carries the same { x402Version, resource, accepts[], extensions } as the JSON body.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"The scan failed after payment. Retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"webhooks":{}}