Automations & webhooks
Send events such as enrolments, completions and grades to your systems, Zapier, Make or n8n, and verify each delivery with its signing secret.
A webhook sends a message to an address you choose the moment something happens in your organization — a learner enrols, completes a course, submits an assignment or earns a certificate. Use it to update your own records or to start a workflow in Zapier, Make or n8n.
Who can use it
Add an endpoint
- Go to Developers → Automations (open Automations) and add an endpoint.
- Paste the Endpoint URL that should receive events. It must be a public
https://address. - Add a description so others know what it is for.
- Tick the events you want. Each event shows an example of the data it sends.
- Click Create Endpoint and copy the Signing Secret. It is shown only once.
- Use Send test event to send a
pingand check it arrives.
Connect Zapier, Make or n8n
In your automation tool, start a workflow with its “catch webhook” trigger (in Zapier: Webhooks by Zapier → Catch Hook). Copy the address it gives you into the Endpoint URL above, send a test event, and build the rest of the workflow from the sample data.
Events you can subscribe to
| Group | Events |
|---|---|
| Learning progress | Course enrolled, activity completed, course completed, assignment submitted, assignment graded, certificate claimed, certificate revoked |
| Users & access | User signed up, email verified, role changed, invited, removed from the organization |
| Courses & content | Course created, published or unpublished, deleted, announcement posted; contributors added or removed; folders and podcast episodes |
| Community & collaboration | Discussions and comments, pins, locks and votes; new boards and playgrounds |
| Groups & subscriptions | User groups created or deleted, members or courses added; subscription packs activated or cancelled |
| Organization | Sign-up method, AI settings or payment settings changed |
The endpoint page shows the exact event names and sample data for each one.
What a delivery looks like
Each event is an HTTP POST with a JSON body:
Example body
{
"event": "course_enrolled",
"delivery_id": "dlv_3f9c1a7e5b2d4c80",
"timestamp": "2026-09-24T08:15:02Z",
"org_id": 42,
"data": {
"user": { "user_uuid": "user_…", "email": "[email protected]", "username": "amina" },
"course": { "course_uuid": "course_…", "name": "Form 3 Chemistry" }
}
}X-Webhook-Event- — the event name.
X-Webhook-Delivery- — a unique delivery id. Store it and ignore repeats, so a retried delivery is only processed once.
X-Webhook-Signature- —
sha256=followed by an HMAC-SHA256 of the raw request body, made with your signing secret.
Verify the signature
Before trusting a delivery, recompute the signature from the raw body (before any JSON parsing) and compare it with the header. Reject anything that does not match.
Python
import hmac, hashlib
def is_from_validbridge(raw_body: bytes, signature_header: str, secret: str) -> bool:
expected = "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature_header or "")Node.js
const crypto = require('crypto')
function isFromValidBridge(rawBody, signatureHeader, secret) {
const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex')
const a = Buffer.from(expected)
const b = Buffer.from(signatureHeader || '')
return a.length === b.length && crypto.timingSafeEqual(a, b)
}Retries and delivery logs
- Answer with any
2xxstatus within 10 seconds to confirm receipt. - Otherwise the delivery is retried, up to 3 attempts in total, a few seconds apart. Redirects are not followed.
- View delivery logs shows each attempt with its status code and the start of your response — the first place to look when something is missing. The most recent 200 attempts per endpoint are kept.
Manage endpoints
- Edit the URL, description or events at any time.
- Disable an endpoint to pause deliveries without losing its settings.
- Regenerate the secret if it may have leaked. The old secret stops working immediately; update your receiver first.
- Delete an endpoint you no longer need.
Was this article helpful?