Developer sign-in required
The Developer & Integration section is restricted to signed-in developer accounts. Sign in with your AI2N.ai developer credentials to continue.
Webhooks
This selector is illustrative — there is no live public API to switch against yet. All requests/responses below use non-production example data.
API version: v1 · Status: Illustrative — pre-release
Webhooks notify your integration when something changes, instead of you polling for it. Every delivery is signed so you can verify it actually came from AI2N.ai.
Events
| Event | Fires when |
|---|---|
content.published | A curriculum content revision is published. |
content.unpublished | A content revision is rolled back or emergency-unpublished. |
training.completed | A learner completes a required training module. |
release.published | A new release note is published. |
known_issue.updated | A known issue's status or workaround changes. |
Verifying the signature
Every delivery includes an X-AI2N-Signature header — an HMAC-SHA256 of the raw request body, keyed with your webhook secret. Always verify it before trusting the payload, and compute the HMAC over the raw bytes, not a re-serialized copy (whitespace differences will break the comparison).
import crypto from "node:crypto";
function verifyWebhook(rawBody: string, signatureHeader: string, secret: string) {
const expected = crypto
.createHmac("sha256", secret)
.update(rawBody)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signatureHeader)
);
}
import hmac, hashlib
def verify_webhook(raw_body: bytes, signature_header: str, secret: str) -> bool:
expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature_header)
Your webhook secret is generated per-subscription in the admin console — never share it or log the raw value.
Retries and replay protection
A failed delivery (non-2xx response, or timeout) is retried with exponential backoff for up to 24 hours. Every delivery includes a unique X-AI2N-Delivery-Id — store the IDs you've already processed and ignore repeats, since retries and at-least-once delivery mean the same event can arrive more than once.