{"openapi":"3.1.0","info":{"title":"Oculo API","version":"1.0.0","description":"Self-hosted logs and errors. Agent guide: https://oculo-api.funonymous.in/llms.txt · Docs: https://oculo-api.funonymous.in/docs.md"},"servers":[{"url":"https://oculo-api.funonymous.in"}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"oc_read_… / oc_ingest_… / oc_admin_…"}},"schemas":{"Event":{"type":"object","properties":{"timestamp":{"type":"string","format":"date-time","description":"ISO time, or epoch s/ms/µs/ns. Default: now"},"level":{"type":"string","enum":["trace","debug","info","warn","error","fatal"]},"message":{"type":"string"},"logger":{"type":"string"},"service":{"type":"string"},"environment":{"type":"string"},"release":{"type":"string"},"host":{"type":"string"},"trace_id":{"type":"string"},"span_id":{"type":"string"},"user":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"}}},"attributes":{"type":"object","additionalProperties":true},"exception":{"type":"object","properties":{"type":{"type":"string"},"value":{"type":"string"},"stacktrace":{"type":"string"}}},"fingerprint":{"type":"array","items":{"type":"string"},"description":"Custom issue grouping; \"{{ default }}\" extends the default"}},"required":["message"]},"Alert":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string","enum":["threshold","spike","new_issue","regression","heartbeat","digest"],"description":"threshold: ≥threshold matching logs in window_min · spike: ≥threshold and 3× the previous 12 windows · new_issue · regression (resolved issue recurs) · heartbeat (missed check-in) · digest (daily summary)"},"query":{"type":"string","description":"threshold/spike only: query language filter, e.g. \"level:>=error service:api\""},"threshold":{"type":"integer","description":"threshold/spike: minimum count (default 10)"},"window_min":{"type":"integer","description":"threshold/spike: window in minutes (default 5)"},"channel":{"type":"string","enum":["webhook","slack","discord","email","telegram","pagerduty"],"description":"default webhook"},"target":{"type":"string","description":"webhook/slack/discord: http(s) URL · email: comma-separated addresses · telegram: chat id (e.g. -1001234567890) or @channel · pagerduty: not used"},"config":{"type":"object","properties":{"bot_token":{"type":"string","description":"telegram: bot token from @BotFather"},"routing_key":{"type":"string","description":"pagerduty: Events v2 integration key"},"hour":{"type":"integer","description":"digest: UTC hour 0-23 (default 9)"},"heartbeat":{"type":"string","description":"heartbeat: slug to watch (empty = all heartbeats)"}}},"cooldown_min":{"type":"integer","description":"minimum minutes between firings (default 30)"},"enabled":{"type":"boolean","description":"default true"}},"required":["type"]},"Error":{"type":"object","properties":{"error":{"type":"string"},"hint":{"type":"string"}},"required":["error"]}}},"security":[{"bearer":[]}],"paths":{"/api/v1/ingest":{"post":{"summary":"Send events: JSON array, single object, {\"events\":[…]} or NDJSON; gzip/deflate/br OK; ≤5000 events, ≤10 MB. Reply {accepted, dropped} (with a queue: {accepted, dropped:0, queued:true}).","tags":["Send logs"],"description":"Who can call it: ingest key (also read/write key, member or admin)","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"timestamp":{"type":"string","format":"date-time","description":"ISO time, or epoch s/ms/µs/ns. Default: now"},"level":{"type":"string","enum":["trace","debug","info","warn","error","fatal"]},"message":{"type":"string"},"logger":{"type":"string"},"service":{"type":"string"},"environment":{"type":"string"},"release":{"type":"string"},"host":{"type":"string"},"trace_id":{"type":"string"},"span_id":{"type":"string"},"user":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"}}},"attributes":{"type":"object","additionalProperties":true},"exception":{"type":"object","properties":{"type":{"type":"string"},"value":{"type":"string"},"stacktrace":{"type":"string"}}},"fingerprint":{"type":"array","items":{"type":"string"},"description":"Custom issue grouping; \"{{ default }}\" extends the default"}},"required":["message"]}},"example":[{"level":"error","message":"Payment failed","service":"api","attributes":{"orderId":8812}}]}}},"responses":{"202":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/v1/logs":{"post":{"summary":"OpenTelemetry OTLP/HTTP logs, protobuf or JSON (alias: /api/v1/otlp/v1/logs)","tags":["Send logs"],"description":"Who can call it: ingest key (also read/write key, member or admin)","responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/otlp/v1/logs":{"post":{"summary":"Same as /v1/logs","tags":["Send logs"],"description":"Who can call it: ingest key (also read/write key, member or admin)","responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/heartbeats/{slug}/ping":{"post":{"summary":"Cron check-in. ?period=1d (and ?grace=5m) creates the heartbeat on its first ping. GET also works.","tags":["Send logs"],"description":"Who can call it: ingest key (also read/write key, member or admin)","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}},{"name":"period","in":"query","schema":{"type":"string"}},{"name":"grace","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/summary":{"get":{"summary":"Project health: totals, by level, error_rate (a percent, 0-100) with change vs the previous window, top/new/regressed issues, top error messages, releases. Best first call.","tags":["Read"],"description":"Who can call it: any key or account with access to the project (read key is enough)","parameters":[{"name":"hours","in":"query","schema":{"type":"integer"},"description":"window, default 24"},{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"},{"name":"format","in":"query","schema":{"type":"string","enum":["json","md","text"]},"description":"Output format; md = compact tables for LLMs"},{"name":"fields","in":"query","schema":{"type":"string"},"description":"Comma-separated fields to keep per row (dot paths ok)"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/projects/{project}/summary":{"get":{"summary":"Same as /api/v1/summary for a given project","tags":["Read"],"description":"Who can call it: any key or account with access to the project (read key is enough)","parameters":[{"name":"project","in":"path","required":true,"schema":{"type":"string"}},{"name":"hours","in":"query","schema":{"type":"integer"}},{"name":"format","in":"query","schema":{"type":"string","enum":["json","md","text"]},"description":"Output format; md = compact tables for LLMs"},{"name":"fields","in":"query","schema":{"type":"string"},"description":"Comma-separated fields to keep per row (dot paths ok)"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/logs/search":{"get":{"summary":"Search logs, newest first. Reply {data, next_cursor, highlights (matched words), took_ms}.","tags":["Read"],"description":"Who can call it: any key or account with access to the project (read key is enough)","parameters":[{"name":"q","in":"query","schema":{"type":"string"},"description":"Query language, see \"Query language\""},{"name":"since","in":"query","schema":{"type":"string"},"description":"30m, 2h, 7d, ISO time or epoch ms"},{"name":"until","in":"query","schema":{"type":"string"},"description":"same formats as since"},{"name":"limit","in":"query","schema":{"type":"integer"},"description":"default 100, max 1000"},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"next_cursor from the previous page"},{"name":"order","in":"query","schema":{"type":"string","enum":["desc","asc"]}},{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"},{"name":"format","in":"query","schema":{"type":"string","enum":["json","md","text"]},"description":"Output format; md = compact tables for LLMs"},{"name":"fields","in":"query","schema":{"type":"string"},"description":"Comma-separated fields to keep per row (dot paths ok)"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/logs/{id}":{"get":{"summary":"One log","tags":["Read"],"description":"Who can call it: any key or account with access to the project (read key is enough)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"},{"name":"format","in":"query","schema":{"type":"string","enum":["json","md","text"]},"description":"Output format; md = compact tables for LLMs"},{"name":"fields","in":"query","schema":{"type":"string"},"description":"Comma-separated fields to keep per row (dot paths ok)"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/logs/{id}/context":{"get":{"summary":"One log, n logs before and after it, and its whole trace","tags":["Read"],"description":"Who can call it: any key or account with access to the project (read key is enough)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"n","in":"query","schema":{"type":"integer"},"description":"default 10, max 200"},{"name":"scope","in":"query","schema":{"type":"string","enum":["service","host"]},"description":"only neighbours from the same service/host"},{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"},{"name":"format","in":"query","schema":{"type":"string","enum":["json","md","text"]},"description":"Output format; md = compact tables for LLMs"},{"name":"fields","in":"query","schema":{"type":"string"},"description":"Comma-separated fields to keep per row (dot paths ok)"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/logs/histogram":{"get":{"summary":"Counts per time bucket by level, plus deploy markers","tags":["Read"],"description":"Who can call it: any key or account with access to the project (read key is enough)","parameters":[{"name":"q","in":"query","schema":{"type":"string"},"description":"Query language, see \"Query language\""},{"name":"since","in":"query","schema":{"type":"string"},"description":"30m, 2h, 7d, ISO time or epoch ms"},{"name":"until","in":"query","schema":{"type":"string"},"description":"same formats as since"},{"name":"buckets","in":"query","schema":{"type":"integer"},"description":"5-500, default 60"},{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"},{"name":"format","in":"query","schema":{"type":"string","enum":["json","md","text"]},"description":"Output format; md = compact tables for LLMs"},{"name":"fields","in":"query","schema":{"type":"string"},"description":"Comma-separated fields to keep per row (dot paths ok)"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/logs/facets":{"get":{"summary":"Top 15 values per field over the most recent matching logs","tags":["Read"],"description":"Who can call it: any key or account with access to the project (read key is enough)","parameters":[{"name":"q","in":"query","schema":{"type":"string"},"description":"Query language, see \"Query language\""},{"name":"since","in":"query","schema":{"type":"string"},"description":"30m, 2h, 7d, ISO time or epoch ms"},{"name":"until","in":"query","schema":{"type":"string"},"description":"same formats as since"},{"name":"facets","in":"query","schema":{"type":"string"},"description":"comma list of level,environment,service,release,logger,host,user,exception"},{"name":"sample","in":"query","schema":{"type":"integer"},"description":"logs scanned, default 100000"},{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"},{"name":"format","in":"query","schema":{"type":"string","enum":["json","md","text"]},"description":"Output format; md = compact tables for LLMs"},{"name":"fields","in":"query","schema":{"type":"string"},"description":"Comma-separated fields to keep per row (dot paths ok)"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/logs/export":{"get":{"summary":"Streamed export","tags":["Read"],"description":"Who can call it: any key or account with access to the project (read key is enough)","parameters":[{"name":"q","in":"query","schema":{"type":"string"},"description":"Query language, see \"Query language\""},{"name":"since","in":"query","schema":{"type":"string"},"description":"30m, 2h, 7d, ISO time or epoch ms"},{"name":"until","in":"query","schema":{"type":"string"},"description":"same formats as since"},{"name":"limit","in":"query","schema":{"type":"integer"},"description":"default 100000, max 1000000"},{"name":"as","in":"query","schema":{"type":"string","enum":["ndjson","csv"]}},{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/traces/{trace}":{"get":{"summary":"Every log in a trace, in order","tags":["Read"],"description":"Who can call it: any key or account with access to the project (read key is enough)","parameters":[{"name":"trace","in":"path","required":true,"schema":{"type":"string"}},{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"},{"name":"format","in":"query","schema":{"type":"string","enum":["json","md","text"]},"description":"Output format; md = compact tables for LLMs"},{"name":"fields","in":"query","schema":{"type":"string"},"description":"Comma-separated fields to keep per row (dot paths ok)"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/issues":{"get":{"summary":"Errors grouped into issues","tags":["Read"],"description":"Who can call it: any key or account with access to the project (read key is enough)","parameters":[{"name":"status","in":"query","schema":{"type":"string"},"description":"unresolved (default), resolved, ignored, all, or a comma list"},{"name":"sort","in":"query","schema":{"type":"string","enum":["last","freq","new","users"]}},{"name":"q","in":"query","schema":{"type":"string"},"description":"text in title/culprit"},{"name":"release","in":"query","schema":{"type":"string"}},{"name":"since","in":"query","schema":{"type":"string"},"description":"last seen within 30m/6h/7d"},{"name":"limit","in":"query","schema":{"type":"integer"},"description":"default 25, max 200"},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"next_cursor from the previous page"},{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"},{"name":"format","in":"query","schema":{"type":"string","enum":["json","md","text"]},"description":"Output format; md = compact tables for LLMs"},{"name":"fields","in":"query","schema":{"type":"string"},"description":"Comma-separated fields to keep per row (dot paths ok)"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/issues/{id}":{"get":{"summary":"Issue detail: latest event with stack trace, breadcrumbs, 48h and 30d timelines, releases, users, tags, recent events","tags":["Read"],"description":"Who can call it: any key or account with access to the project (read key is enough)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"},{"name":"format","in":"query","schema":{"type":"string","enum":["json","md","text"]},"description":"Output format; md = compact tables for LLMs"},{"name":"fields","in":"query","schema":{"type":"string"},"description":"Comma-separated fields to keep per row (dot paths ok)"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}},"patch":{"summary":"Change status and/or assignee","tags":["Triage"],"description":"Who can call it: read/write key, member/owner account, or admin key","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["unresolved","resolved","ignored"]},"assignee":{"type":["string","null"]}}},"example":{"status":"resolved","assignee":"alice"}}}},"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/issues/{id}/events":{"get":{"summary":"Events of one issue, newest first","tags":["Read"],"description":"Who can call it: any key or account with access to the project (read key is enough)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer"},"description":"default 50, max 500"},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"next_cursor from the previous page"},{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"},{"name":"format","in":"query","schema":{"type":"string","enum":["json","md","text"]},"description":"Output format; md = compact tables for LLMs"},{"name":"fields","in":"query","schema":{"type":"string"},"description":"Comma-separated fields to keep per row (dot paths ok)"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/releases":{"get":{"summary":"Releases with log and error counts","tags":["Read"],"description":"Who can call it: any key or account with access to the project (read key is enough)","parameters":[{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"},{"name":"format","in":"query","schema":{"type":"string","enum":["json","md","text"]},"description":"Output format; md = compact tables for LLMs"},{"name":"fields","in":"query","schema":{"type":"string"},"description":"Comma-separated fields to keep per row (dot paths ok)"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/releases/compare":{"get":{"summary":"What changed between releases a and b: new, increased, decreased and gone issues (defaults: the two latest)","tags":["Read"],"description":"Who can call it: any key or account with access to the project (read key is enough)","parameters":[{"name":"a","in":"query","schema":{"type":"string"}},{"name":"b","in":"query","schema":{"type":"string"}},{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"},{"name":"format","in":"query","schema":{"type":"string","enum":["json","md","text"]},"description":"Output format; md = compact tables for LLMs"},{"name":"fields","in":"query","schema":{"type":"string"},"description":"Comma-separated fields to keep per row (dot paths ok)"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/rollups":{"get":{"summary":"Total and error counts per day (or hour) from long-lived rollups","tags":["Read"],"description":"Who can call it: any key or account with access to the project (read key is enough)","parameters":[{"name":"days","in":"query","schema":{"type":"integer"},"description":"default 30, max 400"},{"name":"group","in":"query","schema":{"type":"string","enum":["day","hour"]}},{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"},{"name":"format","in":"query","schema":{"type":"string","enum":["json","md","text"]},"description":"Output format; md = compact tables for LLMs"},{"name":"fields","in":"query","schema":{"type":"string"},"description":"Comma-separated fields to keep per row (dot paths ok)"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/patterns":{"get":{"summary":"Log templates (variable parts as <*>) with counts and share; filter logs with pattern:<id>","tags":["Read"],"description":"Who can call it: any key or account with access to the project (read key is enough)","parameters":[{"name":"q","in":"query","schema":{"type":"string"},"description":"Query language, see \"Query language\""},{"name":"since","in":"query","schema":{"type":"string"},"description":"30m, 2h, 7d, ISO time or epoch ms"},{"name":"until","in":"query","schema":{"type":"string"},"description":"same formats as since"},{"name":"match","in":"query","schema":{"type":"string"},"description":"substring of the template"},{"name":"level","in":"query","schema":{"type":"string"},"description":"minimum level, e.g. warn"},{"name":"service","in":"query","schema":{"type":"string"}},{"name":"sort","in":"query","schema":{"type":"string","enum":["count","new","rare"]}},{"name":"limit","in":"query","schema":{"type":"integer"},"description":"default 50, max 500"},{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"},{"name":"format","in":"query","schema":{"type":"string","enum":["json","md","text"]},"description":"Output format; md = compact tables for LLMs"},{"name":"fields","in":"query","schema":{"type":"string"},"description":"Comma-separated fields to keep per row (dot paths ok)"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/metrics":{"get":{"summary":"Metric over time from logs. Reply {buckets[] (bucket start times), series[{group, values[] (one per bucket, null = no data), total (over the whole window), count}], interval_ms, rows_scanned, truncated}. Top 8 groups, the rest as \"other\".","tags":["Read"],"description":"Who can call it: any key or account with access to the project (read key is enough)","parameters":[{"name":"fn","in":"query","schema":{"type":"string","enum":["count","avg","sum","min","max","p50","p90","p95","p99"]},"description":"default count"},{"name":"field","in":"query","schema":{"type":"string"},"description":"numeric attribute for non-count fns, e.g. @duration_ms"},{"name":"group_by","in":"query","schema":{"type":"string"},"description":"service, environment, release, host, logger, level or @attr"},{"name":"q","in":"query","schema":{"type":"string"},"description":"Query language, see \"Query language\""},{"name":"since","in":"query","schema":{"type":"string"},"description":"default 24h"},{"name":"until","in":"query","schema":{"type":"string"},"description":"same formats as since"},{"name":"interval","in":"query","schema":{"type":"string"},"description":"5m, 1h, 1d (default: about 60 buckets)"},{"name":"buckets","in":"query","schema":{"type":"integer"},"description":"5-200, default 60"},{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"},{"name":"format","in":"query","schema":{"type":"string","enum":["json","md","text"]},"description":"Output format; md = compact tables for LLMs"},{"name":"fields","in":"query","schema":{"type":"string"},"description":"Comma-separated fields to keep per row (dot paths ok)"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/fields":{"get":{"summary":"Attribute keys seen in recent logs with their type (number/string)","tags":["Read"],"description":"Who can call it: any key or account with access to the project (read key is enough)","parameters":[{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"},{"name":"format","in":"query","schema":{"type":"string","enum":["json","md","text"]},"description":"Output format; md = compact tables for LLMs"},{"name":"fields","in":"query","schema":{"type":"string"},"description":"Comma-separated fields to keep per row (dot paths ok)"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/tail":{"get":{"summary":"Live tail, Server-Sent Events. With a key: Authorization header. Browsers: ?ticket= from POST /api/v1/tail/ticket","tags":["Read"],"description":"Who can call it: any key or account with access to the project (read key is enough)","parameters":[{"name":"q","in":"query","schema":{"type":"string"},"description":"Query language, see \"Query language\""},{"name":"ticket","in":"query","schema":{"type":"string"}},{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/tail/ticket":{"post":{"summary":"One-time 60 s ticket for /api/v1/tail?ticket=… (remembers key and project)","tags":["Read"],"description":"Who can call it: any key or account with access to the project (read key is enough)","parameters":[{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/heartbeats":{"get":{"summary":"Heartbeats with status (ok, late, waiting), next_due and ping_url","tags":["Read"],"description":"Who can call it: any key or account with access to the project (read key is enough)","parameters":[{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"},{"name":"format","in":"query","schema":{"type":"string","enum":["json","md","text"]},"description":"Output format; md = compact tables for LLMs"},{"name":"fields","in":"query","schema":{"type":"string"},"description":"Comma-separated fields to keep per row (dot paths ok)"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}},"post":{"summary":"Create a heartbeat (then add a \"heartbeat\" alert to be notified)","tags":["Set up"],"description":"Who can call it: read/write key, member/owner account, or admin key","parameters":[{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"slug":{"type":"string","description":"lowercase letters, digits, dashes"},"name":{"type":"string"},"period":{"type":["string","integer"],"description":"30m, 6h, 1d, 1w or seconds (1 minute to 90 days); default 1d"},"grace":{"type":["string","integer"],"description":"same formats; default 5m"}},"required":["slug"]},"example":{"slug":"nightly-backup","period":"1d","grace":"15m"}}}},"responses":{"201":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/sourcemaps":{"get":{"summary":"Uploaded source maps","tags":["Read"],"description":"Who can call it: any key or account with access to the project (read key is enough)","parameters":[{"name":"release","in":"query","schema":{"type":"string"}},{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}},"post":{"summary":"Upload a source map for one bundle of a release","tags":["Set up"],"description":"Who can call it: read/write key, member/owner account, or admin key","parameters":[{"name":"release","in":"query","required":true,"schema":{"type":"string"}},{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"file":{"type":"string","description":"bundle file name, e.g. app.3f9a1c.js"},"map":{"type":["object","string"],"description":"the source map JSON"}},"required":["map"]},"example":{"file":"app.3f9a1c.js","map":{"version":3,"sources":["…"],"mappings":"…"}}}}},"responses":{"201":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/saved-searches":{"get":{"summary":"Saved searches","tags":["Read"],"description":"Who can call it: any key or account with access to the project (read key is enough)","parameters":[{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}},"post":{"summary":"Save a search","tags":["Triage"],"description":"Who can call it: read/write key, member/owner account, or admin key","parameters":[{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"query":{"type":"string"}},"required":["name","query"]},"example":{"name":"API errors","query":"level:>=error service:api"}}}},"responses":{"201":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/explain/status":{"get":{"summary":"{enabled}: whether AI explanations are configured on this server","tags":["Read"],"description":"Who can call it: any key or account with access to the project (read key is enough)","parameters":[{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/issues/{id}/resolve":{"post":{"summary":"Mark resolved (reopens automatically as \"regressed\" if it happens again)","tags":["Triage"],"description":"Who can call it: read/write key, member/owner account, or admin key","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/issues/{id}/ignore":{"post":{"summary":"Mark ignored","tags":["Triage"],"description":"Who can call it: read/write key, member/owner account, or admin key","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/issues/{id}/unresolve":{"post":{"summary":"Reopen","tags":["Triage"],"description":"Who can call it: read/write key, member/owner account, or admin key","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/issues/{id}/explain":{"post":{"summary":"AI likely cause and fix (501 unless the server sets ANTHROPIC_API_KEY; issue data is sent to Anthropic). Cached; ?refresh=1 regenerates","tags":["Triage"],"description":"Who can call it: any key or account with access to the project (read key is enough)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"refresh","in":"query","schema":{"type":"string"}},{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/saved-searches/{id}":{"delete":{"summary":"Delete a saved search","tags":["Triage"],"description":"Who can call it: read/write key, member/owner account, or admin key","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/projects":{"post":{"summary":"Create a project. Reply {project, ingest_key, read_key} — keys are shown once.","tags":["Set up"],"description":"Who can call it: admin key or instance-admin account","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"slug":{"type":"string","description":"default: from name"},"retention_days":{"type":"integer","description":"1-3650, default 14"},"settings":{"type":"object"}},"required":["name"]},"example":{"name":"Shop API"}}}},"responses":{"201":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}},"get":{"summary":"Projects you can see, with your role and 24h stats","tags":["Set up"],"description":"Who can call it: any key or account with access to the project (read key is enough)","parameters":[{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"},{"name":"format","in":"query","schema":{"type":"string","enum":["json","md","text"]},"description":"Output format; md = compact tables for LLMs"},{"name":"fields","in":"query","schema":{"type":"string"},"description":"Comma-separated fields to keep per row (dot paths ok)"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/projects/{id}":{"get":{"summary":"One project","tags":["Set up"],"description":"Who can call it: any key or account with access to the project (read key is enough)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"project slug or numeric id"},{"name":"format","in":"query","schema":{"type":"string","enum":["json","md","text"]},"description":"Output format; md = compact tables for LLMs"},{"name":"fields","in":"query","schema":{"type":"string"},"description":"Comma-separated fields to keep per row (dot paths ok)"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}},"patch":{"summary":"Rename, retention, settings (merged into existing settings)","tags":["Set up"],"description":"Who can call it: owner account or admin key","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"project slug or numeric id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"retention_days":{"type":"integer"},"settings":{"type":"object","properties":{"scrubEmails":{"type":"boolean"},"extraKeys":{"type":"array","items":{"type":"string"}},"sampling":{"type":"object","description":"e.g. {\"debug\": 0.1}"},"dropMessages":{"type":"array","items":{"type":"string"}}}}}},"example":{"retention_days":30,"settings":{"sampling":{"debug":0.1},"dropMessages":["healthcheck"]}}}}},"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}},"delete":{"summary":"Delete a project and all its data","tags":["Set up"],"description":"Who can call it: owner account or admin key","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"project slug or numeric id"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/projects/{id}/keys":{"get":{"summary":"API keys (prefixes only)","tags":["Set up"],"description":"Who can call it: owner account or admin key","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"project slug or numeric id"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}},"post":{"summary":"Create a key. kind \"ingest\" (send only) or \"read\"; can_write:true makes a read/write key (oc_read_… that can also resolve issues, save searches, manage heartbeats, upload source maps). Reply {id, kind, key} — shown once.","tags":["Set up"],"description":"Who can call it: owner account or admin key","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"project slug or numeric id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"kind":{"type":"string","enum":["ingest","read"]},"name":{"type":"string"},"can_write":{"type":"boolean","description":"read keys only"}},"required":["kind"]},"example":{"kind":"read","name":"agent","can_write":false}}}},"responses":{"201":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/keys/{id}":{"delete":{"summary":"Revoke a key","tags":["Set up"],"description":"Who can call it: owner account or admin key","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/alerts":{"get":{"summary":"Alert rules (secrets masked)","tags":["Set up"],"description":"Who can call it: member/owner account or admin key (never project keys: alerts send outbound requests)","parameters":[{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}},"post":{"summary":"Create an alert rule","tags":["Set up"],"description":"Who can call it: member/owner account or admin key (never project keys: alerts send outbound requests)","parameters":[{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string","enum":["threshold","spike","new_issue","regression","heartbeat","digest"],"description":"threshold: ≥threshold matching logs in window_min · spike: ≥threshold and 3× the previous 12 windows · new_issue · regression (resolved issue recurs) · heartbeat (missed check-in) · digest (daily summary)"},"query":{"type":"string","description":"threshold/spike only: query language filter, e.g. \"level:>=error service:api\""},"threshold":{"type":"integer","description":"threshold/spike: minimum count (default 10)"},"window_min":{"type":"integer","description":"threshold/spike: window in minutes (default 5)"},"channel":{"type":"string","enum":["webhook","slack","discord","email","telegram","pagerduty"],"description":"default webhook"},"target":{"type":"string","description":"webhook/slack/discord: http(s) URL · email: comma-separated addresses · telegram: chat id (e.g. -1001234567890) or @channel · pagerduty: not used"},"config":{"type":"object","properties":{"bot_token":{"type":"string","description":"telegram: bot token from @BotFather"},"routing_key":{"type":"string","description":"pagerduty: Events v2 integration key"},"hour":{"type":"integer","description":"digest: UTC hour 0-23 (default 9)"},"heartbeat":{"type":"string","description":"heartbeat: slug to watch (empty = all heartbeats)"}}},"cooldown_min":{"type":"integer","description":"minimum minutes between firings (default 30)"},"enabled":{"type":"boolean","description":"default true"}},"required":["type"]},"example":{"name":"API errors","type":"threshold","query":"level:>=error service:api","threshold":10,"window_min":5,"channel":"slack","target":"https://hooks.slack.com/services/…","cooldown_min":30}}}},"responses":{"201":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/alerts/{id}":{"patch":{"summary":"Change any alert field (same body as create, all optional)","tags":["Set up"],"description":"Who can call it: member/owner account or admin key (never project keys: alerts send outbound requests)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string","enum":["threshold","spike","new_issue","regression","heartbeat","digest"],"description":"threshold: ≥threshold matching logs in window_min · spike: ≥threshold and 3× the previous 12 windows · new_issue · regression (resolved issue recurs) · heartbeat (missed check-in) · digest (daily summary)"},"query":{"type":"string","description":"threshold/spike only: query language filter, e.g. \"level:>=error service:api\""},"threshold":{"type":"integer","description":"threshold/spike: minimum count (default 10)"},"window_min":{"type":"integer","description":"threshold/spike: window in minutes (default 5)"},"channel":{"type":"string","enum":["webhook","slack","discord","email","telegram","pagerduty"],"description":"default webhook"},"target":{"type":"string","description":"webhook/slack/discord: http(s) URL · email: comma-separated addresses · telegram: chat id (e.g. -1001234567890) or @channel · pagerduty: not used"},"config":{"type":"object","properties":{"bot_token":{"type":"string","description":"telegram: bot token from @BotFather"},"routing_key":{"type":"string","description":"pagerduty: Events v2 integration key"},"hour":{"type":"integer","description":"digest: UTC hour 0-23 (default 9)"},"heartbeat":{"type":"string","description":"heartbeat: slug to watch (empty = all heartbeats)"}}},"cooldown_min":{"type":"integer","description":"minimum minutes between firings (default 30)"},"enabled":{"type":"boolean","description":"default true"}},"required":["type"]}}}},"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}},"delete":{"summary":"Delete an alert","tags":["Set up"],"description":"Who can call it: member/owner account or admin key (never project keys: alerts send outbound requests)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/alerts/{id}/test":{"post":{"summary":"Send a test notification now. Reply {ok, error?}","tags":["Set up"],"description":"Who can call it: member/owner account or admin key (never project keys: alerts send outbound requests)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/alerts/{id}/events":{"get":{"summary":"Last 50 deliveries with ok/error","tags":["Set up"],"description":"Who can call it: member/owner account or admin key (never project keys: alerts send outbound requests)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/heartbeats/{slug}":{"patch":{"summary":"Change name, period or grace","tags":["Set up"],"description":"Who can call it: read/write key, member/owner account, or admin key","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}},{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"period":{"type":"string"},"grace":{"type":"string"}}}}}},"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}},"delete":{"summary":"Delete a heartbeat","tags":["Set up"],"description":"Who can call it: read/write key, member/owner account, or admin key","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}},{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/sourcemaps/{id}":{"delete":{"summary":"Delete a source map","tags":["Set up"],"description":"Who can call it: read/write key, member/owner account, or admin key","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/me":{"get":{"summary":"Who am I (key kind or user, role, project)","tags":["People and accounts"],"description":"Who can call it: any key or account with access to the project (read key is enough)","parameters":[{"name":"project","in":"query","schema":{"type":"string"},"description":"Project slug, for admin keys and accounts with several projects"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/projects/{id}/members":{"get":{"summary":"Members and roles","tags":["People and accounts"],"description":"Who can call it: any key or account with access to the project (read key is enough)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"project slug or numeric id"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/projects/{id}/members/{userId}":{"patch":{"summary":"Change a member's role","tags":["People and accounts"],"description":"Who can call it: owner account or admin key","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"project slug or numeric id"},{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"role":{"type":"string","enum":["viewer","member","owner"]}},"required":["role"]},"example":{"role":"member"}}}},"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}},"delete":{"summary":"Remove a member (members may remove themselves)","tags":["People and accounts"],"description":"Who can call it: owner account or admin key","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"project slug or numeric id"},{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/projects/{id}/invites":{"post":{"summary":"Create an invite link (7 days, single use). Reply {url}; send it to the person","tags":["People and accounts"],"description":"Who can call it: owner account or admin key","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"project slug or numeric id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string"},"role":{"type":"string","enum":["viewer","member","owner"],"description":"default member"}},"required":["email"]},"example":{"email":"friend@example.com","role":"member"}}}},"responses":{"201":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}},"get":{"summary":"Pending invites","tags":["People and accounts"],"description":"Who can call it: owner account or admin key","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"project slug or numeric id"}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/projects/{id}/invites/{email}":{"delete":{"summary":"Cancel an invite","tags":["People and accounts"],"description":"Who can call it: owner account or admin key","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"project slug or numeric id"},{"name":"email","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/invites/{token}":{"get":{"summary":"Invite details","tags":["People and accounts"],"description":"Who can call it: no key","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[]}},"/api/v1/invites/{token}/accept":{"post":{"summary":"Join the project as the invited role","tags":["People and accounts"],"description":"Who can call it: signed-in account (session cookie)","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/auth/config":{"get":{"summary":"{github, has_users, signup_open, ingest_url}","tags":["People and accounts"],"description":"Who can call it: no key","responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[]}},"/api/v1/auth/signup":{"post":{"summary":"Create an account (browser only, same-origin). The first account becomes instance admin; later ones need an invite","tags":["People and accounts"],"description":"Who can call it: no key","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string"},"password":{"type":"string","description":"at least 10 characters"},"name":{"type":"string"},"invite":{"type":"string"}},"required":["email","password"]}}}},"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[]}},"/api/v1/auth/login":{"post":{"summary":"Sign in (browser only, sets a session cookie)","tags":["People and accounts"],"description":"Who can call it: no key","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string"},"password":{"type":"string"}},"required":["email","password"]}}}},"responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[]}},"/api/v1/auth/logout":{"post":{"summary":"Sign out","tags":["People and accounts"],"description":"Who can call it: signed-in account (session cookie)","responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key"},"403":{"description":"Not allowed for this key or role"}}}},"/api/v1/auth/github/start":{"get":{"summary":"Start \"Continue with GitHub\" (when configured)","tags":["People and accounts"],"description":"Who can call it: no key","responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[]}},"/api/v1/auth/github/callback":{"get":{"summary":"GitHub OAuth callback","tags":["People and accounts"],"description":"Who can call it: no key","responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[]}},"/healthz":{"get":{"summary":"{ok, storage, queue, outbox_rows?, queue_backlog?}","tags":["Meta"],"description":"Who can call it: no key","responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[]}},"/llms.txt":{"get":{"summary":"This guide","tags":["Meta"],"description":"Who can call it: no key","responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[]}},"/openapi.json":{"get":{"summary":"OpenAPI 3.1 description of every endpoint","tags":["Meta"],"description":"Who can call it: no key","responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[]}},"/docs":{"get":{"summary":"Full documentation (HTML)","tags":["Meta"],"description":"Who can call it: no key","responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[]}},"/docs.md":{"get":{"summary":"Full documentation (Markdown)","tags":["Meta"],"description":"Who can call it: no key","responses":{"200":{"description":"OK"},"400":{"description":"Bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[]}}}}