Hooks API
Base path: /api/hooks
All endpoints require authentication. See API Overview for auth details.
List hooks
Section titled “List hooks”GET /api/hooksResponse:
{ "hooks": [ { "id": "hook_abc123", "name": "Slack task alerts", "event_type": "task.failed", "hook_type": "http", "enabled": true, "scope": "global", "config": {"url": "https://hooks.slack.com/...", "method": "POST"}, "filter_expr": null, "priority": 0, "tags": [], "created_at": "2026-01-01T00:00:00Z" } ]}Create a hook
Section titled “Create a hook”POST /api/hooksHTTP hook (outbound webhook):
{ "name": "Notify on task failure", "event_type": "task.failed", "hook_type": "http", "config": { "url": "https://your-server.com/webhook", "secret": "your-hmac-secret-min-32-chars-long", "headers": {"X-Source": "snippbot"}, "queued": true, "retry_delay_s": 10, "retry_multiplier": 2.0, "max_delay_s": 3600 }, "max_retries": 5, "filter_expr": {"field": "data.agent_id", "op": "eq", "value": "agent_123"}}Python hook (execute Python code):
{ "name": "Log task completion", "event_type": "task.completed", "hook_type": "python", "source_code": "print(event['data']['task_id'])"}Builtin hook (built-in action):
{ "name": "Announce on Slack", "event_type": "project.updated", "hook_type": "builtin", "config": { "channel": "slack:#general", "template": "Project {{data.name}} moved to {{data.status}}" }}Returns 201 with the created hook object directly.
Get a hook
Section titled “Get a hook”GET /api/hooks/{id}Update a hook
Section titled “Update a hook”PUT /api/hooks/{id}Send only fields to update:
{"enabled": false}To toggle enabled state only, use the dedicated endpoint:
PATCH /api/hooks/{id}/toggleDelete a hook
Section titled “Delete a hook”DELETE /api/hooks/{id}Returns {"success": true}.
Test a hook
Section titled “Test a hook”POST /api/hooks/{id}/testFires the hook with a synthetic test event. Returns the execution record:
{ "id": "exec_abc123", "hook_id": "hook_abc123", "event_type": "task.failed", "started_at": "2026-03-02T14:00:00Z", "completed_at": "2026-03-02T14:00:00.045Z", "duration_ms": 45, "status": "success"}Events
Section titled “Events”List bundled hooks
Section titled “List bundled hooks”GET /api/hooks/bundledReturns built-in hooks that ship with Snippbot.
List available events
Section titled “List available events”GET /api/hooks/event-typesReturns all hookable event types grouped by category:
{ "event_types": { "task": ["task.queued", "task.started", "task.completed", "task.failed", "task.retrying", "task.skipped"], "project": ["project.created", "project.updated", "project.deleted", "project.completed"], "memory": ["memory.stored", "memory.consolidated", "memory.recalled"],
"channel": ["channel.message.received", "channel.message.sent", "channel.message.failed"], "scheduler": ["scheduler.started", "scheduler.stopped", "scheduler.tick"] }}Common events:
| Event | Fired when |
|---|---|
task.completed | A task finishes successfully |
task.failed | A task fails |
| project.created | A project is created |
| project.updated | Project status changes |
| memory.stored | Memory is persisted |
| channel.message.received | A message arrives via a channel |
Executions
Section titled “Executions”List executions for a hook
Section titled “List executions for a hook”GET /api/hooks/{id}/executionsQuery: status (success, error, running, timeout, skipped), since, limit, offset
Response:
{ "executions": [ { "id": "exec_abc123", "hook_id": "hook_abc123", "event_type": "task.failed", "status": "success", "started_at": "2026-03-02T14:00:00Z", "completed_at": "2026-03-02T14:00:00.048Z", "duration_ms": 48 } ]}Per-hook analytics
Section titled “Per-hook analytics”GET /api/hooks/{id}/analyticsQuery: period (hourly, daily), start, end
Returns execution analytics for a specific hook.
Webhook endpoints (inbound)
Section titled “Webhook endpoints (inbound)”Register inbound webhook endpoints to receive external events. These live under /api/webhooks (separate from /api/hooks).
List webhook endpoints
Section titled “List webhook endpoints”GET /api/webhooksCreate a webhook endpoint
Section titled “Create a webhook endpoint”POST /api/webhooks{ "name": "GitHub push events", "secret": "github-webhook-secret"}Returns:
{ "id": "wh_abc123", "url": "https://your-snippbot/api/webhooks/{webhook_id}/receive", "secret": "github-webhook-secret"}Get / Update / Delete a webhook endpoint
Section titled “Get / Update / Delete a webhook endpoint”GET /api/webhooks/{id}PUT /api/webhooks/{id}DELETE /api/webhooks/{id}List deliveries for a webhook
Section titled “List deliveries for a webhook”GET /api/webhooks/{id}/deliveriesReceive a webhook (external-facing)
Section titled “Receive a webhook (external-facing)”POST /api/webhooks/{webhook_id}/receiveThis is the URL external services send events to. It is authenticated via HMAC signature, not bearer token.
Replay a delivery
Section titled “Replay a delivery”POST /api/webhooks/{id}/deliveries/{delivery_id}/replayHook deliveries (outbound HTTP queue)
Section titled “Hook deliveries (outbound HTTP queue)”HTTP hooks with queue-backed delivery enabled track each delivery attempt. These endpoints manage the delivery queue.
List deliveries for a hook
Section titled “List deliveries for a hook”GET /api/hooks/{id}/deliveriesQuery: status (pending, processing, success, failed, dead_letter), limit, offset
Response:
{ "deliveries": [ { "id": "del_abc123", "hook_id": "hook_abc123", "event_type": "task.completed", "status": "success", "attempt_count": 1, "response_status": 200, "duration_ms": 450, "created_at": "2026-04-17T00:00:00Z" } ], "stats": {"success": 5, "failed": 0, "pending": 0}}Retry a failed delivery
Section titled “Retry a failed delivery”POST /api/hooks/{id}/deliveries/{delivery_id}/retryOnly failed or dead_letter deliveries can be retried. Returns 409 otherwise.
Send a test delivery
Section titled “Send a test delivery”POST /api/hooks/{id}/test-deliverySends a synthetic test.notification event to the hook’s URL. Returns 202 with the delivery object.
Delivery queue stats
Section titled “Delivery queue stats”GET /api/hooks/deliveries/queue-statsReturns global delivery counts across all HTTP hooks:
{ "stats": { "pending": 0, "processing": 0, "success": 42, "failed": 1, "dead_letter": 0 }}Global analytics
Section titled “Global analytics”GET /api/hooks/analytics/globalReturns execution statistics across all hooks:
{ "total_deliveries": 1247, "success_rate": 0.98, "avg_latency_ms": 52, "by_event": { "task.completed": {"deliveries": 800, "success_rate": 0.99}, "task.failed": {"deliveries": 447, "success_rate": 0.97} }, "dead_letter_count": 3}Retry behavior
Section titled “Retry behavior”Inline HTTP hooks (default)
Section titled “Inline HTTP hooks (default)”Inline hooks retry immediately with fast exponential backoff:
| Attempt | Delay |
|---|---|
| 1 | 100ms |
| 2 | 200ms |
| 3 | 400ms |
| N | 100ms × 2^(N-1) |
Queue-backed HTTP hooks (config.queued: true)
Section titled “Queue-backed HTTP hooks (config.queued: true)”Queued hooks use configurable exponential backoff with jitter:
| Config | Default | Description |
|---|---|---|
retry_delay_s | 10 | Initial retry delay in seconds |
retry_multiplier | 2.0 | Backoff multiplier |
max_delay_s | 3600 | Maximum delay cap |
max_retries | 5 | Retries before dead letter |
After max_retries failures, deliveries move to the dead letter queue and can be manually retried via the API or UI.
HMAC verification
Section titled “HMAC verification”Both inbound webhooks and outbound HTTP hooks include a signature header when a secret is configured:
X-Snippbot-Signature: sha256=<hex_digest>Verify in Python:
import hmac, hashlib
def verify(payload: bytes, signature: str, secret: str) -> bool: expected = hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest() return hmac.compare_digest(f"sha256={expected}", signature)