Appearance
Webhooks
Configure webhooks to receive real-time notifications about push events. Today the dispatcher fires notification.sent after each fan-out — see the Available Events table below for reserved event names.
Base URL: https://app.krafter.dev/api/v1
Signing, retry policy, and auto-disable rules are shared across the platform — see Webhook delivery.
List Webhooks
Retrieve all webhooks configured for an app.
GET /push/apps/:app_id/webhooksRequired scope: push:read
Example Request
bash
curl https://app.krafter.dev/api/v1/push/apps/a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d/webhooks \
-H "Authorization: Bearer kr_live_abc123def456"Example Response
json
{
"data": [
{
"id": "f6a7b8c9-0d1e-2f3a-4b5c-6d7e8f9a0b1c",
"app_id": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"url": "https://example.com/webhooks/push",
"events": ["notification.sent"],
"enabled": true,
"failure_count": 0,
"created_at": "2025-06-01T08:00:00Z",
"updated_at": "2025-06-01T08:00:00Z"
}
]
}Create Webhook
Create a new webhook for an app. The webhook will start receiving events immediately if enabled is true (the default).
POST /push/apps/:app_id/webhooksRequired scope: push:write
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
url | string | Yes | The URL to send webhook payloads to. Must use https:// — lib/krafter/push/push_webhook.ex:21 rejects http://, and Krafter.UrlValidator.validate_url/2 rejects loopback, RFC 1918 / link-local, cloud-metadata, and .local / .internal hosts to prevent SSRF. |
secret | string | No | Secret used to sign webhook payloads. Optional — when omitted (or empty string), the dispatcher skips the x-krafter-signature header entirely (webhook_delivery_helper.ex:42-46). Without a secret your handler has no way to verify the request came from Krafter; treat this as a development-only path. |
events | string[] | No | Events to subscribe to. Defaults to [] (no events fire) — set this to ["notification.sent"] to actually receive deliveries. See Available Events below. |
enabled | boolean | No | Whether the webhook is active. Defaults to true. |
Available Events
Today the dispatcher emits a single event:
| Event | Description |
|---|---|
notification.sent | Fan-out completed for a notification. Payload includes notification_id, app_id, title, sent_count, and failed_count. |
Coming soon
notification.delivered, notification.clicked, notification.failed, subscriber.registered, and subscriber.unsubscribed are reserved event names. The webhook schema accepts them in events arrays without error, but the dispatcher does not emit them yet — your handler will only see notification.sent until per-event delivery, click, and subscriber-lifecycle tracking ship.
Example Request
bash
curl -X POST https://app.krafter.dev/api/v1/push/apps/a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d/webhooks \
-H "Authorization: Bearer kr_live_abc123def456" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/webhooks/push",
"secret": "whsec_a1b2c3d4e5f6g7h8i9j0",
"events": ["notification.sent"]
}'Example Response
json
// 201 Created
{
"data": {
"id": "f6a7b8c9-0d1e-2f3a-4b5c-6d7e8f9a0b1c",
"app_id": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"url": "https://example.com/webhooks/push",
"events": ["notification.sent"],
"enabled": true,
"failure_count": 0,
"created_at": "2025-06-01T08:00:00Z",
"updated_at": "2025-06-01T08:00:00Z"
}
}Update Webhook
Update an existing webhook. Only provided fields are changed.
PATCH /push/apps/:app_id/webhooks/:webhook_idRequired scope: push:write
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
url | string | No | The URL to send webhook payloads to. |
secret | string | No | Secret used to sign webhook payloads. |
events | string[] | No | Events to subscribe to. |
enabled | boolean | No | Whether the webhook is active. |
Example Request
bash
curl -X PATCH https://app.krafter.dev/api/v1/push/apps/a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d/webhooks/f6a7b8c9-0d1e-2f3a-4b5c-6d7e8f9a0b1c \
-H "Authorization: Bearer kr_live_abc123def456" \
-H "Content-Type: application/json" \
-d '{
"events": ["notification.sent"],
"enabled": false
}'Example Response
json
{
"data": {
"id": "f6a7b8c9-0d1e-2f3a-4b5c-6d7e8f9a0b1c",
"app_id": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"url": "https://example.com/webhooks/push",
"events": ["notification.sent"],
"enabled": false,
"failure_count": 0,
"created_at": "2025-06-01T08:00:00Z",
"updated_at": "2025-06-15T11:00:00Z"
}
}Delete Webhook
Permanently delete a webhook. It will stop receiving events immediately.
DELETE /push/apps/:app_id/webhooks/:webhook_idRequired scope: push:write
Example Request
bash
curl -X DELETE https://app.krafter.dev/api/v1/push/apps/a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d/webhooks/f6a7b8c9-0d1e-2f3a-4b5c-6d7e8f9a0b1c \
-H "Authorization: Bearer kr_live_abc123def456"Example Response
// 204 No Content