Overview
Webhooks allow your application to receive real-time HTTP notifications when events occur, such as when an evaluation completes. Instead of polling the API, you register a URL and we'll send events to it.
Supported Events
| Event | Description |
|---|---|
evaluation.completed | An evaluation has been graded successfully |
evaluation.failed | An evaluation failed to process |
assessment.deployed | Reserved for future assessment deployment events |
assessment.submitted | Reserved for future assessment submission events |
course.deployed | A course has been deployed |
course.completed | A course generation has completed |
lti.launch_completed | An LTI launch flow completed successfully |
lti.launch_failed | An LTI launch flow failed |
lti.grade_synced | A grade was successfully synced to the LMS |
lti.grade_sync_failed | Grade sync to the LMS failed after all retries |
Webhook Payload
{
"evaluationId": "2f4ad455-1e8e-4b6c-9f3a-7ebf4cf6f483",
"status": "COMPLETED",
"evaluationType": "open_ended",
"score": 8,
"maxScore": 10,
"normalizedScore": 80
}Signature Verification
Every webhook request includes these headers:
X-Platform-SignatureX-Platform-Event
The signature is computed as HMAC_SHA256(payload, secret) where secret is the
value returned when you created the webhook endpoint. Verify against the raw request body.
const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}Retry Policy
If your endpoint returns a non-2xx status code, we retry with exponential backoff:
| Attempt | Delay |
|---|---|
| 1st retry | 5 seconds |
| 2nd retry | 25 seconds |
| 3rd retry | 125 seconds |
After the initial delivery attempt plus 3 retries (4 total attempts), the delivery is marked as failed.
Managing Webhook Endpoints
Use the management endpoints below to create, list, and delete webhook subscriptions.
These are internal management endpoints authenticated via TutorFlow admin auth, not via Platform API keys. For dashboard-level webhook management, use the Dashboard API endpoints.
Create a Webhook Endpoint
POST /v1/platform/webhooks| Parameter | Type | Required | Description |
|---|---|---|---|
url | string | Yes | The HTTPS URL that will receive webhook events |
events | string[] | Yes | List of event types to subscribe to |
secret | string | No | A shared secret for HMAC signature verification. Auto-generated if omitted. |
curl -X POST https://api.tutorflow.io/v1/platform/webhooks \
-H "Authorization: Bearer tf_platform_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://myapp.com/webhooks/tutorflow",
"events": ["evaluation.completed", "evaluation.failed"]
}'Response:
{
"id": "wh_abc123",
"url": "https://myapp.com/webhooks/tutorflow",
"events": ["evaluation.completed", "evaluation.failed"],
"secret": "whsec_...",
"createdAt": "2026-03-19T10:00:00Z"
}Store the secret value securely. It is only returned once at creation time and is
used for signature verification.
List Webhook Endpoints
GET /v1/platform/webhooksReturns all webhook endpoints registered for your workspace.
curl https://api.tutorflow.io/v1/platform/webhooks \
-H "Authorization: Bearer tf_platform_..."Response:
[
{
"id": "wh_abc123",
"platformWorkspaceId": "workspace-uuid",
"url": "https://myapp.com/webhooks/tutorflow",
"events": ["evaluation.completed", "evaluation.failed"],
"status": "active",
"createdAt": "2026-03-19T10:00:00Z",
"updatedAt": "2026-03-19T10:00:00Z"
}
]Delete a Webhook Endpoint
DELETE /v1/platform/webhooks/:id| Parameter | Type | Description |
|---|---|---|
id | string | The webhook endpoint ID |
curl -X DELETE https://api.tutorflow.io/v1/platform/webhooks/wh_abc123 \
-H "Authorization: Bearer tf_platform_..."Returns 204 No Content on success.
Best Practices
- Always verify the HMAC signature before processing.
- Return
200 OKquickly and process the event asynchronously. - Handle duplicate events idempotently using the payload resource identifier.
- Use HTTPS endpoints only.