Webhooks API
The Webhooks API lets you manage your outage webhooks from a script instead of the account dashboard. It does exactly what the Webhooks page in your account does — create, list, edit, delete, and send a test — authenticated with a scoped API token.
A token can only manage webhooks. It cannot read device status, change your account, or do anything else.
Base URL
Section titled “Base URL”https://my.gridwatchdog.comAll endpoints below are relative to this base URL.
Getting a token
Section titled “Getting a token”-
Sign in to your account and open API tokens (under Integrations on your account page, at
https://my.gridwatchdog.com/account/tokens). -
Click Create token. The token — a string beginning
gwk_— is shown once. Copy it now; we store only a hash, so we can’t show it to you again. -
Use it as a bearer token on every request:
Authorization: Bearer gwk_your_token_here
You can revoke or rotate a token at any time from the same page. Revoking takes effect immediately. Tokens are created only from a signed-in browser session — a token can’t create another token.
Webhook object
Section titled “Webhook object”A webhook is returned as a JSON object with these fields:
| Field | Type | Description |
|---|---|---|
id |
number | The webhook’s unique id. |
type |
string | discord, slack, or generic. |
url |
string | The endpoint we deliver to. |
enabled |
boolean | Whether the webhook is active. Auto-disables after repeated failures. |
events |
array of strings | Which events fire this webhook (see Events). |
device_scope |
string or null | A device id to scope to one device, or null for all your devices. |
last_status |
string or null | The outcome of the most recent delivery attempt. |
created_at |
number | Unix timestamp (seconds) when the webhook was created. |
secret |
string | Generic webhooks only — the HMAC signing secret (see Signatures). |
Events
Section titled “Events”A webhook fires only on the events in its events list:
| Event | Meaning |
|---|---|
power_lost |
Mains power was lost. |
power_restored |
Mains power came back. |
lost_contact |
The device went dark (stopped checking in). |
silence_resolved |
The device came back online after going dark. |
If you omit events when creating a webhook, it subscribes to all four.
Webhook types
Section titled “Webhook types”| Type | URL requirement |
|---|---|
discord |
An https:// URL on discord.com, discordapp.com, or ptb.discord.com. |
slack |
An https:// URL on hooks.slack.com. |
generic |
Any https:// URL. Deliveries are HMAC-signed (see below). |
You can have up to 10 webhooks per account.
Endpoints
Section titled “Endpoints”Every endpoint requires the Authorization: Bearer … header. Requests without a
valid token get 401 { "error": "invalid_token" }.
List webhooks
Section titled “List webhooks”GET /account/webhooksReturns all your webhooks.
curl -H "Authorization: Bearer gwk_your_token_here" \ https://my.gridwatchdog.com/account/webhooks{ "webhooks": [ { "id": 12, "type": "discord", "url": "https://discord.com/api/webhooks/…", "enabled": true, "events": ["power_lost", "power_restored"], "device_scope": null, "last_status": "ok", "created_at": 1758666000 } ]}Create a webhook
Section titled “Create a webhook”POST /account/webhooksSend the fields as JSON (Content-Type: application/json) or as form-encoded
values.
| Field | Required | Description |
|---|---|---|
type |
yes | discord, slack, or generic. |
url |
yes | The delivery URL (must satisfy the type’s URL requirement). |
events |
no | Array (JSON) or comma-separated string. Defaults to all four events. |
device_scope |
no | A device id to scope to one device. Omit for all your devices. |
curl -X POST https://my.gridwatchdog.com/account/webhooks \ -H "Authorization: Bearer gwk_your_token_here" \ -H "Content-Type: application/json" \ -d '{ "type": "generic", "url": "https://example.com/hooks/gridwatchdog", "events": ["power_lost", "power_restored"] }'{ "ok": true, "id": 13 }Edit a webhook
Section titled “Edit a webhook”POST /account/webhooks/:idUpdate the url, the events, or both. Fields you omit are left unchanged. The
new url is re-validated against the webhook’s existing type.
curl -X POST https://my.gridwatchdog.com/account/webhooks/13 \ -H "Authorization: Bearer gwk_your_token_here" \ -H "Content-Type: application/json" \ -d '{ "events": ["power_lost", "lost_contact"] }'{ "ok": true }Delete a webhook
Section titled “Delete a webhook”POST /account/webhooks/:id/deletecurl -X POST https://my.gridwatchdog.com/account/webhooks/13/delete \ -H "Authorization: Bearer gwk_your_token_here"{ "ok": true }Re-enable a webhook
Section titled “Re-enable a webhook”POST /account/webhooks/:id/enableRe-enables a webhook that was auto-disabled after repeated delivery failures.
curl -X POST https://my.gridwatchdog.com/account/webhooks/13/enable \ -H "Authorization: Bearer gwk_your_token_here"{ "ok": true }Send a test delivery
Section titled “Send a test delivery”POST /account/webhooks/:id/testFires a synthetic power_lost delivery to the webhook so you can confirm it’s
wired up. A successful test on a disabled webhook re-enables it.
curl -X POST https://my.gridwatchdog.com/account/webhooks/13/test \ -H "Authorization: Bearer gwk_your_token_here"{ "ok": true, "status": 204, "reenabled": false }Verifying generic deliveries
Section titled “Verifying generic deliveries”For generic webhooks, every delivery we POST to your endpoint carries an
X-GridWatchdog-Signature header: the HMAC-SHA256 of the raw request body, keyed
by the webhook’s secret (returned in the webhook object for
generic hooks), hex-encoded. Recompute it on your side and compare to confirm the
delivery really came from GridWatchdog. Discord and Slack deliveries are not
signed — they go only to their respective verified hosts.
Errors
Section titled “Errors”| Status | Body | Meaning |
|---|---|---|
401 |
{ "error": "invalid_token" } |
The token is missing, unknown, or revoked. |
400 |
{ "error": "…" } |
Bad type, an invalid url for the type, or no valid events. |
404 |
{ "error": "Not found" } |
No webhook with that id belongs to you. |
409 |
{ "error": "Too many webhooks" } |
You’ve reached the 10-webhook limit. |