Skip to content

Implement webhooks

Receive real-time notifications about authentication events in your application using Scalekit webhooks

Receive real-time notifications when authentication and user management events occur in your application. For example, when users are provisioned, updated, or deprovisioned through directory sync, Scalekit sends webhook events to your application so you can keep your systems synchronized automatically.

Scalekit sends POST requests to your webhook endpoint with event details, and waits for a 201 response to confirm receipt. For example, one event fires immediately after a user is provisioned via SCIM. We’ll explore more events throughout this guide.

Example of directory user created webhookIdPScalekitYour App Provision user via SCIMt POST /webhooks/manage-users Verify signature with signing secret Process event: sync user to DB Return 201 Created

You can receive webhooks for directory sync events, user provisioning changes, and other authentication events.

EventWhen it fires
organization.directory_enabledDirectory synchronization is activated for an organization
organization.directory_disabledDirectory synchronization is deactivated for an organization
organization.directory.user_createdNew user is provisioned via SCIM
organization.directory.user_updatedUser profile is updated via SCIM
organization.directory.user_deletedUser is deprovisioned via SCIM
organization.directory.group_createdNew group is created via SCIM
organization.directory.group_updatedGroup is updated via SCIM
organization.directory.group_deletedGroup is deleted via SCIM

At each event occurrence, Scalekit sends a POST request to your webhook endpoint with the relevant event details.

  1. Create an HTTPS endpoint that receives and verifies POST requests from Scalekit. This critical security step ensures requests are authentic and haven’t been tampered with.

    Express.js - Verify request signature
    // Security: ALWAYS verify requests are from Scalekit before processing
    // This prevents unauthorized parties from triggering your webhook handlers
    app.post('/webhooks/manage-users', async (req, res) => {
    try {
    // Parse the webhook headers for signature verification
    const headers = {
    'webhook-id': req.headers['webhook-id'],
    'webhook-signature': req.headers['webhook-signature'],
    'webhook-timestamp': req.headers['webhook-timestamp']
    };
    const event = req.body;
    // Get the signing secret from Scalekit dashboard > Settings > Webhooks
    // Store this securely in environment variables
    const webhookSecret = process.env.SCALEKIT_WEBHOOK_SECRET;
    // Initialize Scalekit client (reference installation guide for setup)
    const scalekit = new ScalekitClient(
    process.env.SCALEKIT_ENVIRONMENT_URL,
    process.env.SCALEKIT_CLIENT_ID,
    process.env.SCALEKIT_CLIENT_SECRET
    );
    // Verify the webhook payload signature
    // This confirms the request is from Scalekit and hasn't been tampered with
    await scalekit.verifyWebhookPayload(webhookSecret, headers, event);
    // ✓ Request verified - proceed to business logic (next step)
    } catch (error) {
    console.error('Webhook verification failed:', error);
    // Return 401 on verification failures to fail securely
    return res.status(401).json({
    error: 'Invalid signature'
    });
    }
    });
  2. After verification, parse the webhook event, apply your custom business logic, and return a 201 response to acknowledge receipt.

    Express.js - Business logic and response
    // Use case: Sync user data from directory to your application
    // Examples: User provisioning, deprovisioning, group membership updates
    app.post('/webhooks/manage-users', async (req, res) => {
    try {
    // ... (verification code from Step 1)
    // Parse the verified webhook event
    const event = req.body;
    // Process webhook asynchronously (don't block the response)
    // This allows us to respond quickly to prevent unnecessary retries
    processWebhookEvent(event).catch(error => {
    // Log error but don't throw - we already acknowledged receipt
    console.error('Async processing error:', error);
    });
    // IMPORTANT: Always respond with 201 to acknowledge receipt
    // Scalekit expects this response within 10 seconds
    return res.status(201).json({ received: true });
    } catch (error) {
    console.error('Webhook error:', error);
    return res.status(401).json({ error: 'Invalid signature' });
    }
    });
    async function processWebhookEvent(event) {
    console.log(`Processing event: ${event.type}`);
    switch (event.type) {
    case 'organization.directory.user_created':
    // Sync new user to your database
    await handleUserCreated(event.data);
    break;
    case 'organization.directory.user_updated':
    // Update user profile in your database
    await handleUserUpdated(event.data);
    break;
    case 'organization.directory.user_deleted':
    // Deprovision user from your application
    await handleUserDeleted(event.data);
    break;
    case 'organization.directory.group_created':
    // Handle new group creation
    await handleGroupCreated(event.data);
    break;
    default:
    console.log(`Unhandled event type: ${event.type}`);
    }
    }
    async function handleUserCreated(data) {
    // Use case: Sync new user to your database when provisioned via SCIM
    console.log(`New user created: ${data.email} in org: ${data.organization_id}`);
    // Sync to your database
    await syncUserToDatabase(data);
    // Grant default permissions
    await setupUserDefaults(data.id, data.organization_id);
    }
  3. Register the webhook in Scalekit dashboard

    Section titled “Register the webhook in Scalekit dashboard”

    Configure your webhook by specifying the endpoint URL, selecting events to receive, and setting up security.

    In the Scalekit dashboard, navigate to Settings > Webhooks to register your endpoint.

    • Click Add Endpoint and provide:
      • Endpoint URL - Your application’s HTTPS webhook handler (e.g., https://yourapp.com/webhooks/manage-users)
      • Description - Optional description for this endpoint
    • Select which events you want to receive:
      • Directory sync events (organization.directory_enabled, organization.directory_disabled)
      • User events (organization.directory.user_created, user_updated, user_deleted)
      • Group events (organization.directory.group_created, group_updated, group_deleted)
    • Copy the Signing Secret to verify webhook authenticity in your application
    • Click Create
    • Toggle Enable to activate the webhook
  4. Use the Test tab in the Scalekit dashboard to verify your implementation before enabling it in production.

    • Open the Test tab on the Webhooks page
    • The left panel shows the request body sent to your endpoint
    • Click Send Test Event to test your webhook handler
    • The right panel shows your application’s response
    • Verify your endpoint returns a 201 status code
  5. Scalekit keeps a log of every webhook request sent to your application and the response it returned. Use these logs to debug and troubleshoot issues.

    • Navigate to Settings > Webhooks in your dashboard
    • Select your webhook endpoint
    • Click on the Logs tab to view request history
    • Each log entry shows the request payload, response status, and timestamps

    Requests and responses generated by the “Test” button are not logged. This keeps production logs free of test data.