1. List event keys
GET /api/v1/webhooks/events returns the live event list (for example proposal.accepted and eform.submitted). Do not hard-code a guessed set.
2. Subscribe
Write access required. One subscription per event. Repeat the call with the same URL to cover multiple events.POST /api/v1/webhooks with your HTTPS url and event.
201 includes id and webhookSecret. Store the secret immediately. List and get routes do not return it again.
GET /api/v1/webhooks lists subscriptions (no secrets). POST /api/v1/webhooks/{id}/test sends a test delivery. DELETE /api/v1/webhooks/{id} deactivates the subscription.
3. Verify every delivery
Each POST to your URL includes:
Verification:
- Read the raw body bytes. Do not re-serialize JSON.
- Build
canonical = {X-Om-Timestamp} + "." + {rawBody}. - Compute
expected = "sha256=" + HMAC_SHA256_UTF8(webhookSecret, canonical)(hex lowercase). - Compare with a constant-time compare. Reject on mismatch.