Skip to main content

Webhooks

Webhooks allow external services to trigger actions in Open Genie. Each webhook has a shared secret for validation and maps to a specific action.

How It Works

External Service

POST /api/webhooks/{id}
Headers: X-Webhook-Secret: <secret>
Body: { custom payload }

Validate secret against DB record

Merge incoming payload with stored actionPayload

actionRegistry.execute(actionType, mergedPayload)

Return ActionResult

Webhook Record

{
id: "uuid",
name: "Home Assistant Motion",
secret: "random-secret-string",
actionType: "send_notification",
actionPayload: {
title: "Motion Alert",
target: "phones",
level: "warning"
},
enabled: true,
lastTriggeredAt: "2024-01-15T10:30:00Z"
}

Payload Merging

The webhook's stored actionPayload is merged with the incoming request body. Incoming fields override stored defaults:

Stored: { title: "Motion Alert", target: "phones" }
Incoming: { body: "Kitchen sensor triggered", target: "all" }
Merged: { title: "Motion Alert", body: "Kitchen sensor triggered", target: "all" }

REST API

MethodPathDescription
GET/api/webhooksList all webhooks
POST/api/webhooksCreate a webhook
PATCH/api/webhooks/[id]/manageUpdate webhook
DELETE/api/webhooks/[id]/manageDelete webhook
POST/api/webhooks/[id]Trigger the webhook

Create a Webhook

curl -X POST http://localhost:3000/api/webhooks \
-H "Content-Type: application/json" \
-d '{
"name": "Doorbell Alert",
"actionType": "send_notification",
"actionPayload": {
"title": "Doorbell",
"body": "Someone is at the door",
"target": "all",
"level": "info"
}
}'

Response includes the generated id and secret.

Trigger a Webhook

curl -X POST http://localhost:3000/api/webhooks/{id} \
-H "X-Webhook-Secret: <secret>" \
-H "Content-Type: application/json" \
-d '{"body": "Override message"}'

Integration Examples

Home Assistant

# configuration.yaml
rest_command:
notify_genie:
url: "http://genie-server:3000/api/webhooks/YOUR_WEBHOOK_ID"
method: POST
headers:
X-Webhook-Secret: "YOUR_SECRET"
Content-Type: "application/json"
payload: '{"body": "{{ trigger.to_state.attributes.friendly_name }} triggered"}'

IFTTT / Zapier / n8n

Point a webhook action at:

POST http://your-server:3000/api/webhooks/{id}
Header: X-Webhook-Secret: <secret>

Key Files

FilePurpose
lib/webhooks.tsSecret validation and action execution
server/routes/webhooks.tsList, create, trigger, update/delete endpoints