API Reference
Hookbase provides a RESTful API for managing all aspects of your webhook infrastructure.
Interactive API Explorer
Try out endpoints directly from your browser with the API Explorer. Browse schemas, view examples, and send test requests — no setup required.
Postman Collection
Download the Postman Collection for quick API exploration.
OpenAPI Specification
Download the OpenAPI 3.0 Spec for SDK generation, API testing tools, and automated documentation.
Compatible with tools like Swagger UI, Redocly, and any OpenAPI code generator.
Base URL
https://api.hookbase.appAuthentication
All API requests require authentication. See Authentication for details.
URL Patterns
Hookbase supports two URL patterns for API requests:
API Key Authentication (Recommended)
When using an API key, the organization is inferred automatically from the key — no need to include an organization ID in the URL:
curl https://api.hookbase.app/api/sources \
-H "Authorization: Bearer whr_your_api_key"JWT Authentication
When using JWT tokens (e.g. from the dashboard), you must include the organization ID in the path:
curl https://api.hookbase.app/api/organizations/{orgId}/sources \
-H "Authorization: Bearer your_jwt_token"Tip
All examples in this documentation use the simplified API key pattern. If you're using JWT authentication, prefix the resource path with /api/organizations/{orgId}
Resource ID Format
Every inbound resource — organizations, sources, destinations, routes, events, deliveries, filters, transforms, schemas, cron jobs, tunnels, API keys, custom domains, notification channels and users — is identified by a plain UUID v4:
11111111-1111-4111-8111-111111111111There are no prefixed IDs on the inbound API. If you see something like src_abc123 or
rte_main456 in your own code or in an older copy of these docs, it is not a Hookbase ID and will
not resolve.
The outbound (send) API is a separate resource tree, but its IDs (applications, endpoints, subscriptions, event types, messages, attempts) are plain UUIDs too.
The prefixed values you will see are secrets and keys, not resource IDs:
| Prefix | What it is |
|---|---|
whr_ | An API key's secret value, used in the Authorization header. The key's own ID is a UUID. |
whsec_ | An outbound endpoint's HMAC signing secret (v1 signatures). |
whpk_ | An outbound endpoint's Ed25519 public key (v1a signatures), for endpoints with signatureScheme: "ed25519". |
Slugs are separate from IDs. A source is addressed by its slug in its ingest URL
(/ingest/{orgSlug}/{sourceSlug}) but by its UUID everywhere in this API.
Request Format
- All requests should use
Content-Type: application/json - Request bodies should be JSON-encoded
- URL parameters should be URL-encoded
Response Format
All responses are JSON-encoded. Every response is wrapped in a key named after the resource —
there is no generic data envelope.
Success Response
A single resource comes back under its singular name:
{
"source": {
"id": "11111111-1111-4111-8111-111111111111",
"name": "My Source",
"createdAt": "2024-01-15T10:30:00Z"
}
}A collection comes back under its plural name:
{
"sources": [...],
"pagination": {
"total": 100,
"page": 1,
"pageSize": 20
}
}So GET /api/routes returns { "routes": [...] }, GET /api/destinations returns
{ "destinations": [...] }, and so on. Two endpoints name their collection differently from their
URL: /api/notification-channels returns { "channels": [...] } and /api/audit-logs returns
{ "logs": [...] }.
Not every collection is paginated. Sources, routes, destinations, transforms and filters carry the
pagination object above; schemas, notification channels, cron groups, custom domains and
redaction policies return the array alone. Audit logs use flat total, limit and offset fields
rather than a nested object.
A write that has nothing to return answers { "success": true } — that includes PATCH and
DELETE on a source.
Error Response
{
"error": "Source not found"
}error is always present and always a human-readable string. Two optional fields accompany it:
code, a stable identifier such as FEATURE_DISABLED, LIMIT_EXCEEDED or VALIDATION_ERROR, and
details, which carries the field-level breakdown when a request body fails validation:
{
"error": "Invalid input",
"details": {
"formErrors": [],
"fieldErrors": {
"slug": ["Required"]
}
}
}An unrecognised field is a validation error too — the API rejects unknown keys rather than ignoring
them, so a misspelled field name is a 400 and not a silently dropped setting.
HTTP Status Codes
| Code | Description |
|---|---|
| 200 | Success |
| 201 | Created |
| 204 | No Content (successful deletion) |
| 400 | Bad Request (invalid input) |
| 401 | Unauthorized (missing or invalid auth) |
| 403 | Forbidden (insufficient permissions) |
| 404 | Not Found |
| 409 | Conflict (duplicate resource) |
| 422 | Unprocessable Entity (validation error) |
| 429 | Too Many Requests (rate limited) |
| 500 | Internal Server Error |
Rate Limits
Event limits vary by plan:
| Plan | Events/month |
|---|---|
| Free | 1,000 |
| Starter | 25,000 |
| Pro | 500,000 |
| Business | 2,000,000 |
See Pricing for full plan details.
Pagination
List endpoints support pagination:
GET /api/sources?page=1&pageSize=20| Parameter | Default | Max |
|---|---|---|
| page | 1 | - |
| pageSize | 20 | 100 |
Filtering
Many list endpoints support filtering:
GET /api/events?status=delivered&sourceId=11111111-1111-4111-8111-111111110008Sorting
Sort results using the sort parameter:
GET /api/events?sort=-createdAtPrefix with - for descending order.
API Endpoints
Core Resources
| Resource | Description |
|---|---|
| Sources | Webhook receive endpoints |
| Destinations | Delivery targets |
| Routes | Source to destination mappings |
| Events | Received webhook events |
| Deliveries | Delivery attempts and status |
Webhook Ingest
| Endpoint | Description |
|---|---|
| Webhook Ingest | Public endpoint for receiving webhooks |
| Provider Catalog | Public list of supported providers and their signature/secret rules |
Authentication & Access
| Resource | Description |
|---|---|
| Authentication | JWT tokens and session management |
| API Keys | Programmatic access tokens |
Development Tools
| Resource | Description |
|---|---|
| Tunnels | Local development tunnels |
Advanced Features
| Resource | Description |
|---|---|
| Transforms | Payload transformation functions |
| Filters | Conditional routing rules |
| Schemas | Payload validation schemas |
| Cron Jobs | Scheduled webhook triggers |
SDKs
Official SDKs are available for:
| Language | Package | Requires | Install |
|---|---|---|---|
| Node.js / TypeScript | @hookbase/sdk | Node.js 18+ | npm install @hookbase/sdk |
| Python | hookbase | Python 3.9+ | pip install hookbase |
| Go | github.com/HookbaseApp/hookbase-go | Go 1.21+ | go get github.com/HookbaseApp/hookbase-go |
| .NET | Hookbase | .NET 8+ | dotnet add package Hookbase |
| Java | app.hookbase:hookbase-java | Java 25+ | Gradle: implementation("app.hookbase:hookbase-java:1.1.0") |
See the SDK references for Node.js, Python, Go, .NET and Java.
Quick Examples
Create a Source
curl -X POST https://api.hookbase.app/api/sources \
-H "Authorization: Bearer whr_your_api_key" \
-H "Content-Type: application/json" \
-d '{"name": "GitHub", "slug": "github"}'List Events
curl https://api.hookbase.app/api/events \
-H "Authorization: Bearer whr_your_api_key"Replay an Event
Events are not replayed directly — replay is a delivery-level operation. To redeliver one event, pass its id to the bulk endpoint:
curl -X POST https://api.hookbase.app/api/deliveries/bulk-replay-events \
-H "Authorization: Bearer whr_your_api_key" \
-H "Content-Type: application/json" \
-d '{"eventIds": ["{eventId}"]}'Pass either eventIds or a since/until window, never both — sending both is a 400
(REPLAY_TARGET_AMBIGUOUS) and sending neither is a 400 (REPLAY_TARGET_MISSING). To replay a
single delivery instead, use POST /api/deliveries/{deliveryId}/replay.