API reference
Every REST endpoint: method, path, body fields, units consumed, and phase. The base URL is https://api.discatch.com.
Auth: Authorization: Bearer dk_live_... on every request. Keys are scoped: read, search, catches:write, billing:read. The MCP server uses OAuth 2.1 with PKCE when it ships.
POST /v1/quote
Price a request without running it. Body is any of the request bodies below. Returns a ceiling with locked unit prices; the charge never exceeds the ceiling.
| Field | Type | Notes |
|---|---|---|
| query | string | Boolean syntax: AND, OR, NOT, quotes, -term |
| sources | string[] | Source names from GET /v1/sources |
| since | string | 24h, 7d, or RFC 3339 |
| limit | int | Max results, default 25 |
Units consumed: none. The quote itself is free.
POST /v1/search
One-off search across the waterfall. Returns quote, results, and coverage.
| Field | Type | Notes |
|---|---|---|
| query | string | Boolean syntax |
| sources | string[] | web, news, hackernews, discourse, stackexchange, github in phase 1b |
| since | string | 24h, 7d, RFC 3339 |
| limit | int | Max results, default 25 |
| classify | bool | Opt-in classification |
| coverage | string | fast or deep. deep lets the waterfall go further |
| budget_usd | number | Hard cap. The planner stops before exceeding it |
| dry_run | bool | Quote only, same as POST /v1/quote |
| quote_id | string | Lock a previous quote |
Units consumed: search (per call), result (per matched item). With classify: classify (per result classified).
POST /v1/capture
Fetch one URL with thread context. Returns a single Result with body populated.
| Field | Type | Notes |
|---|---|---|
| url | string | The URL to fetch |
| include_replies | bool | Include reply thread |
Units consumed: capture (per call).
POST /v1/classify
Classify results you already have against your own criteria.
| Field | Type | Notes |
|---|---|---|
| results | Result[] | The results to classify |
| criteria | string | What relevant means for you: bug, question, feature request, or any labels |
Units consumed: classify (per result).
Catches
| Method | Path | Purpose | Units |
|---|---|---|---|
| POST | /v1/catches | Create a catch | alert on each firing, result per item |
| GET | /v1/catches | List catches | none |
| GET | /v1/catches/{id} | Read one, including last run and delivery status | none |
| PATCH | /v1/catches/{id} | Update query, sources, interval, destination | none |
| POST | /v1/catches/{id}/pause | Pause | none |
| POST | /v1/catches/{id}/resume | Resume | none |
| POST | /v1/catches/{id}/test | Fire the destination with a sample payload | none |
| DELETE | /v1/catches/{id} | Delete | none |
| GET | /v1/catches/{id}/results | Results delivered so far | none |
| GET | /v1/catches/{id}/deliveries | Delivery log with outcomes | none |
Create body
POST /v1/catches
{
"name": "string",
"query": "string",
"sources": ["hackernews", "discourse"],
"interval": "5m | 15m | 1h | 6h | 24h",
"classify": false,
"min_prescore": 0.3,
"destination": { "type": "webhook", "url": "https://...", "secret": "whsec_..." }
}Destination types: webhook, claude_code, codex, doozy, github_dispatch, pane, email, slack.
Events
| Method | Path | Purpose | Units |
|---|---|---|---|
| GET | /v1/events?since=&catch=&type=&min_prescore=&limit=&wait= | Read the event log from a cursor. wait long-polls | none |
| GET | /v1/events/stream | SSE, resumable with Last-Event-ID | none |
| POST | /v1/subscriptions | Route events to a webhook, Doozy, GitHub dispatch, Pane, email, Slack | none |
| GET | /v1/subscriptions | List with delivery health | none |
| DELETE | /v1/subscriptions/{id} | Remove | none |
| GET | /v1/subscriptions/{id}/deliveries | Delivery log and dead letters | none |
Other endpoints
| Method | Path | Purpose | Units |
|---|---|---|---|
| GET | /v1/doctor | The orientation manifest | none |
| POST | /v1/keys/trial | Get a trial key with no email and no card | none |
| POST | /v1/keys/claim | Attach an email to a trial key | none |
| GET | /v1/sources | Sources with current availability | none |
| GET | /v1/usage | Units consumed this period, by kind, with spend | none |
Errors
Every error is { code, message, next_action, docs_url, request_id }. Agents act on next_action. 402 says the unit price refused and how to add funds. 429 says when to retry.
| Code | Meaning |
|---|---|
| unauthorized | Missing or invalid key |
| scope_missing | Key lacks the required scope |
| budget_exceeded | The quote exceeds budget_usd |
| quote_expired | The quote_id is no longer valid |
| source_unavailable | A requested source is down or not yet available |
| invalid_query | Query syntax error |
| rate_limited | Too many requests. Retry after the header says |
| destination_failed | The catch destination could not be reached |
Last reviewed by Parsa Khazaeepoul, founder, dcouple. Copy from docs/onboarding.md, docs/query-language.md, docs/events.md, docs/api.md.