{"openapi":"3.1.0","info":{"title":"Pickrate Public API","version":"1.0.0","description":"Query whether AI agents pick a developer tool over its competitors (its 'Pick Rate'). The same read surface is available as an MCP server at /api/mcp and via WebMCP at /.well-known/webmcp.\n\n## Versioning\nEndpoints under `/api/public` are v1 and are additive-only: new fields may appear, existing fields will not change type or disappear without a new major path prefix (`/api/public/v2/...`). Treat unknown fields as forward compatibility, not as an error. If an endpoint is ever retired it will first return `Deprecation` and `Sunset` response headers (RFC 9745 / RFC 8594) for at least 90 days before removal, and the replacement will be named in a `Link; rel=\"successor-version\"` header.\n\n## Errors\nEvery 4xx and 5xx returns the `Error` schema: a stable `error.code` to branch on, a human-readable `error.message`, and usually an `error.hint` naming the next action. An unknown path under `/api` returns this same shape rather than an HTML error page.\n\n## Rate limits\nThe public read endpoints are unauthenticated and unmetered — no key, no quota. The endpoints that create things (agent registration) are limited per IP per hour and return the standard `RateLimit`, `RateLimit-Policy`, and `RateLimit-Limit/Remaining/Reset` headers on every response, plus `Retry-After` on a 429.\n\n## Result sets\nList responses are complete, not paged: a category leaderboard returns every measured vendor in that category (tens, not thousands). There is no cursor to follow and no truncation to detect."},"servers":[{"url":"https://pickrate.io"}],"paths":{"/api/public/report":{"get":{"operationId":"getReport","summary":"Pick Rate report for one tool","description":"Headline Pick Rate, rank, and who beats a single tool. Resolve by name, slug, domain, or package.","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string"},"description":"Tool name, slug, domain, or package (e.g. 'stripe', 'clerk', '@sendgrid/mail')."}],"responses":{"200":{"description":"Report","content":{"application/json":{"schema":{"type":"object","properties":{"tool":{"type":"string"},"slug":{"type":"string"},"category":{"type":"string"},"pickRate":{"type":"number","description":"Share of trials an agent picks this tool (0–1)."},"rank":{"type":"integer"},"field":{"type":"integer","description":"Number of tools in the category."},"defaultRate":{"type":"number"},"shortlistRate":{"type":"number"},"nTrials":{"type":"integer"},"asOf":{"type":["string","null"],"format":"date-time"},"beatenBy":{"type":"array","items":{"type":"object"}},"readiness":{"type":["object","null"],"description":"Agent readiness from Cloudflare's Agent Readiness score: what this vendor PUBLISHES for agents, not whether agents pick it. The two correlate at roughly 0.19 across the measured corpus, so read them as separate signals.","properties":{"level":{"type":["integer","null"],"description":"0-5 readiness level."},"levelName":{"type":["string","null"]},"checksPassed":{"type":"integer"},"checksScored":{"type":"integer"},"blocked":{"type":"boolean","description":"True when the site refused the scanner with a bot challenge."},"scannedAt":{"type":"string","format":"date-time"},"source":{"type":"string"}}},"url":{"type":"string","format":"uri"}}}}}},"400":{"description":"`q` was missing or empty (`error.code` = `invalid_request`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No measured tool matched `q` (`error.code` = `not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/public/leaderboard":{"get":{"operationId":"getLeaderboard","summary":"Ranked tools for a category","description":"Tools in a category ranked by Pick Rate. Omit `category` to list available categories (optionally scoped to one domain).","parameters":[{"name":"category","in":"query","required":false,"schema":{"type":"string"},"description":"Category slug (e.g. 'payments', 'auth', 'search')."},{"name":"domain","in":"query","required":false,"schema":{"type":"string","enum":["dev-tools","saas"]},"description":"When listing categories (no category given), scope to one leaderboard tree."}],"responses":{"200":{"description":"Ranked vendors, or the list of categories when no category is given","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"description":"No leaderboard exists for that category (`error.code` = `not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["invalid_request","not_found","unauthorized","invalid_key","rate_limited","internal_error"],"description":"Stable machine-readable code. Branch on this, not on the message."},"message":{"type":"string","description":"Human-readable explanation. Safe to show a user."},"hint":{"type":"string","description":"What to do next, when there is something useful to say."},"documentation":{"type":"string","format":"uri"}}}}}}}}