Webhooks
Get told when things happen instead of polling.
Register an HTTPS endpoint and Ingenee will POST a signed JSON event to it. Add endpoints in
Settings → Organisation → Webhooks, or with the API (webhooks:write scope, admin role):
curl -X POST https://dev.app.ingenee.ai/api/v1/webhooks \
-H "Authorization: Bearer $INGENEE_API_KEY" -H "content-type: application/json" \
-d '{ "url": "https://example.com/ingenee", "events": ["media-job-finished", "publish-succeeded"] }'The response includes the endpoint's signing secret (whsec_…), shown once.
Events
| Event | Sent when | data |
|---|---|---|
media-job-finished | A Studio job finishes processing | jobId, assetId, status, outputs[] |
media-job-failed | A Studio job fails | jobId, status, error |
publish-succeeded | A channel schedule is published | kind: "channel", channelId, channelName, versionId |
rights-expiring | Once a day, for titles whose rights end within 14 days. Each title and end date is announced once | windowDays, titles[] with assetId, title, endsAt and territory when it's a single territory |
ingest-finished | An import job finishes | jobId, catalogId, status (done or completed_with_errors), processedRows, errorRows |
Payload
POST /ingenee HTTP/1.1
content-type: application/json
x-ingenee-event: media-job-finished
x-ingenee-signature: sha256=5d41402abc4b2a76b9719d911017c592…
{
"event": "media-job-finished",
"sentAt": "2026-10-30T07:12:01.004Z",
"data": {
"jobId": "…",
"assetId": "…",
"status": "completed",
"outputs": [{ "mediaId": "…", "kind": "rendition", "key": "…" }]
}
}Verify the signature
x-ingenee-signature is sha256= followed by the hex HMAC-SHA256 of the raw request body, keyed with your
signing secret. Compare it in constant time before you trust the payload.
import { createHmac, timingSafeEqual } from 'node:crypto';
export function verify(rawBody: string, header: string | undefined, secret: string): boolean {
const expected = 'sha256=' + createHmac('sha256', secret).update(rawBody).digest('hex');
const a = Buffer.from(expected);
const b = Buffer.from(header ?? '');
return a.length === b.length && timingSafeEqual(a, b);
}Delivery
- Answer with any
2xxwithin 8 seconds. Do the work after you respond. - Up to 3 redirects are followed, and every hop must be a public HTTPS address.
- Settings shows the last delivery's status for each endpoint, and Send test posts a test event.
POST /v1/webhooks/{id}/testdoes the same from the API.