Webhooks
Webhooks let Coassemble send server-to-server POST requests to your endpoint when important course events happen.
If you are embedding Coassemble in an iframe and want browser-side events instead, see Events.
Events you can subscribe to
| Event | Fires when |
|---|---|
course.created | A new course is created. |
course.commenced | A learner first commences a course tracking record. |
course.completed | A learner first completes a course tracking record. |
Delivery format
Coassemble sends webhooks as POST requests with Content-Type: application/json.
Request headers
| Header | Description |
|---|---|
X-Coassemble-Event | Event name, e.g. course.completed. |
X-Coassemble-Delivery | Unique delivery ID (UUID). Use this for idempotency. |
X-Coassemble-Timestamp | Unix timestamp (seconds) used for signature verification. |
X-Coassemble-Signature | HMAC SHA-256 signature in the format sha256=<hex>. |
Request body
{
"id": "17fd9df8-c77a-4b7d-a281-267b74f8cbf3",
"type": "course.completed",
"occurredAt": "2026-02-22T10:15:30.000Z",
"workspaceId": 1234,
"data": {
"course": {
"id": 4321,
"title": "Security Basics",
"key": "security-basics",
"clientIdentifier": "course_abc"
},
"tracking": {
"id": 8888,
"identifier": "user_123",
"email": "user@example.com",
"commenced": "2026-02-22T10:01:00.000Z",
"completed": "2026-02-22T10:15:30.000Z",
"totalTime": 870
}
}
}
Signature verification
Each webhook endpoint has its own signing secret generated when the endpoint is created.
Signatures are created with: sha256 = HMAC_SHA256(secret, "<timestamp>.<raw_request_body>")
Example
Node.js
import crypto from 'crypto';
function verifyWebhookSignature({ rawBody, timestamp, signatureHeader, secret }) {
const expected = `sha256=${crypto
.createHmac('sha256', secret)
.update(`${timestamp}.${rawBody}`)
.digest('hex')}`;
if (!signatureHeader || signatureHeader.length !== expected.length) return false;
return crypto.timingSafeEqual(
Buffer.from(signatureHeader, 'utf8'),
Buffer.from(expected, 'utf8')
);
}
Use the raw request body string when verifying signatures (before JSON parsing).
Retry and failure behavior
- A delivery is considered successful only when your endpoint returns a
2xxstatus. - Coassemble uses a
10srequest timeout. - Failed deliveries are retried up to
4total attempts. - Backoff delays are approximately
1 minute,5 minutes, then30 minutes. - Delivery attempts include the same
X-Coassemble-DeliveryID so you can deduplicate safely.
Setup
- Build an HTTPS endpoint in your app that accepts
POSTJSON and returns2xxquickly. - In Coassemble authoring, go to
Settings->Webhooks. - Create a webhook endpoint URL and select one or more events.
- Send a test delivery to confirm your receiver logic (
data.testistrueon test payloads). - Validate signatures, deduplicate using
X-Coassemble-Delivery, then process asynchronously.
Managing webhooks
Webhook endpoints are currently managed in the Coassemble app.
- Go to
Settings->Webhooksto create, edit, test, enable/disable, or delete endpoints. - Webhook endpoint URLs must use
https://.