data.
Common envelope
| Field | Type | Description |
|---|---|---|
id | string | Unique delivery ID, e.g. dlv_01abc…. Same value as the X-Quippy-Delivery-Id header. Use it to dedupe on retries. |
type | string | The event type — e.g. exam.completed. Same as the X-Quippy-Event header. |
created | ISO 8601 string | Timestamp of this delivery attempt. |
institutionId | string | Your institution’s ID. Handy if you run one receiver for many tenants. |
test | boolean (optional) | Present and true only for synthetic test deliveries. |
data | object | Event-specific payload — see below. |
Events
exam.started — fires when a student begins a proctored exam session
exam.started — fires when a student begins a proctored exam session
studentId may be null for guest / link-based
exam modes. attempt is 1-indexed — the student’s nth attempt at this
exam. Great for driving real-time attendance dashboards.exam.completed — fires when a student submits an exam
exam.completed — fires when a student submits an exam
studentId may
be null for guest / link-based exam modes.violation.detected — fires when a critical proctoring violation is recorded
violation.detected — fires when a critical proctoring violation is recorded
Only critical violations fire this event. Warnings (e.g. one
quick head turn) are too noisy to push to customer systems by default
— they’re visible inside Quippy’s own dashboard but don’t emit.
| Field | Meaning |
|---|---|
type | The violation classifier — multiple_faces, face_not_visible, tab_switch, copy_paste, etc. |
severity | Always "critical" for webhook deliveries. |
riskScore | Cumulative session risk score (0–100), recalculated on each violation. |
totalViolations | Count of all violations on this session so far, critical + warning combined. |
recordingTimestamp | Seconds from recording start — useful to link directly into the playback. null if no recording. |
recordingTimeFormatted | Same timestamp as HH:MM:SS. |
grading.done — fires when an AI-graded assessment is persisted
grading.done — fires when an AI-graded assessment is persisted
score fields you’ll see depend on assessmentType:| Assessment type | Score fields populated |
|---|---|
speaking, open-ended, mixed | overall, pronunciation, fluency, accuracy |
cefr-speaking, cefr-writing | overall, cefrLevel (A1–C2) |
ielts-speaking, ielts-writing-task1, ielts-writing-task2 | overall, IELTS band in overall (0–9 scale) |
hskk_speaking | overall, pronunciation, fluency |
| written | overall, content, grammar (under score.*) |
null — don’t key off their presence.Teacher edits to an existing assessment (reviewing, overriding a
score) do not re-fire
grading.done. The event is strictly
“first grade was persisted.”user.provisioned — fires when a new institution user is created
user.provisioned — fires when a new institution user is created
via field tells
you how it happened:via | Fires on |
|---|---|
"invite" (or omitted) | Admin invites a user via POST /api/v2/users/invite or the Members page |
"sso" | A user authenticates via SSO for the first time (JIT provisioning) or a soft-deleted user is reactivated through SSO |
"scim" | The customer’s IdP pushes a new user via POST /api/scim/v2/Users |
role is one of admin, manager, editor, member, viewer.
accessLevel is the numeric equivalent (5 / 4 / 3 / 2 / 1).user.deprovisioned — fires when an institution user is removed
user.deprovisioned — fires when an institution user is removed
via tells you the trigger:via | Fires on |
|---|---|
"admin" (or omitted) | An admin removes the user from the Members page |
"scim" | The customer’s IdP deactivates the user (active: false PATCH or DELETE /api/scim/v2/Users/:id) |
user.provisioned to drive user lifecycle syncs in external
HRIS, CRM, or SIEM systems.subscription.updated — fires when the Stripe subscription status changes
subscription.updated — fires when the Stripe subscription status changes
active,
past_due, canceled, etc. planId may be null if the plan isn’t
recorded on our side.webhook.test — synthetic event from the 'Send test' button
webhook.test — synthetic event from the 'Send test' button
Delivering to multiple endpoints
If you subscribe two endpoints to the same event, each gets its own delivery row with a distinctid — they don’t share attempts or retry
state.