Skip to main content
Webhooks notify your application of authentication events in real-time.

What are webhooks

Webhooks are HTTP callbacks that Scalekit sends to your application when events occur:
  • User authentication
  • User creation/update
  • Session events
  • SSO configuration changes
  • SCIM provisioning events

Webhook flow

  1. Event occurs in Scalekit (e.g., user logs in)
  2. Scalekit sends HTTP POST to your webhook URL
  3. Your application processes the event
  4. Your application responds with 200 OK

Configuration

Configure webhooks in Dashboard > Developers > Webhooks:
  1. Add your webhook URL
  2. Select events to receive
  3. Copy the signing secret
  4. Test the webhook

Webhook format

{
  "id": "evt_1234567890",
  "type": "user.authenticated",
  "created": "2024-01-15T10:30:00Z",
  "data": {
    "userId": "usr_1234567890",
    "organizationId": "org_1234567890",
    "email": "[email protected]"
  }
}

Verifying webhooks

Verify webhook signatures to ensure authenticity:
const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
  const hmac = crypto.createHmac('sha256', secret);
  const digest = hmac.update(payload).digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(digest)
  );
}

app.post('/webhooks', (req, res) => {
  const signature = req.headers['x-scalekit-signature'];
  const payload = JSON.stringify(req.body);
  
  if (!verifyWebhook(payload, signature, webhookSecret)) {
    return res.status(401).send('Invalid signature');
  }
  
  // Process event
  res.status(200).send('OK');
});

Best practices

Return 200 quickly

Respond with 200 OK immediately and process asynchronously:
app.post('/webhooks', async (req, res) => {
  // Verify signature
  if (!verifySignature(req)) {
    return res.status(401).send('Invalid signature');
  }
  
  // Queue for processing
  await queue.add('webhook', req.body);
  
  // Return immediately
  res.status(200).send('OK');
});

Handle retries

Scalekit retries failed webhooks with exponential backoff:
  • Initial retry: 1 minute
  • Subsequent retries: 2, 4, 8, 16, 30 minutes
  • Maximum retries: 10 attempts

Idempotency

Process each webhook exactly once:
const processedEvents = new Set();

if (processedEvents.has(event.id)) {
  return res.status(200).send('Already processed');
}

processedEvents.add(event.id);
// Process event

Next steps

Webhook events

Available webhook events

Webhook security

Security best practices

Build docs developers (and LLMs) love