Reference
API conventions
Authentication, the response envelope, errors and field naming — the rules every endpoint follows.
Base URL: https://api.catchook.com
Every endpoint, schema and response is listed in the
API reference, generated from the same OpenAPI document
the API serves at /openapi.json.
This page covers the rules that apply across all of them.
Authentication
Every request carries an API key:
curl https://api.catchook.com/endpoints \
-H "Authorization: Bearer ck_live_..."
Keys are scoped to a project and shown once, at creation. There is no way to recover one afterwards — rotate instead.
Your organization is never a parameter. It is resolved from the key, or from the active organization of a dashboard session. A key can only ever see its own organization’s data, so there is no cross-tenant identifier to get wrong.
Response envelope
Every successful response has the same shape:
{
"data": { "id": "end_60e42bf9513149f2b89dddaa779079a4" },
"timestamp": "2026-08-29T10:04:11.284Z"
}
Lists add pagination:
{
"data": [],
"pagination": { "limit": 20, "cursor": "..." },
"timestamp": "2026-08-29T10:04:11.284Z"
}
Errors replace data entirely:
{
"error": { "code": "endpoint_not_found", "message": "No endpoint with that id" },
"timestamp": "2026-08-29T10:04:11.284Z"
}
Branch on error.code, never on error.message — messages are written for
humans and get reworded.
Field naming
JSON fields are snake_case on the wire: project_id, receiver_url,
created_at, retry_max_attempts.
Resources
/projects | Environments within an organization. One is created with the org |
/endpoints | Inbound URLs. Create, pause, resume, rotate secret |
/endpoints/:id/destinations | Fan-out targets for an endpoint |
/api-keys | Create, list and delete keys, scoped to a project |
/events | Recent events, filterable by endpoint and time |
/events/:id/replay | Re-send one event to its destinations |
Rate limits and sizes
| Receive, per endpoint | 12,000 requests/minute (~200/sec) |
| Request body | 100 KB |
retry_max_attempts | 10 |
| Event retention | 14 days |
Reading events
/events is backed by a column store, and two flags change what it costs:
payload=1includes headers and the raw body. Without it you get metadata only, which is much cheaper for a list view.delivery_summary=falseskips the per-event delivery rollup, saving a second query when you are not rendering that column.