Please wait while we prepare your content.

Please wait while we prepare your content.
Receive signed waiver events in real time, verify every payload with HMAC SHA-256, and include guardian/minor details or video waiver completion evidence where relevant.
Signed waivers, template changes, and record updates.
HMAC SHA-256 over the raw request body.
Completion summaries for video waiver submissions.
Stable top-level structure with nullable optional sections.
Webhooks allow you to receive HTTP POST notifications when specific events occur. Perfect for integrating waiver submissions, guardian/minor records, and video waiver completion evidence into your CRM, access control, marketing automation, or custom applications in real-time.
Subscribe to the events your integration needs.
waiver.submittedFired when a waiver is signed and submitted
waiver.verifiedFired when a submitted waiver is successfully email verified
waiver.expiring_soonFired when an unverified waiver is approaching its verification expiry window
waiver.expiredFired when a waiver is marked expired by the expiration cron
waiver.updatedFired when an existing waiver is modified (status, notes, compliance)
waiver.deletedFired when a waiver is deleted (GDPR compliance)
template.createdFired when a waiver template is created
template.updatedFired when a waiver template is modified
template.archivedFired when a waiver template is archived instead of hard deleted, usually because signed waivers reference it
template.deletedFired when an unused waiver template is permanently deleted
Every webhook request includes these headers.
X-Webhook-SignatureHMAC SHA-256 signature (computed on raw body string)X-Webhook-EventEvent type (e.g., waiver.submitted)X-Webhook-TimestampISO 8601 timestampX-Webhook-DeliveryUnique delivery identifier. Use this for idempotent processing when present.Content-Typeapplication/jsonThe signature is computed on the raw JSON request body string, not a parsed or re-serialized object. You must capture the raw body before parsing to verify correctly.
// Node.js/Express example
const crypto = require('crypto');
function verifyWebhook(rawBodyString, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(rawBodyString)
.digest('hex');
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}
// Express.js - capture raw body:
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-webhook-signature'];
const rawBody = req.body.toString('utf8');
if (!verifyWebhook(rawBody, signature, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
const payload = JSON.parse(rawBody);
// Process webhook...
});The top-level keys stay consistent. Optional sections such as guardianInfo, participants, and videoCompletion are populated only when relevant.
When an adult signs a waiver for themselves. signerInfo contains the participant details. guardianInfo is null, participants is empty, and videoCompletion is null for non-video templates.
{
"event": "waiver.submitted",
"timestamp": "2025-01-15T10:30:00.000Z",
"organizationId": "org_abc123",
"data": {
"waiverId": "waiver_xyz789",
"templateId": "template_123",
"templateName": "Standard Liability Waiver",
"templateType": "text",
"isGuardianSigning": false,
"numberOfMinors": 0,
"signerInfo": {
"firstName": "John",
"lastName": "Doe",
"email": "[email protected]",
"phone": "0412 345 678",
"dateOfBirth": "1990-05-15"
},
"guardianInfo": null,
"participants": [],
"videoCompletion": null,
"formData": {
"fullName": "John Doe",
"email": "[email protected]",
"phone": "0412 345 678",
"dateOfBirth": "1990-05-15",
"emergencyContactName": "Jane Doe",
"emergencyContactPhone": "0423 456 789",
"confirmRead": true,
"confirmAge": true,
"confirmVoluntary": true,
"signature": "data:image/png;base64,..."
},
"compliance": {
"certificateId": "WW-123456",
"signedAt": "2025-01-15T10:30:00.000Z",
"ipAddress": "203.45.67.89",
"userAgent": "Mozilla/5.0...",
"signatureMethod": "electronic",
"devicePlatform": "desktop"
},
"organization": {
"id": "org_abc123",
"name": "Adventure Sports Co"
},
"status": "completed"
}
}When a parent or guardian signs on behalf of one or more minors. signerInfo contains the guardian details, guardianInfo is populated, and participants contains the minor records built from participants[] or participantInfo.
{
"event": "waiver.submitted",
"timestamp": "2025-01-15T10:30:00.000Z",
"organizationId": "org_abc123",
"data": {
"waiverId": "waiver_xyz789",
"templateId": "template_123",
"templateName": "Youth Activity Waiver",
"templateType": "text",
"isGuardianSigning": true,
"numberOfMinors": 2,
"signerInfo": {
"firstName": "Sarah",
"lastName": "Smith",
"email": "[email protected]",
"phone": "0412 345 678",
"dateOfBirth": null
},
"guardianInfo": {
"fullName": "Sarah Smith",
"email": "[email protected]",
"phone": "0412 345 678",
"relationship": "Parent"
},
"participants": [
{
"fullName": "Emily Smith",
"dateOfBirth": "2015-03-20",
"customFields": {
"allergies": "None",
"medicalConditions": "Asthma - mild"
}
},
{
"fullName": "James Smith",
"dateOfBirth": "2012-08-10",
"customFields": {
"allergies": "Peanuts",
"medicalConditions": "None"
}
}
],
"videoCompletion": null,
"formData": {
"guardianFullName": "Sarah Smith",
"guardianEmail": "[email protected]",
"guardianPhone": "0412 345 678",
"guardianRelationship": "Parent",
"emergencyContactName": "Michael Smith",
"emergencyContactPhone": "0423 456 789",
"confirmRead": true,
"confirmAge": true,
"confirmVoluntary": true,
"confirmGuardianship": true,
"confirmAuthority": true,
"confirmLegalResponsibility": true,
"guardianSignature": "data:image/png;base64,..."
},
"compliance": {
"certificateId": "WW-789012",
"signedAt": "2025-01-15T10:30:00.000Z",
"ipAddress": "203.45.67.89",
"userAgent": "Mozilla/5.0...",
"signatureMethod": "electronic",
"devicePlatform": "mobile"
},
"organization": {
"id": "org_abc123",
"name": "Adventure Sports Co"
},
"status": "completed"
}
}When a video waiver is submitted. videoCompletion is included in the waiver.submitted webhook payload as a submission-time summary generated from the template videos, including watched percentage and checkpoint pass counts. This example shows an adult signing; guardian-mode video waivers still populate guardianInfo and participants the same way as text waivers.
{
"event": "waiver.submitted",
"timestamp": "2025-01-15T10:30:00.000Z",
"organizationId": "org_abc123",
"data": {
"waiverId": "waiver_xyz789",
"templateId": "template_456",
"templateName": "Safety Training Waiver",
"templateType": "video",
"isGuardianSigning": false,
"numberOfMinors": 0,
"signerInfo": {
"firstName": "John",
"lastName": "Doe",
"email": "[email protected]",
"phone": "0412 345 678",
"dateOfBirth": "1990-05-15"
},
"guardianInfo": null,
"participants": [],
"videoCompletion": {
"completedAt": "2025-01-15T10:30:00.000Z",
"videosWatched": [
{
"videoId": "video_001",
"name": "Safety Orientation",
"watchedPercentage": 100,
"checkpointsPassed": 3,
"checkpointsTotal": 3
}
],
"passed": true
},
"formData": {
"fullName": "John Doe",
"email": "[email protected]",
"confirmRead": true,
"confirmAge": true,
"confirmVoluntary": true,
"confirmVideoWatched": true,
"signature": "data:image/png;base64,..."
},
"compliance": {
"certificateId": "WW-345678",
"signedAt": "2025-01-15T10:30:00.000Z",
"ipAddress": "203.45.67.89",
"userAgent": "Mozilla/5.0...",
"signatureMethod": "electronic",
"devicePlatform": "desktop"
},
"organization": {
"id": "org_abc123",
"name": "Adventure Sports Co"
},
"status": "completed"
}
}Build receivers that are safe when deliveries are retried or downstream systems are slow.
Use these rules when building your webhook receiver.
Verify the signature before parsing or trusting the payload.
Use the raw request body string for HMAC verification. Re-stringifying parsed JSON can change spacing or key order and break verification.
Treat webhook handlers as idempotent. Your receiver may see retries if the first delivery is not acknowledged.
Return a 2xx response only after your integration has safely accepted the event.