Webhooks
Integrate Testify with external systems by configuring webhooks that send real-time event notifications to your endpoints.
Overview
Webhooks allow you to receive HTTP POST notifications whenever specific events occur in Testify. When an event triggers (such as an exam submission or a new user signup), Testify sends a JSON payload to your configured endpoint URL, signed with HMAC-SHA256 for verification.
Supported Events
Testify supports the following webhook event types:
| Category | Events | Description |
|---|---|---|
| Exams | exam.created, exam.published, exam.assigned | Exam lifecycle events |
| Attempts | attempt.started, attempt.submitted, attempt.graded | Student exam activity |
| Students | student.enrolled, student.removed | Student enrollment changes |
| Questions | question.created, question.updated | Question bank changes |
| Users | user.created, user.updated, user.suspended | User account events |
| Organizations | org.created, org.updated | Organization changes |
| Papers | paper.created, paper.published | Paper lifecycle events |
| Certificates | certificate.issued | Certificate generation |
| Credits | credit.purchased, credit.depleted | Billing and credit events |
Creating a Webhook
- Navigate to "Admin" > "Webhooks"
- Click "Create Webhook"
- Fill in the configuration:
- "Name" -- a descriptive label (e.g., "LMS Sync" or "Slack Notifications")
- "URL" -- the HTTPS endpoint that will receive the webhook payloads
- "Events" -- select one or more event types to subscribe to
- "Secret" -- optionally enter a signing secret, or leave blank to auto-generate one
- "Headers" -- optionally add custom HTTP headers (as JSON key-value pairs)
- Click "Save"
The system automatically generates a signing secret if you do not provide one. Save this secret -- you will need it to verify webhook signatures on your receiving server.
Tip: Always use HTTPS endpoints for webhooks to ensure payload security in transit.
Webhook Payload Format
Every webhook delivery sends a POST request with the following structure:
{
"event": "exam.published",
"timestamp": "2026-03-21T10:30:00.000Z",
"organization": {
"id": "org-uuid",
"name": "Your Organization"
},
"data": {
// Event-specific data
}
}
Request Headers
Each delivery includes these headers:
| Header | Description |
|---|---|
Content-Type | application/json |
X-Webhook-Signature | sha256=<HMAC signature> |
X-Webhook-Event | The event type (e.g., exam.published) |
X-Webhook-Attempt | The delivery attempt number (1, 2, or 3) |
Verifying Webhook Signatures
To verify a webhook is genuinely from Testify, compute the HMAC-SHA256 of the request body using your webhook secret and compare it to the X-Webhook-Signature header.
const crypto = require('crypto');
function verifySignature(payload, signature, secret) {
const computed = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex');
return signature === `sha256=${computed}`;
}
Tip: Always verify signatures before processing webhook payloads. This prevents spoofed requests from being processed.
Testing a Webhook
Before relying on a webhook in production, send a test event to verify your endpoint is configured correctly.
- Go to "Admin" > "Webhooks"
- Find your webhook in the list
- Click "Test"
- Testify sends a
test.pingevent to your endpoint with a sample payload - The result shows:
- Whether delivery succeeded
- HTTP status code returned by your endpoint
- Response time in milliseconds
- Preview of the response body
Tip: Your endpoint should return a 2xx status code to indicate successful receipt. Any non-2xx response is treated as a failure.
Retry Logic
Testify automatically retries failed webhook deliveries using exponential backoff.
Retry Schedule
| Attempt | Delay Before Retry | Total Wait |
|---|---|---|
| 1st attempt | Immediate | 0 seconds |
| 2nd attempt | 1 second | 1 second |
| 3rd attempt | 4 seconds | 5 seconds |
If all three attempts fail, the delivery is marked as failed in the delivery log.
Timeout
Each delivery attempt has a configurable timeout (default: 30 seconds). If your endpoint does not respond within this window, the attempt is marked as failed.
Viewing Delivery Logs
Monitor the status and history of webhook deliveries.
- Go to "Admin" > "Webhooks"
- Click on a webhook to expand its details
- Click "View Logs"
- The delivery log shows the most recent deliveries (up to 100) with:
- Event type
- HTTP response status code
- Response body (truncated)
- Duration in milliseconds
- Success/failure status
- Attempt number
- Timestamp
Webhook Health Monitoring
Each webhook displays health metrics on the webhooks list page.
Health Indicators
- Total Deliveries -- lifetime count of delivery attempts
- Successful Deliveries -- count of successful attempts
- Success Rate -- percentage of successful deliveries (last 50)
- Avg Response Time -- average response time in milliseconds (last 50)
- Consecutive Failures -- number of failures in a row from most recent
Tip: If consecutive failures exceed 5, investigate your endpoint. Common causes include server downtime, expired SSL certificates, or firewall changes.
Replaying a Delivery
If a delivery failed and you want to retry it with the original payload:
- Go to the webhook's "Delivery Logs"
- Find the failed delivery
- Click "Replay"
- Testify re-sends the original payload with a
replayed_attimestamp andoriginal_delivery_idappended - The replay result is shown immediately
Retrying All Failed Deliveries
Batch-retry all failed deliveries from the last 24 hours.
- Go to "Admin" > "Webhooks"
- Click on the webhook
- Click "Retry Failed"
- The system retries all unique failed deliveries from the past 24 hours (2 attempts each)
- Results show:
- Number retried
- Number succeeded
- Number still failing
Tip: Use "Retry Failed" after resolving an endpoint outage to recover missed events without manual replay.
Updating a Webhook
- Go to "Admin" > "Webhooks"
- Click on the webhook you want to edit
- Update any of the following:
- "Name"
- "URL"
- "Events" (subscribed event types)
- "Active/Inactive" toggle
- "Headers"
- Click "Save"
Tip: Toggle a webhook to inactive instead of deleting it if you want to temporarily stop deliveries without losing the configuration.
Deleting a Webhook
- Go to "Admin" > "Webhooks"
- Click the "Delete" button next to the webhook
- Confirm deletion
Deleting a webhook also removes all its delivery logs.
Best Practices
Endpoint Design
- Return a 2xx response as quickly as possible (within 5 seconds)
- Process webhook payloads asynchronously (queue them for background processing)
- Handle duplicate deliveries idempotently (the same event may be delivered more than once)
- Log all received payloads for debugging
Security
- Always verify the
X-Webhook-Signatureheader - Use HTTPS endpoints only
- Rotate your webhook secret periodically by updating the webhook configuration
- Restrict your endpoint to accept requests only from Testify's IP addresses if possible
Monitoring
- Set up alerts for high consecutive failure counts
- Monitor average response time -- slow responses may cause timeouts
- Review delivery logs weekly to catch intermittent failures
Troubleshooting
Webhook Not Firing
- Verify the webhook is set to active
- Check that the event type you expect is in the webhook's subscribed events list
- Use the "Test" button to verify endpoint connectivity
All Deliveries Failing
- Check that your endpoint URL is correct and accessible from the internet
- Verify your SSL certificate is valid and not expired
- Check firewall rules on your receiving server
- Look at the response body in delivery logs for error messages
Signature Verification Failing
- Ensure you are using the correct webhook secret
- Verify you are computing HMAC-SHA256 over the raw JSON request body
- Check that the
Content-Typeisapplication/json