Advanced

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:

  1. Go to Dashboard → Settings → Webhooks
  2. Click Add Endpoint and enter your HTTPS URL
  3. Select the events you want to receive
  4. Copy the generated signing secret and store it securely
  5. 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

http
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.0

Example Payload

json
{
  "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.

EventDescriptionPayload Fields
quiz.completedTriggered when a player finishes a quizquiz_id, user_id, score, time_spent
quiz.createdTriggered when a new quiz is createdquiz_id, title, category, created_by
quiz.publishedTriggered when a quiz is published and made publicly accessiblequiz_id, title, published_by
attempt.submittedTriggered when a quiz attempt is submittedattempt_id, quiz_id, user_id, score
leaderboard.updatedTriggered when leaderboard rankings change for a quizquiz_id, top_scores, updated_at

quiz.created Payload Example

json
{
  "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.

javascript
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.

AttemptDelayDescription
1st retry1 minuteFirst retry after initial failure
2nd retry10 minutesSecond retry with increased delay
3rd retry1 hourFinal 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.

bash
# 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/quizapi

Remember to update your webhook URL in the dashboard when you deploy to production. Ngrok URLs are temporary and change on each restart.