Webhooks
Get notified when events happen in your QuizAPI account. Webhooks allow your application to receive real-time HTTP callbacks whenever important events occur.
Coming Soon
Webhooks are currently in development and not yet available. The documentation below describes the planned API. We will announce availability on our blog when webhooks are ready for use.
Setup
Configure your webhook endpoint in the Dashboard Settings page. Provide an HTTPS URL that can receive POST requests, and select which events you want to subscribe to.
Quick setup steps:
- Go to Dashboard → Settings → Webhooks
- Click Add Endpoint and enter your HTTPS URL
- Select the events you want to receive
- Copy the generated signing secret and store it securely
- Click Save to activate the webhook
Payload Format
All webhook payloads are JSON objects delivered via HTTP POST. Every payload includes a unique event ID, the event type, a timestamp, and the event-specific data.
Request Headers
POST /webhooks/quizapi HTTP/1.1
Host: your-app.com
Content-Type: application/json
X-QuizAPI-Signature: sha256=5d3a1c8b9f2e...
X-QuizAPI-Event: quiz.completed
X-QuizAPI-Delivery: evt_abc123def456
User-Agent: QuizAPI-Webhooks/1.0Example Payload
{
"id": "evt_abc123def456",
"event": "quiz.completed",
"created_at": "2025-01-16T14:30:00Z",
"data": {
"quiz_id": "quiz_abc123",
"user_id": "user_xyz789",
"score": 8,
"total_questions": 10,
"time_spent": 245,
"completed_at": "2025-01-16T14:30:00Z"
}
}Event Types
Subscribe to the events that matter to your application. Each event type carries a specific data payload.
| Event | Description | Payload Fields |
|---|---|---|
quiz.completed | Triggered when a player finishes a quiz | quiz_id, user_id, score, time_spent |
quiz.created | Triggered when a new quiz is created | quiz_id, title, category, created_by |
quiz.published | Triggered when a quiz is published and made publicly accessible | quiz_id, title, published_by |
attempt.submitted | Triggered when a quiz attempt is submitted | attempt_id, quiz_id, user_id, score |
leaderboard.updated | Triggered when leaderboard rankings change for a quiz | quiz_id, top_scores, updated_at |
quiz.created Payload Example
{
"id": "evt_ghi789jkl012",
"event": "quiz.created",
"created_at": "2025-01-16T10:00:00Z",
"data": {
"quiz_id": "quiz_new456",
"title": "React Hooks Quiz",
"category": "programming",
"created_by": "user_abc123"
}
}Webhook Security
Every webhook request includes an X-QuizAPI-Signature header containing an HMAC-SHA256 signature. Always verify this signature before processing the payload to ensure it was sent by QuizAPI and has not been tampered with.
Never skip signature verification in production. Without it, any third party could send fake webhook events to your endpoint.
const crypto = require("crypto");
function verifyWebhookSignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac("sha256", secret)
.update(payload, "utf8")
.digest("hex");
const expected = `sha256=${expectedSignature}`;
// Use timingSafeEqual to prevent timing attacks
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
// Express.js example
app.post("/webhooks/quizapi", express.raw({ type: "application/json" }), (req, res) => {
const signature = req.headers["x-quizapi-signature"];
const payload = req.body.toString();
if (!verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET)) {
return res.status(401).json({ error: "Invalid signature" });
}
const event = JSON.parse(payload);
switch (event.event) {
case "quiz.completed":
console.log("Quiz completed:", event.data);
break;
case "quiz.created":
console.log("Quiz created:", event.data);
break;
default:
console.log("Unhandled event:", event.event);
}
res.status(200).json({ received: true });
});Retry Policy
If your endpoint returns a non-2xx status code or times out (30 seconds), QuizAPI will retry the delivery up to 3 times with exponential backoff.
| Attempt | Delay | Description |
|---|---|---|
| 1st retry | 1 minute | First retry after initial failure |
| 2nd retry | 10 minutes | Second retry with increased delay |
| 3rd retry | 1 hour | Final retry attempt before marking as failed |
After all retries are exhausted, the event is marked as failed. You can view and manually retry failed deliveries in the Dashboard.
Testing Locally
Use a tunneling tool like ngrok to expose your local development server to the internet. This lets QuizAPI deliver webhooks to your machine during development.
# 1. Install ngrok
brew install ngrok # macOS
# or download from https://ngrok.com
# 2. Start your local server
node server.js # Starts on port 3000
# 3. Expose your local server to the internet
ngrok http 3000
# 4. Copy the ngrok URL (e.g., https://abc123.ngrok.io)
# and set it as your webhook URL in the QuizAPI dashboard:
# https://abc123.ngrok.io/webhooks/quizapiRemember to update your webhook URL in the dashboard when you deploy to production. Ngrok URLs are temporary and change on each restart.