Event Drains
Event drains stream delivery-lifecycle events out of Hooksbase into external observability or journaling systems. Use them when you need a near-real-time feed of delivery state changes outside the dashboard itself.
Available through
Event drain management is available in the dashboard, SDK, CLI, and project-authenticated API routes despite the /v1/app path prefix.
Dashboard
PreferredCreate, inspect, pause, resume, edit, and delete drains from project settings.
Public API
AvailableUse project API keys against /v1/app/event-drains when you need raw HTTP automation.
TypeScript SDK
AvailableUse client.eventDrains for list, create, get, update, pause, resume, and delete.
CLI
AvailableUse hooksbase event-drains for terminal automation.
Drain model
Drains subscribe to delivery lifecycle events, not arbitrary webhook payloads. The current event types are:
-
delivery.created -
attempt.completed -
delivery.succeeded -
delivery.failed -
delivery.dlq_entered
Tiering:
- Free and Starter cannot create drains
- Pro allows one drain
- Business allows three drains
- Enterprise is effectively unbounded
You can optionally scope a drain to a subset of webhook IDs instead of the whole project.
Where this lives
Event drain management is dashboard-first, and the dashboard is the preferred surface. Open the event drains section from project settings to:
- create a drain (pick a sink type, provide credentials, choose event types, optionally scope to specific webhooks)
- inspect the drain's current status, recent failure count, and last error
- pause or resume a drain
- edit sink configuration and credentials
- delete a drain
There is also a low-level project-authenticated route family under
/v1/app/event-drains. Despite the /v1/app prefix,
these routes use project API key auth and are available through the SDK and CLI.
Sink types and events
Supported sink types:
webhook— POST each event to an HTTPS URL, optionally signedaxiom— forward events to an Axiom datasetdatadog— forward events to Datadog Logsobject_storage— write one JSON object per event to S3-compatible storageotlp_http— emit events as OpenTelemetry Logs over OTLP/HTTP JSON
Behavior notes:
- webhook drains can include an optional signing secret; Hooksbase sends the
HMAC in
x-signature-sha256 - object-storage drains write one JSON object per drain event
- OTLP HTTP drains are logs-only, JSON-only, and do not batch or backfill
Because drains are delivery-lifecycle observers, they pair naturally with operator alerting: drains give you raw event streams, while operator alerting gives you customer-facing incident state and routing.
API, SDK, and CLI examples
Create, patch, and resume require Pro+. List, get, pause, and delete are still project-authenticated, but lower-tier projects do not process active drains.
Create a webhook drain with the SDK
await client.eventDrains.create({
name: 'Delivery stream',
sinkType: 'webhook',
sinkConfig: {
url: 'https://observability.example.com/hooksbase',
signingSecret: 'drain-secret',
},
eventTypes: ['delivery.created', 'attempt.completed', 'delivery.failed'],
filterWebhookIds: ['wh_123'],
})
Create a webhook drain with the CLI
hooksbase event-drains create --file ./event-drain.json
Create a webhook drain
curl https://api.hooksbase.com/v1/app/event-drains \
-H "Authorization: Bearer swk_..." \
-H "Content-Type: application/json" \
-d '{
"name": "Delivery stream",
"sinkType": "webhook",
"sinkConfig": {
"url": "https://observability.example.com/hooksbase",
"signingSecret": "drain-secret"
},
"eventTypes": [
"delivery.created",
"attempt.completed",
"delivery.failed"
],
"filterWebhookIds": ["wh_123"]
}'
201 response
{
"id": "drain_123",
"projectId": "proj_123",
"name": "Delivery stream",
"status": "active",
"sinkType": "webhook",
"eventTypes": [
"delivery.created",
"attempt.completed",
"delivery.failed"
],
"filterWebhookIds": ["wh_123"],
"consecutiveFailures": 0,
"lastSuccessAt": null,
"lastFailureAt": null,
"createdAt": 1766600000000,
"updatedAt": 1766600000000
}
Patch event types or sink config
curl -X PATCH https://api.hooksbase.com/v1/app/event-drains/drain_123 \
-H "Authorization: Bearer swk_..." \
-H "Content-Type: application/json" \
-d '{
"eventTypes": [
"delivery.created",
"attempt.completed",
"delivery.succeeded",
"delivery.failed",
"delivery.dlq_entered"
],
"sinkConfig": {
"url": "https://observability.example.com/hooksbase-v2"
}
}'
Pause, resume, and delete
curl -X POST https://api.hooksbase.com/v1/app/event-drains/drain_123/pause \
-H "Authorization: Bearer swk_..."
curl -X POST https://api.hooksbase.com/v1/app/event-drains/drain_123/resume \
-H "Authorization: Bearer swk_..."
curl -X DELETE https://api.hooksbase.com/v1/app/event-drains/drain_123 \
-H "Authorization: Bearer swk_..."
See raw HTTP examples for copy-ready HTTP requests for this route family.
Patch and failure behavior
When editing an existing drain, the dashboard uses merge semantics for credentials:
- leaving object-storage credentials blank keeps the existing encrypted values
- optional object-storage fields can be cleared with an explicit empty value
- leaving OTLP headers blank keeps the saved headers
- clearing OTLP headers is an explicit action in the UI
Failure behavior:
- a drain moves to
failedafter10consecutive failures - resume returns it to
activeand resets the consecutive-failure counter - paused or failed drains can still be inspected, edited, resumed, or deleted
- drain failures can surface into operator issues such as
drain_pausedanddrain_degraded
Common mistakes
- Assuming drains stream original inbound payloads instead of delivery lifecycle events.
- Treating the
/v1/app/event-drainsprefix as browser-session auth. These event-drain routes use project API keys for automation. - Forgetting that editing a drain's credentials preserves saved values unless you explicitly clear them.
- Expecting drains to replace operator alerting. They serve different operator workflows.
- Treating the dashboard's browser traffic as an integration contract.