Skip to content
Shoal
Shoal

Guides

Webhooks

Get notified when flags change and verify signed payloads.

Webhooks send an HTTP POST to your endpoint whenever something changes in a project — a flag toggled, a rule edited, a rollout step completed.

Create an endpoint

Go to Project settings → Webhooks → Add endpoint, or use the API. Choose the events you want:

  • flag.updated — state, rules or variations changed
  • flag.created, flag.deleted
  • rollout.step — a scheduled rollout advanced
  • rollout.guard_triggered — a guard paused or rolled back a rollout

Payload

POST /your/webhook
{
  "id": "evt_01J9ZK4W3T",
  "type": "flag.updated",
  "createdAt": "2026-10-01T08:12:44Z",
  "environment": "production",
  "data": {
    "flag": "new-checkout",
    "changes": [{ "path": "rollout.percent", "from": 25, "to": 50 }],
    "actor": { "type": "user", "email": "mia@acme.dev" }
  }
}

Verify signatures

Every request carries a Shoal-Signature header: an HMAC-SHA256 of the raw body with your endpoint secret. Reject requests that don’t match.

verify.ts
import { createHmac, timingSafeEqual } from "node:crypto";

export function verify(body: string, header: string, secret: string) {
  const expected = createHmac("sha256", secret).update(body).digest("hex");
  return timingSafeEqual(Buffer.from(expected), Buffer.from(header));
}
verify.py
import hmac, hashlib

def verify(body: bytes, header: str, secret: str) -> bool:
    expected = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, header)
Edit this pageLast updated:
Was this page helpful?

Type to search. Results come from a local index — nothing leaves your browser.

↑ ↓ to navigate↵ to openMiniSearch · local