Webhooks
Register outgoing HTTP webhooks that fire when API write events happen (page/media/user mutations, config updates, GPM installs, Grav upgrades). Each webhook has a URL, an event filter list, an optional shared secret for HMAC signing, and a delivery log. Permissions: api.webhooks.read / api.web...
Register outgoing HTTP webhooks that fire when API write events happen (page/media/user mutations, config updates, GPM installs, Grav upgrades). Each webhook has a URL, an event filter list, an optional shared secret for HMAC signing, and a delivery log.
Permissions: api.webhooks.read / api.webhooks.write. Secrets are always redacted in API responses — the full value is shown once on creation and never again.
Valid event names
* (all), page.created, page.updated, page.deleted, page.moved, page.translated, pages.reordered, media.uploaded, media.deleted, user.created, user.updated, user.deleted, config.updated, gpm.installed, gpm.removed, grav.upgraded.
List Webhooks
/webhooks
{"data": [{"id": "wh_abc123", "url": "https://example.com/hook", "events": ["page.created", "page.updated"], "secret": "grav_a****************_xyz", "enabled": true}]}
Response Codes
Create Webhook
/webhooks
Parameters
| Name | Type | Description |
|---|---|---|
| url required | string | Absolute HTTP(S) URL to POST payloads to. |
| events optional | array | Event filter. Use `["*"]` to receive every event, or list specific events. Defaults to all. |
| secret optional | string | Shared secret used to sign request bodies (HMAC-SHA256 sent as `X-Hub-Signature-256`). A random one is generated if omitted. |
| enabled optional | boolean | Defaults to true. |
{"url": "https://example.com/hook", "events": ["page.updated", "page.deleted"]}
{"data": {"id": "wh_abc123", "url": "https://example.com/hook", "events": ["page.updated", "page.deleted"], "secret": "grav_abcdef1234567890", "enabled": true}}
Response Codes
Get Webhook
/webhooks/{id}
Parameters
| Name | Type | Description |
|---|---|---|
| id required | string | Webhook id (path param). |
{"data": {"id": "wh_abc123", "url": "https://example.com/hook", "events": ["page.updated"], "secret": "grav_a****************_xyz", "enabled": true}}
Response Codes
Update Webhook
/webhooks/{id}
Parameters
| Name | Type | Description |
|---|---|---|
| id required | string | Webhook id (path param). |
| url optional | string | New URL. |
| events optional | array | Replacement event filter. |
| secret optional | string | New shared secret. |
| enabled optional | boolean | Enable/disable the webhook without deleting it. |
{"enabled": false}
{"data": {"id": "wh_abc123", "url": "https://example.com/hook", "events": ["page.updated"], "secret": "grav_a****************_xyz", "enabled": false}}
Response Codes
Delete Webhook
/webhooks/{id}
Parameters
| Name | Type | Description |
|---|---|---|
| id required | string | Webhook id (path param). |
Response Codes
Delivery Log
/webhooks/{id}/deliveries
Parameters
| Name | Type | Description |
|---|---|---|
| id required | string | Webhook id (path param). |
| page optional | integer | Page number (default 1). |
| per_page optional | integer | Items per page. |
{"data": [{"event": "page.updated", "url": "https://example.com/hook", "status_code": 200, "success": true, "duration_ms": 142, "delivered_at": "2026-04-17T12:00:00+00:00"}], "meta": {"total": 57, "page": 1, "per_page": 50}}
Response Codes
Test Webhook
/webhooks/{id}/test
Parameters
| Name | Type | Description |
|---|---|---|
| id required | string | Webhook id (path param). |
{"data": {"event": "webhook.test", "url": "https://example.com/hook", "status_code": 200, "success": true, "duration_ms": 118, "delivered_at": "2026-04-17T12:00:00+00:00"}}