Events & webhook endpoints
An event is a record of something that happened: an alert opened, a task moved, a sampling ended, an order came from ChatGPT. Skoup keeps every event for 30 days and sends it to the webhook endpoints that listen to its type — HTTPS URLs of yours, each with its own signing secret. data.object has exactly the shape the matching GET endpoint returns, so an event and a fetch never disagree. The full list of types is generated from the platform itself.
Endpoints can be created in Settings → Developers → Webhooks, or through the API — handy for n8n, Zapier or a script that subscribes itself. They live in the mode of the key that created them: a test key manages test endpoints, which receive the events of test-mode calls (livemode: false).
Lifecycle of a delivery
pendingsucceededretryingfailedI want to…
| I want to… | Call |
|---|---|
| Subscribe a URL to some events | POST /v1/webhook_endpoints (url, enabled_events) |
| Subscribe to everything | Same call with enabled_events: ["*"] |
| Pause an endpoint | PATCH /v1/webhook_endpoints/{endpoint} with disabled: true |
| Remove an endpoint | DELETE /v1/webhook_endpoints/{endpoint} |
| Catch up after downtime | GET /v1/events?type=alert.created |
| Read one event again | GET /v1/events/{event} |
| Replay a delivery, send a test event | Settings → Developers → Webhooks (dashboard) |
Scopes: webhooks:write for endpoints, events:read for events.
Scenario: an n8n workflow that subscribes itself
curl -X POST https://api.skoup.ai/v1/webhook_endpoints \
-H "Authorization: Bearer skoup_test_4eC39HqLyjWDarjtT1zdp7dc" \
-H "Content-Type: application/json" \
-d '{"url":"https://n8n.example.com/webhook/skoup","enabled_events":["alert.created","task.created"],"description":"n8n · triage"}'The response is the only one that carries secret (whsec_…): store it to verify the X-Skoup-Signature header of every delivery.
Pitfalls
- Verify the signature on the raw body, and deduplicate on the event
id: a delivery may arrive twice. - HTTPS and public addresses only. Private, loopback and cloud-metadata addresses are refused; use a tunnel to test locally.
- Answer fast, work later. Acknowledge with a 2xx, then process in the background: after 10 s the delivery counts as failed.
- Unknown types are refused:
enabled_eventsmust list types of the catalog, or*.