{
  "openapi": "3.1.0",
  "info": {
    "title": "x402 payable APIs — agiscorecard",
    "version": "1.1.0",
    "summary": "Pay-per-call scanning APIs for AI agents. No account, no API key — pay per request in USDC on Base via the x402 payment-required protocol (v2 + legacy v1).",
    "description": "Six GET endpoints that autonomous agents can pay for with a wallet instead of a login. Each unpaid request returns **HTTP 402** with a machine-readable price quote in both protocol versions at once: the `PAYMENT-REQUIRED` response header (base64 x402 **v2** `PaymentRequired`) and a JSON body (legacy **v1**). The client signs an EIP-3009 USDC `transferWithAuthorization` and retries with `PAYMENT-SIGNATURE` (v2) or `X-PAYMENT` (v1). Settlement happens **only after the work succeeds** — failed calls are never charged.\n\n## Pricing\n\n| Endpoint | Price (USD) | Atomic USDC (6 decimals) |\n|---|---|---|\n| `GET /api/scan` | $0.005 | 5000 |\n| `GET /api/mcp-check` | $0.005 | 5000 |\n| `GET /api/wellknown` | $0.005 | 5000 |\n| `GET /api/llms-extract` | $0.005 | 5000 |\n| `GET /api/scan-batch` | $0.02 | 20000 |\n| `GET /api/mcp-index` | $0.01 | 10000 |\n\nAsset: native USDC on Base — contract `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` (6 decimals, EIP-712 domain name \"USD Coin\", version \"2\"). Network: `eip155:8453` (x402 v2, CAIP-2) / `base` (x402 v1). Scheme: `exact`.\n\n## Discovery\n\n- `GET /.well-known/x402` — x402-native machine-readable catalog (paths, prices, live v2 `accepts[]`).\n- `GET /openapi.json` — this document.\n\nClient libraries that automate the whole 402 → sign → retry flow: `@x402/fetch` + `@x402/evm` (current, v2) or `x402-fetch` (legacy, v1).\n\nUntil the receiving wallet is configured server-side, any endpoint can be tried free by appending `demo=1` (the result arrives wrapped in `{\"demo\": true, \"result\": ...}`); once payments are live, calls without a payment header receive the 402 quote.",
    "contact": {
      "name": "x402 APIs — agiscorecard",
      "url": "https://x402.agiscorecard.com/"
    },
    "license": {
      "name": "Proprietary — pay-per-call, no account required",
      "url": "https://x402.agiscorecard.com/"
    }
  },
  "servers": [
    { "url": "https://x402.agiscorecard.com" }
  ],
  "security": [
    {},
    { "x402PaymentSignature": [] },
    { "x402LegacyXPayment": [] }
  ],
  "tags": [
    { "name": "paid", "description": "x402-payable endpoints (USDC on Base, charged only on success)" },
    { "name": "discovery", "description": "Free machine-readable catalogs" }
  ],
  "paths": {
    "/api/scan": {
      "get": {
        "operationId": "scanSite",
        "tags": ["paid"],
        "summary": "Agent-readiness scan of any website ($0.005)",
        "description": "Scans a website's AI-agent surface — AI-crawler access in robots.txt, llms.txt, agents.md, JSON-LD structured data, meta basics and sitemap — and returns a 0–100 score with itemized checks and concrete fixes.",
        "x-pricing": { "usd": "$0.005", "atomicUsdc": "5000" },
        "parameters": [
          { "$ref": "#/components/parameters/url" },
          { "$ref": "#/components/parameters/demo" }
        ],
        "responses": {
          "200": {
            "description": "Scan report. Includes the x402 settlement receipt headers.",
            "headers": {
              "PAYMENT-RESPONSE": { "$ref": "#/components/headers/PAYMENT-RESPONSE" },
              "X-PAYMENT-RESPONSE": { "$ref": "#/components/headers/X-PAYMENT-RESPONSE" }
            },
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/ScanReport" } }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "402": { "$ref": "#/components/responses/PaymentRequired" },
          "502": { "$ref": "#/components/responses/UpstreamError" }
        }
      }
    },
    "/api/mcp-check": {
      "get": {
        "operationId": "mcpCheck",
        "tags": ["paid"],
        "summary": "MCP server health check ($0.005)",
        "description": "Health-checks an MCP server via a real JSON-RPC handshake: initialize, protocol version, serverInfo identity, capabilities, tools/list quality, latency, TLS and auth posture — scored 0–100 with itemized checks.",
        "x-pricing": { "usd": "$0.005", "atomicUsdc": "5000" },
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "required": true,
            "description": "MCP server endpoint URL to check.",
            "schema": { "type": "string", "examples": ["your-server.com/mcp"] }
          },
          { "$ref": "#/components/parameters/demo" }
        ],
        "responses": {
          "200": {
            "description": "MCP health report. Includes the x402 settlement receipt headers.",
            "headers": {
              "PAYMENT-RESPONSE": { "$ref": "#/components/headers/PAYMENT-RESPONSE" },
              "X-PAYMENT-RESPONSE": { "$ref": "#/components/headers/X-PAYMENT-RESPONSE" }
            },
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/ScoredReport" } }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "402": { "$ref": "#/components/responses/PaymentRequired" },
          "502": { "$ref": "#/components/responses/UpstreamError" }
        }
      }
    },
    "/api/wellknown": {
      "get": {
        "operationId": "wellknownAudit",
        "tags": ["paid"],
        "summary": "Well-known agent-discovery audit ($0.005)",
        "description": "Audits a site's well-known agent-discovery surface: .well-known/ai-catalog.json, MCP server card, A2A agent card, llms.txt, agents.md and robots.txt AI-crawler access — scored 0–100 with pass/warn/fail checks and fix links.",
        "x-pricing": { "usd": "$0.005", "atomicUsdc": "5000" },
        "parameters": [
          { "$ref": "#/components/parameters/url" },
          { "$ref": "#/components/parameters/demo" }
        ],
        "responses": {
          "200": {
            "description": "Discovery audit report. Includes the x402 settlement receipt headers.",
            "headers": {
              "PAYMENT-RESPONSE": { "$ref": "#/components/headers/PAYMENT-RESPONSE" },
              "X-PAYMENT-RESPONSE": { "$ref": "#/components/headers/X-PAYMENT-RESPONSE" }
            },
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/ScoredReport" } }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "402": { "$ref": "#/components/responses/PaymentRequired" },
          "502": { "$ref": "#/components/responses/UpstreamError" }
        }
      }
    },
    "/api/llms-extract": {
      "get": {
        "operationId": "llmsExtract",
        "tags": ["paid"],
        "summary": "llms.txt / AI-policy file extraction ($0.005)",
        "description": "Structured extraction of one domain's AI-policy files: llms.txt parsed into title/summary/sections/link lists, agents.md headings and excerpt, ai.txt, and per-AI-crawler robots.txt verdicts (GPTBot, ClaudeBot, PerplexityBot, Google-Extended, CCBot, …) with aggregate adoption signals. Public hosts only — private/local addresses are rejected with a free 400 before any payment challenge.",
        "x-pricing": { "usd": "$0.005", "atomicUsdc": "5000" },
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "required": true,
            "description": "Target domain or URL to extract. Public hosts only (localhost, RFC-1918 and .local/.internal hosts are rejected free of charge).",
            "schema": { "type": "string", "examples": ["example.com"] }
          },
          { "$ref": "#/components/parameters/demo" }
        ],
        "responses": {
          "200": {
            "description": "Extracted AI-policy structure. Includes the x402 settlement receipt headers.",
            "headers": {
              "PAYMENT-RESPONSE": { "$ref": "#/components/headers/PAYMENT-RESPONSE" },
              "X-PAYMENT-RESPONSE": { "$ref": "#/components/headers/X-PAYMENT-RESPONSE" }
            },
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/LlmsExtractResult" } }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "402": { "$ref": "#/components/responses/PaymentRequired" },
          "502": { "$ref": "#/components/responses/UpstreamError" }
        }
      }
    },
    "/api/scan-batch": {
      "get": {
        "operationId": "scanBatch",
        "tags": ["paid"],
        "summary": "Batch agent-readiness scan, up to 5 URLs ($0.02)",
        "description": "Scans up to 5 comma-separated URLs concurrently in one paid call; each returns the full 0–100 scored report. Requests with more than 5 URLs are rejected with a free 400 — never charged. Partial batches (some scans failed) are delivered and charged with per-URL error entries; if every scan fails the call errors and is not charged.",
        "x-pricing": { "usd": "$0.02", "atomicUsdc": "20000" },
        "parameters": [
          {
            "name": "urls",
            "in": "query",
            "required": true,
            "description": "Comma-separated target URLs, 1 to 5.",
            "schema": { "type": "string", "examples": ["a.com,b.com,c.com"] }
          },
          { "$ref": "#/components/parameters/demo" }
        ],
        "responses": {
          "200": {
            "description": "Batch results array. Includes the x402 settlement receipt headers.",
            "headers": {
              "PAYMENT-RESPONSE": { "$ref": "#/components/headers/PAYMENT-RESPONSE" },
              "X-PAYMENT-RESPONSE": { "$ref": "#/components/headers/X-PAYMENT-RESPONSE" }
            },
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/BatchScanResult" } }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "402": { "$ref": "#/components/responses/PaymentRequired" },
          "502": { "$ref": "#/components/responses/UpstreamError" }
        }
      }
    },
    "/api/mcp-index": {
      "get": {
        "operationId": "mcpIndex",
        "tags": ["paid"],
        "summary": "Full Public MCP Server Index ($0.01)",
        "description": "Returns the full current Public MCP Server Index as JSON: every indexed public MCP server with health score, grade, latency, tool counts and failing checks, fetched live. A free weekly summary is published at https://mcppulse.agiscorecard.com — this endpoint returns the complete machine-readable dataset.",
        "x-pricing": { "usd": "$0.01", "atomicUsdc": "10000" },
        "parameters": [
          { "$ref": "#/components/parameters/demo" }
        ],
        "responses": {
          "200": {
            "description": "The complete MCP server index. Includes the x402 settlement receipt headers.",
            "headers": {
              "PAYMENT-RESPONSE": { "$ref": "#/components/headers/PAYMENT-RESPONSE" },
              "X-PAYMENT-RESPONSE": { "$ref": "#/components/headers/X-PAYMENT-RESPONSE" }
            },
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/McpIndex" } }
            }
          },
          "402": { "$ref": "#/components/responses/PaymentRequired" },
          "502": { "$ref": "#/components/responses/UpstreamError" }
        }
      }
    },
    "/.well-known/x402": {
      "get": {
        "operationId": "x402Catalog",
        "tags": ["discovery"],
        "summary": "x402 machine-readable endpoint catalog (free)",
        "description": "Free, cacheable catalog of every payable endpoint: path, method, query params, price in atomic USDC units, network ids for both protocol versions, and — once the receiving wallet is live — the full v2 `accepts[]` PaymentRequirements. Also links this OpenAPI document via its `openapi` field.",
        "security": [ {} ],
        "responses": {
          "200": {
            "description": "The endpoint catalog.",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/X402Catalog" } }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "x402PaymentSignature": {
        "type": "apiKey",
        "in": "header",
        "name": "PAYMENT-SIGNATURE",
        "description": "x402 v2 payment (current). OpenAPI has no native x402 scheme, so it is modeled as a header credential. Flow: (1) call the endpoint with no payment header → HTTP 402 whose `PAYMENT-REQUIRED` response header carries base64(`PaymentRequired`) — `{ x402Version: 2, error, resource: { url, description, mimeType }, accepts: [{ scheme: \"exact\", network: \"eip155:8453\", amount, asset, payTo, maxTimeoutSeconds, extra }] }` with `amount` in atomic USDC units (6 decimals). (2) Sign an EIP-3009 USDC `transferWithAuthorization` for exactly the quoted amount (asset `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913`, EIP-712 domain name \"USD Coin\" version \"2\"). (3) Retry the same request with `PAYMENT-SIGNATURE: base64(PaymentPayload)` where `PaymentPayload = { x402Version: 2, resource?, accepted: <one of the advertised accepts>, payload: { signature, authorization } }`. (4) The 200 response carries the base64 settlement receipt (incl. on-chain tx hash) in `PAYMENT-RESPONSE` (mirrored as `X-PAYMENT-RESPONSE`). Settlement happens only after the work succeeds — failed calls are never charged. `@x402/fetch` + `@x402/evm` automate the whole flow. Legacy v1 clients use the `X-PAYMENT` header instead (see the x402LegacyXPayment scheme)."
      },
      "x402LegacyXPayment": {
        "type": "apiKey",
        "in": "header",
        "name": "X-PAYMENT",
        "description": "x402 v1 payment (legacy, still accepted on every endpoint). The 402 JSON body carries `{ x402Version: 1, error, accepts: [...] }` with `maxAmountRequired` and network `base`. Retry with `X-PAYMENT: base64({ x402Version: 1, scheme: \"exact\", network: \"base\", payload: { signature, authorization } })`; the receipt arrives in `X-PAYMENT-RESPONSE`. The npm package `x402-fetch` (plus a viem wallet client) automates this flow."
      }
    },
    "parameters": {
      "url": {
        "name": "url",
        "in": "query",
        "required": true,
        "description": "Target URL to scan (scheme optional — `https://` is assumed).",
        "schema": { "type": "string", "examples": ["example.com"] }
      },
      "demo": {
        "name": "demo",
        "in": "query",
        "required": false,
        "description": "While server-side payments are not yet configured, `demo=1` serves a free demo result wrapped in `{\"demo\": true, \"note\": ..., \"result\": ...}`. Ignored once payments are live.",
        "schema": { "type": "string", "enum": ["1"] }
      }
    },
    "headers": {
      "PAYMENT-RESPONSE": {
        "description": "x402 v2 settlement receipt: base64(JSON `SettleResponse`) — `{ success: true, transaction, network, payer? }` including the on-chain transaction hash.",
        "schema": { "type": "string", "contentEncoding": "base64" }
      },
      "X-PAYMENT-RESPONSE": {
        "description": "Legacy x402 v1 receipt header — identical base64 bytes to PAYMENT-RESPONSE.",
        "schema": { "type": "string", "contentEncoding": "base64" }
      },
      "PAYMENT-REQUIRED": {
        "description": "x402 v2 challenge: base64(JSON `PaymentRequired`) — `{ x402Version: 2, error, resource: { url, description, mimeType }, accepts: [{ scheme: \"exact\", network: \"eip155:8453\", amount, asset, payTo, maxTimeoutSeconds, extra: { name, version } }] }`. `amount` is the price in atomic USDC units (6 decimals). v2 clients read this header and ignore the (v1) body.",
        "schema": { "type": "string", "contentEncoding": "base64" }
      }
    },
    "responses": {
      "PaymentRequired": {
        "description": "Payment required (or payment invalid / failed verification / failed settlement — the `error` field says which). The price quote is served in both x402 protocol versions at once: the `PAYMENT-REQUIRED` response header carries the base64 v2 `PaymentRequired` object, and the JSON body is the legacy v1 `PaymentRequired`. The quoted amount always matches this operation's `x-pricing`.",
        "headers": {
          "PAYMENT-REQUIRED": { "$ref": "#/components/headers/PAYMENT-REQUIRED" }
        },
        "content": {
          "application/json": { "schema": { "$ref": "#/components/schemas/PaymentRequiredV1" } }
        }
      },
      "BadRequest": {
        "description": "Invalid request (missing/invalid url, more than 5 batch URLs, private host). Validation runs before any payment challenge — a 400 is always free and never charged.",
        "content": {
          "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
        }
      },
      "UpstreamError": {
        "description": "The work failed (upstream scanner unreachable or errored, target domain dead, payment facilitator unreachable). The payment is never settled for a failed call — you are not charged.",
        "content": {
          "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": ["error"],
        "properties": {
          "error": { "type": "string", "description": "Human- and agent-readable error message." }
        }
      },
      "PaymentRequirementsV1": {
        "type": "object",
        "description": "x402 v1 PaymentRequirements (flat shape with maxAmountRequired and inline resource info).",
        "properties": {
          "scheme": { "type": "string", "const": "exact" },
          "network": { "type": "string", "const": "base", "description": "x402 v1 network id for Base mainnet." },
          "maxAmountRequired": { "type": "string", "description": "Price in atomic USDC units (6 decimals), e.g. \"5000\" = $0.005.", "examples": ["5000"] },
          "resource": { "type": "string", "format": "uri", "description": "Canonical URL of the resource being paid for." },
          "description": { "type": "string" },
          "mimeType": { "type": "string", "const": "application/json" },
          "outputSchema": { "type": ["object", "null"] },
          "payTo": { "type": "string", "description": "Receiving wallet address (0x…) on Base." },
          "maxTimeoutSeconds": { "type": "integer", "examples": [60] },
          "asset": { "type": "string", "description": "USDC contract address on Base.", "examples": ["0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"] },
          "extra": {
            "type": "object",
            "description": "EIP-712 domain of the asset contract.",
            "properties": {
              "name": { "type": "string", "examples": ["USD Coin"] },
              "version": { "type": "string", "examples": ["2"] }
            }
          }
        }
      },
      "PaymentRequiredV1": {
        "type": "object",
        "description": "x402 v1 PaymentRequired challenge (the JSON body of every 402; v2 clients use the PAYMENT-REQUIRED header instead).",
        "required": ["x402Version", "accepts"],
        "properties": {
          "x402Version": { "type": "integer", "const": 1 },
          "error": { "type": "string" },
          "accepts": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/PaymentRequirementsV1" }
          }
        }
      },
      "Check": {
        "type": "object",
        "description": "One itemized check inside a scored report.",
        "properties": {
          "id": { "type": "string" },
          "category": { "type": "string" },
          "title": { "type": "string" },
          "earned": { "type": "number" },
          "possible": { "type": "number" },
          "status": { "type": "string", "enum": ["pass", "warn", "fail"] },
          "detail": { "type": "string" },
          "fix": { "type": ["string", "null"] }
        },
        "additionalProperties": true
      },
      "ScanReport": {
        "type": "object",
        "description": "Agent-readiness scan report (proxied from the AgentReady scanner).",
        "properties": {
          "url": { "type": "string", "format": "uri" },
          "scannedAt": { "type": "string", "format": "date-time" },
          "score": { "type": "integer", "minimum": 0, "maximum": 100 },
          "grade": { "type": "string", "examples": ["A", "B", "C"] },
          "checks": { "type": "array", "items": { "$ref": "#/components/schemas/Check" } },
          "summary": { "type": "string" }
        },
        "additionalProperties": true
      },
      "ScoredReport": {
        "type": "object",
        "description": "Generic 0–100 scored report with itemized checks (MCP health check / well-known audit).",
        "properties": {
          "url": { "type": "string" },
          "score": { "type": "integer", "minimum": 0, "maximum": 100 },
          "grade": { "type": "string" },
          "checks": { "type": "array", "items": { "$ref": "#/components/schemas/Check" } }
        },
        "additionalProperties": true
      },
      "LlmsExtractLink": {
        "type": "object",
        "properties": {
          "title": { "type": "string" },
          "url": { "type": "string" },
          "notes": { "type": "string" }
        }
      },
      "LlmsExtractResult": {
        "type": "object",
        "description": "Structured extraction of a domain's AI-policy files.",
        "properties": {
          "domain": { "type": "string" },
          "origin": { "type": "string", "format": "uri" },
          "fetchedAt": { "type": "string", "format": "date-time" },
          "llmsTxt": {
            "type": "object",
            "properties": {
              "found": { "type": "boolean" },
              "url": { "type": "string", "format": "uri" },
              "status": { "type": ["integer", "null"] },
              "bytes": { "type": "integer" },
              "title": { "type": "string" },
              "summary": { "type": "string" },
              "intro": { "type": "string" },
              "sectionCount": { "type": "integer" },
              "linkCount": { "type": "integer" },
              "sections": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "name": { "type": "string" },
                    "links": { "type": "array", "items": { "$ref": "#/components/schemas/LlmsExtractLink" } },
                    "notes": { "type": "string" }
                  }
                }
              },
              "orphanLinks": { "type": "array", "items": { "$ref": "#/components/schemas/LlmsExtractLink" } }
            },
            "additionalProperties": true
          },
          "agentsMd": {
            "type": "object",
            "properties": {
              "found": { "type": "boolean" },
              "url": { "type": "string", "format": "uri" },
              "status": { "type": ["integer", "null"] },
              "bytes": { "type": "integer" },
              "headings": { "type": "array", "items": { "type": "string" } },
              "excerpt": { "type": "string" }
            },
            "additionalProperties": true
          },
          "aiTxt": {
            "type": "object",
            "properties": {
              "found": { "type": "boolean" },
              "url": { "type": "string", "format": "uri" },
              "status": { "type": ["integer", "null"] },
              "bytes": { "type": "integer" },
              "directives": { "type": "array", "items": { "type": "object" } },
              "excerpt": { "type": "string" }
            },
            "additionalProperties": true
          },
          "robotsTxt": {
            "type": "object",
            "properties": {
              "found": { "type": "boolean" },
              "url": { "type": "string", "format": "uri" },
              "status": { "type": ["integer", "null"] },
              "sitemaps": { "type": "array", "items": { "type": "string" } },
              "aiBots": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "bot": { "type": "string", "examples": ["GPTBot", "ClaudeBot"] },
                    "operator": { "type": "string" },
                    "purpose": { "type": "string" },
                    "allowed": { "type": "boolean" },
                    "matchedBy": { "type": "string" },
                    "allow": { "type": "array", "items": { "type": "string" } },
                    "disallow": { "type": "array", "items": { "type": "string" } },
                    "crawlDelay": { "type": ["number", "null"] }
                  }
                }
              }
            },
            "additionalProperties": true
          },
          "signals": {
            "type": "object",
            "properties": {
              "hasLlmsTxt": { "type": "boolean" },
              "hasAgentsMd": { "type": "boolean" },
              "hasAiTxt": { "type": "boolean" },
              "hasRobotsTxt": { "type": "boolean" },
              "aiBotsAllowed": { "type": "integer" },
              "aiBotsBlocked": { "type": "integer" },
              "aiPolicyStance": { "type": "string", "enum": ["open", "selective", "blocking"] },
              "aiReadinessLevel": { "type": "string", "enum": ["none", "basic", "high"] }
            }
          }
        },
        "additionalProperties": true
      },
      "BatchScanResult": {
        "type": "object",
        "description": "Batch scan results — one entry per requested URL, preserving order.",
        "properties": {
          "count": { "type": "integer", "description": "Number of URLs scanned." },
          "succeeded": { "type": "integer", "description": "How many scans succeeded." },
          "results": {
            "type": "array",
            "items": {
              "type": "object",
              "required": ["url", "ok"],
              "properties": {
                "url": { "type": "string" },
                "ok": { "type": "boolean" },
                "result": { "$ref": "#/components/schemas/ScanReport" },
                "error": { "type": "string", "description": "Present when ok=false." }
              }
            }
          }
        }
      },
      "McpIndex": {
        "type": "object",
        "description": "The complete Public MCP Server Index (shape follows the live dataset; loosely specified).",
        "properties": {
          "updatedAt": { "type": "string" },
          "scanned": { "type": "integer" },
          "results": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": { "type": "string" },
                "score": { "type": "number" },
                "grade": { "type": "string" },
                "latencyMs": { "type": "number" },
                "tools": { "type": "number" }
              },
              "additionalProperties": true
            }
          }
        },
        "additionalProperties": true
      },
      "X402Catalog": {
        "type": "object",
        "description": "x402-native discovery catalog served at /.well-known/x402.",
        "properties": {
          "x402Version": { "type": "integer", "const": 2 },
          "x402Versions": { "type": "array", "items": { "type": "integer" }, "examples": [[1, 2]] },
          "name": { "type": "string" },
          "description": { "type": "string" },
          "network": { "type": "string", "const": "eip155:8453" },
          "networkV1": { "type": "string", "const": "base" },
          "asset": { "type": "object" },
          "payToConfigured": { "type": "boolean" },
          "endpoints": { "type": "array", "items": { "type": "object" } },
          "openapi": { "type": "string", "format": "uri", "description": "URL of this OpenAPI document." },
          "docs": { "type": "string", "format": "uri" }
        },
        "additionalProperties": true
      }
    }
  }
}
