The HookDeploy REST API provides programmatic access to endpoints, captured requests, replays, and usage metrics at https://api.hookdeploy.dev/v1.
Base URL
https://api.hookdeploy.dev/v1
All routes are prefixed with /v1. The API runs on a dedicated Cloudflare Worker separate from the ingestion Worker at hookdeploy.dev/h/*.
Authentication
Every request — including GET /v1/health — requires an API key in the Authorization header:
Authorization: Bearer hd_live_<your-key>
API keys are created in the dashboard under Settings → API Keys. The full key is shown once on creation. After that, only the key prefix is visible.
Keys are validated by SHA-256 hash against the database. Validation results are cached in KV for 30 seconds.
Invalid, expired, or revoked keys return:
HTTP/1.1 401 Unauthorized
{
"error": {
"code": "unauthorized",
"message": "Invalid or missing API key."
}
}
See API keys for creation and security best practices.
Rate limits
Rate limits apply per API key, per minute (UTC):
| Plan | Requests/minute |
|---|---|
| free | 60 |
| starter | 120 |
| team | 300 |
| enterprise | 1000 |
Every response includes rate limit headers:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 47
X-RateLimit-Reset: 1716912060
X-RateLimit-Reset is a Unix timestamp (seconds) for the start of the next minute bucket.
When exceeded:
HTTP/1.1 429 Too Many Requests
{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded."
}
}
API rate limits are separate from webhook ingestion limits (requests/month on your plan).
Response format
Success
Single resources:
{
"data": { ... }
}
Created resources return HTTP 201. Deletes return HTTP 204 with no body.
Paginated lists
{
"data": [ ... ],
"pagination": {
"next_cursor": "uuid-or-null"
}
}
Pass before=<request-id> as a query parameter to fetch the next page. next_cursor is null when there are no more results.
Errors
{
"error": {
"code": "not_found",
"message": "Endpoint not found."
}
}
Error codes
| HTTP | Code | Description |
|---|---|---|
| 400 | bad_request | Invalid input or malformed JSON |
| 401 | unauthorized | Missing or invalid API key |
| 404 | not_found | Route, endpoint, or request not found |
| 429 | rate_limited | Per-key rate limit exceeded |
| 429 | plan_limit | Plan limit reached (e.g. max endpoints) |
| 500 | internal_error | Unexpected server error |
Health check
Verify API connectivity and key validity:
curl -s "https://api.hookdeploy.dev/v1/health" \
-H "Authorization: Bearer hd_live_YOUR_KEY"
{
"data": {
"status": "ok",
"version": "1"
}
}
Available routes
| Method | Route | Description |
|---|---|---|
| GET | /v1/health | Health check |
| GET | /v1/endpoints | List endpoints |
| POST | /v1/endpoints | Create endpoint |
| GET | /v1/endpoints/:id | Get endpoint |
| PATCH | /v1/endpoints/:id | Update endpoint |
| DELETE | /v1/endpoints/:id | Delete endpoint |
| GET | /v1/endpoints/:id/requests | List requests |
| GET | /v1/endpoints/:id/requests/:requestId | Get request |
| POST | /v1/endpoints/:id/requests/:requestId/replay | Replay request |
| GET | /v1/usage | Current usage and limits |
Architecture notes
- No
@supabase/supabase-js— all database access uses nativefetchagainst PostgREST - Auth cache: KV key
auth:{sha256-hash}, TTL 30s - Rate limit buckets: KV key
rl:api:{keyId}:{YYYYMMDDHHMM}, TTL 2 minutes - Payload fetch for replays: ingestion Worker at
/internal/payload/{key}usingINTERNAL_SECRET body_r2_keyis never returned in API responses
Next steps
- Endpoints API — CRUD operations
- Requests API — List and get captured requests
- API keys — Create and manage keys