Webhooks
Webhooks let external services push events to Zubo in real time. When a webhook receives an event, Zubo processes the payload through a configurable prompt template and takes action automatically. This turns Zubo into a reactive automation hub — connect GitHub for push notifications, Stripe for payment events, CI/CD pipelines for build results, or any service that can send HTTP POST requests.
Copy-Paste Task Cards
Secure API Access
Enable API auth and create a key before exposing ports beyond localhost.
zubo config set auth.enabled true
zubo auth create-key my-app
Set Local Model Fallback
Keep responses available during provider outages or API quota issues.
zubo config set failover '["openai","ollama"]'
zubo config set providers.ollama.model llama3.3
Common Errors
If auth.enabled is true, all /api/* calls require Authorization: Bearer <key>. Create a new key if needed.
curl -H "Authorization: Bearer YOUR_KEY" http://localhost:3000/api/dashboard/status
Use failover and switch temporarily to a responsive provider or smaller model. Check logs for repeated timeout patterns.
zubo model openai/gpt-4o-mini
zubo logs --follow
If local providers fail, ensure the runtime is running and a model is installed.
ollama serve
ollama pull llama3.3
Network Requirements
http://localhost:61939/api/webhook/... are only reachable from your own machine. External services (GitHub, Stripe, etc.) cannot send events to localhost.
To receive webhooks from external services, you need a publicly reachable URL. Options:
- ngrok — Run
ngrok http 61939to get a public HTTPS URL that tunnels to your local Zubo instance. Free tier available. - Cloudflare Tunnel — Run
cloudflared tunnel --url http://localhost:61939for a free, fast tunnel. - Deploy Zubo — Run Zubo on a VPS or cloud server with a public IP and domain name.
Once you have a public URL, configure the external service to send events to https://your-public-url/api/webhook/<webhook-id>.
Creating Webhooks
You can create webhooks through the dashboard, the CLI, or the API.
Via the Dashboard
- Open the web dashboard and navigate to the Webhooks panel in the sidebar.
- Click Create Webhook.
- Enter a descriptive name (e.g.,
github-pushes) and an optional HMAC secret for signature verification. - Write a prompt template that tells Zubo how to process incoming events. Use
{{payload}}to inject the raw event payload. - Click Save. The dashboard displays the webhook URL to configure in your external service.
Via the CLI
# Create a webhook with a prompt template
zubo webhook create \
--name "github-pushes" \
--secret "whsec_abc123..." \
--prompt "A GitHub push event just occurred: {{payload}}. Summarize what was pushed and notify me."
# List all webhooks
zubo webhook list
# Delete a webhook
zubo webhook delete github-pushes
Via the API
POST /api/webhooks
Content-Type: application/json
{
"name": "github-pushes",
"secret": "whsec_abc123...",
"prompt": "A GitHub push event just occurred: {{payload}}. Summarize what was pushed and notify me."
}
The response includes the generated webhook URL and ID:
{
"id": "wh_a1b2c3",
"name": "github-pushes",
"url": "http://localhost:3000/webhooks/wh_a1b2c3",
"secret": "whsec_abc123...",
"createdAt": "2026-02-15T10:00:00Z"
}
HMAC Secret Verification
Zubo supports HMAC-SHA256 signature verification to ensure that incoming webhook payloads are authentic and have not been tampered with. When a webhook has a secret configured, Zubo validates the X-Hub-Signature-256 header on every incoming request.
- How it works — the sending service computes an HMAC-SHA256 hash of the request body using the shared secret and includes it in the
X-Hub-Signature-256header assha256=<hex-digest>. Zubo independently computes the same hash and compares them using a constant-time comparison to prevent timing attacks. - GitHub compatibility — the signature format is fully compatible with GitHub webhook secrets. Set the same secret in both Zubo and your GitHub webhook configuration.
- Stripe compatibility — for Stripe webhooks, Zubo also checks the
Stripe-Signatureheader when theX-Hub-Signature-256header is absent. - Failed verification — requests with invalid or missing signatures are rejected with a
401 Unauthorizedresponse. The event is logged but not processed. - Optional — if no secret is configured on the webhook, signature verification is skipped and all incoming requests are accepted.
Prompt Templates
Each webhook has a prompt template that defines how Zubo should process incoming events. The template is a plain-text string with a special {{payload}} placeholder that gets replaced with the full JSON body of the incoming request.
# Simple notification
"New event received: {{payload}}. Summarize it and save to memory."
# GitHub-specific template
"A GitHub {{payload.action}} event occurred on {{payload.repository.full_name}}.
Details: {{payload}}
Summarize the changes and notify me on Telegram."
# Stripe-specific template
"A Stripe payment event occurred: {{payload}}.
If the payment succeeded, log the amount and customer.
If the payment failed, alert me immediately."
When a webhook receives a POST request, Zubo substitutes {{payload}} with the stringified JSON body, constructs a message from the resulting text, and sends it through the agent loop. The agent then processes the message like any other user input — it can use tools, search memory, send notifications, and take any action described in the prompt template.
Dashboard Management
The Webhooks panel in the dashboard provides a visual interface for managing all your webhooks.
- Webhook list — all configured webhooks are displayed with their name, URL, creation date, and last triggered time. Copy the webhook URL with one click.
- Event log — click a webhook to view its recent event history. Each event shows the timestamp, HTTP status, payload size, and whether it was processed successfully.
- Edit — update the name, secret, or prompt template of any webhook. Changes take effect immediately.
- Test — send a test payload to any webhook to verify it is working correctly. The test button sends a sample JSON payload and shows the agent's response.
- Delete — remove a webhook and all its event history.
Examples
GitHub Push Events
Notify yourself on Telegram whenever code is pushed to your repository.
Step 1: Create the webhook:
POST /api/webhooks
Content-Type: application/json
{
"name": "github-main-pushes",
"secret": "my-github-webhook-secret",
"prompt": "A GitHub push event just happened: {{payload}}. Tell me who pushed, to which branch, and list the commit messages. Send me a summary on Telegram."
}
Step 2: In your GitHub repository, go to Settings → Webhooks → Add webhook. Set the Payload URL to the webhook URL returned above, Content type to application/json, and the Secret to the same value. Select "Just the push event."
Result: Every time someone pushes to the repository, Zubo receives the event, summarizes the commits, and sends the summary to your Telegram.
Stripe Payment Events
Track successful payments and alert on failures.
POST /api/webhooks
Content-Type: application/json
{
"name": "stripe-payments",
"secret": "whsec_stripe_signing_secret",
"prompt": "A Stripe webhook event occurred: {{payload}}. If this is a successful payment (payment_intent.succeeded), save the amount, currency, and customer email to memory. If this is a failed payment (payment_intent.payment_failed), alert me immediately with the failure reason."
}
Configure the webhook URL in your Stripe Dashboard under Developers → Webhooks. Select the payment_intent.succeeded and payment_intent.payment_failed events.
API Endpoints
All webhook management endpoints are under /api/webhooks and require authentication when auth.enabled is true.
List Webhooks
GET /api/webhooks
Returns all configured webhooks with their metadata.
Response:
{
"webhooks": [
{
"id": "wh_a1b2c3",
"name": "github-pushes",
"url": "http://localhost:3000/webhooks/wh_a1b2c3",
"hasSecret": true,
"prompt": "A GitHub push event...",
"createdAt": "2026-02-15T10:00:00Z",
"lastTriggeredAt": "2026-02-15T14:30:00Z",
"eventCount": 12
}
]
}
Create Webhook
POST /api/webhooks
Content-Type: application/json
{
"name": "github-pushes",
"secret": "whsec_abc123...",
"prompt": "Process this event: {{payload}}"
}
Create a new webhook endpoint. The name and prompt fields are required. The secret field is optional but recommended for production use.
Response:
{
"id": "wh_a1b2c3",
"name": "github-pushes",
"url": "http://localhost:3000/webhooks/wh_a1b2c3",
"secret": "whsec_abc123...",
"createdAt": "2026-02-15T10:00:00Z"
}
Update Webhook
PUT /api/webhooks/:id
Content-Type: application/json
{
"name": "github-all-events",
"secret": "new-secret",
"prompt": "Updated prompt: {{payload}}"
}
Update a webhook's name, secret, or prompt template. All fields are optional — only the fields you include will be updated.
Delete Webhook
DELETE /api/webhooks/:id
Delete a webhook and all its associated event history. Returns 204 No Content on success.
Get Webhook Events
GET /api/webhooks/:id/events?limit=20&offset=0
Returns the event history for a specific webhook, ordered by most recent first.
Query parameters:
| Parameter | Default | Description |
|---|---|---|
limit | 20 | Number of events to return. Maximum 100. |
offset | 0 | Number of events to skip for pagination. |
Response:
{
"events": [
{
"id": "evt_xyz789",
"webhookId": "wh_a1b2c3",
"timestamp": "2026-02-15T14:30:00Z",
"status": "processed",
"payloadSize": 2048,
"processingTimeMs": 1250
}
],
"total": 12
}
Test Webhook
POST /api/webhooks/:id/test
Content-Type: application/json
{
"payload": {
"action": "push",
"repository": { "full_name": "user/repo" },
"commits": [{ "message": "test commit" }]
}
}
Send a test payload to a webhook. The payload is processed through the prompt template and the agent's response is returned. The event is recorded in the webhook's event history with a "test" status. If no payload is provided, a default sample payload is used.
Response:
{
"reply": "A push to user/repo was received with 1 commit: 'test commit'.",
"eventId": "evt_test_001"
}