{"openapi":"3.1.0","info":{"title":"Can My Agent API","version":"1.0.0","description":"The public REST API for Can My Agent, a catalog of plain prompts for personal AI agents. Everything here is public and read-only, with no authentication. Agents that want a richer interface should use the MCP server instead — see GET /.well-known/mcp.json.","contact":{"url":"https://canmyagent.com/docs"}},"servers":[{"url":"https://canmyagent.com","description":"Production"}],"tags":[{"name":"catalog","description":"Searching and reading the prompt catalog."},{"name":"telemetry","description":"Fire-and-forget usage and error beacons."},{"name":"feedback","description":"The public feedback inbox."},{"name":"meta","description":"Health and discovery."}],"paths":{"/api/v1/prompts":{"get":{"tags":["catalog"],"operationId":"listPrompts","summary":"Search and browse the prompt catalog","description":"Returns compact prompt rows (slug, title, description, category, verification, creator, stats). Omit the query to browse; pass `q` for ranked search. Each row carries a `markdown_url` with the full prompt text as Markdown with YAML frontmatter. Rate-limited: 120 requests/minute per IP.","parameters":[{"name":"q","in":"query","description":"Full-text search query. Empty means browse everything.","schema":{"type":"string","maxLength":200}},{"name":"category","in":"query","description":"Filter to one category.","schema":{"type":"string","enum":["home","family","food","health","money","shopping","travel","calendar","social","learning","creative","work","business","coding","investing","setup","other"]}},{"name":"sort","in":"query","description":"Result ordering. Defaults to trending.","schema":{"type":"string","enum":["trending","new","copied","downloaded"],"default":"trending"}},{"name":"limit","in":"query","description":"Rows to return, 1–100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":30}}],"responses":{"200":{"description":"A page of prompt rows.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromptList"}}}}}}},"/api/v1/prompts/random":{"get":{"tags":["catalog"],"operationId":"randomPrompt","summary":"One random published prompt","description":"The same random pick as /surprise, as JSON — for agents and the MCP server. Never cached.","responses":{"200":{"description":"A random prompt.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromptSummary"}}}},"404":{"description":"No published prompts exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/events":{"post":{"tags":["telemetry"],"operationId":"recordEvent","summary":"Record a prompt copy event","description":"Fire-and-forget copy beacon from the prompt page's Copy button. Always answers 204 — including when rate-limited — so a working counter never looks broken.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["slug","kind"],"properties":{"slug":{"type":"string","maxLength":96,"description":"The copied prompt's slug."},"kind":{"type":"string","enum":["copy"],"description":"Only 'copy' is accepted."},"client":{"type":"string","description":"Where the copy happened (e.g. chatgpt, button)."}}}}}},"responses":{"204":{"description":"Recorded (or deliberately dropped). No body."},"400":{"description":"Invalid JSON, slug, or kind.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/client-errors":{"post":{"tags":["telemetry"],"operationId":"reportClientError","summary":"Report a frontend error","description":"The inline error beacon in the site layout forwards window errors here; the Sentry DSN stays server-side. Small validated payloads only. Third-party webview noise is filtered.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["message"],"properties":{"kind":{"type":"string","enum":["error","unhandledrejection"],"description":"Defaults to 'error'."},"message":{"type":"string","maxLength":500,"description":"The error message."},"stack":{"type":"string","maxLength":2000},"url":{"type":"string","maxLength":500,"description":"The page URL where it threw."}}}}}},"responses":{"204":{"description":"Accepted. No body."},"400":{"description":"Invalid JSON or missing message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/feedback":{"get":{"tags":["feedback"],"operationId":"listFeedback","summary":"Read the public feedback inbox","description":"Read-only and public: titles and bodies of bug reports and feature ideas. `reporter` is a display name, never an email or token. There is deliberately no HTTP write path — agents file feedback through the MCP feedback_submit tool.","parameters":[{"name":"status","in":"query","description":"Only this triage status.","schema":{"type":"string","enum":["new","ack","planned","done","declined"]}},{"name":"type","in":"query","description":"Only this kind of feedback.","schema":{"type":"string","enum":["bug","feature","praise","question"]}},{"name":"limit","in":"query","description":"Max items to return. Defaults to 50, capped at 200.","schema":{"type":"integer","minimum":1,"default":50}}],"responses":{"200":{"description":"The feedback inbox.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackList"}}}},"400":{"description":"Invalid status, type, or limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/healthz":{"get":{"tags":["meta"],"operationId":"healthCheck","summary":"Service health","description":"Liveness plus dependency checks: D1, and which optional bindings (events, media, browser, AI, ingest, vectors) and API keys are configured. 503 when the database is unreachable.","responses":{"200":{"description":"Healthy.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Health"}}}},"503":{"description":"Degraded — the database is unreachable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Health"}}}}}}},"/.well-known/mcp.json":{"get":{"tags":["meta"],"operationId":"mcpDiscovery","summary":"MCP server manifest","description":"Machine-readable manifest for the Model Context Protocol server at POST /mcp (Streamable HTTP, no authentication): server name, endpoint, transport, and advertised capabilities.","responses":{"200":{"description":"The MCP manifest.","content":{"application/json":{"schema":{"type":"object"}}}}}}}},"components":{"schemas":{"PromptSummary":{"type":"object","required":["slug","title","description","category","url","markdown_url"],"properties":{"slug":{"type":"string","description":"URL-safe identifier, e.g. weekend-scout-a48c78."},"title":{"type":"string"},"description":{"type":"string"},"category":{"type":"string","enum":["home","family","food","health","money","shopping","travel","calendar","social","learning","creative","work","business","coding","investing","setup","other"]},"verification":{"type":"string","description":"Static-scan verdict: verified or unverified."},"creator":{"type":"string","nullable":true,"description":"Creator handle, or null for anonymous."},"url":{"type":"string","format":"uri","description":"The prompt's HTML page."},"markdown_url":{"type":"string","format":"uri","description":"The full prompt as Markdown with YAML frontmatter."},"stats":{"type":"object","properties":{"copies":{"type":"integer"},"downloads":{"type":"integer"},"trending":{"type":"number"}}},"updated_at":{"type":"string","description":"ISO timestamp of the last update."}}},"PromptList":{"type":"object","required":["count","prompts"],"properties":{"count":{"type":"integer","description":"Rows in this page."},"prompts":{"type":"array","items":{"$ref":"#/components/schemas/PromptSummary"}}}},"FeedbackItem":{"type":"object","required":["id","type","status","title"],"properties":{"id":{"type":"integer"},"type":{"type":"string","enum":["bug","feature","praise","question"]},"status":{"type":"string","enum":["new","ack","planned","done","declined"]},"title":{"type":"string"},"body":{"type":"string"},"reporter":{"type":"string","description":"Display name, never an email."},"reporter_kind":{"type":"string","enum":["agent","human"]},"created_at":{"type":"string","description":"ISO timestamp."}}},"FeedbackList":{"type":"object","required":["feedback"],"properties":{"feedback":{"type":"array","items":{"$ref":"#/components/schemas/FeedbackItem"}}}},"Health":{"type":"object","required":["status","db"],"properties":{"status":{"type":"string","enum":["ok","degraded"]},"db":{"type":"string","enum":["ok","down"]},"bindings":{"type":"object","description":"Which optional bindings are configured.","additionalProperties":{"type":"boolean"}},"semantic_search":{"type":"string"},"keys":{"type":"object","description":"Which API keys are configured (booleans only, never the keys).","additionalProperties":{"type":"boolean"}}}},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Machine-readable error slug."}}}}}}