Webhooks overview
Understand how Scalekit webhooks deliver real-time notifications about authentication and user management events in your application
Scalekit sends webhooks to deliver real-time notifications about authentication and user management events. Webhooks provide instant updates when users sign up, log in, or when directory changes occur, eliminating the need to poll for changes.
Webhook delivery flow
Webhooks enable responsive integrations that react immediately to changes in Scalekit. Instead of polling APIs to check for updates, your application receives instant notifications about important events.
Key benefits include:
- Real-time updates: Get notified immediately when events occur
- Reduced API calls: No need to poll for changes
- Event-driven architecture: Build responsive workflows that react to user actions
- Reliable delivery: Scalekit ensures webhook delivery with automatic retries
Webhook event object
Section titled “Webhook event object”All webhook payloads follow a standardized structure with metadata and event-specific data in the data field.
{ "spec_version": "1", "id": "evt_123456789", "object": "DirectoryUser", "environment_id": "env_123456789", "occurred_at": "2024-08-21T10:20:17.072Z", "organization_id": "org_123456789", "type": "organization.directory.user_created", "data": { "user_id": "usr_123456789", "email": "user@example.com", "name": "John Doe" }}| Property | Description |
|---|---|
spec_version | The version of the event specification format. Currently “1”. |
id | A unique identifier for the event (e.g., evt_123456789). |
object | The type of object that triggered the event (e.g., “DirectoryUser”, “Directory”, “Connection”). |
environment_id | The ID of the environment where the event occurred. |
occurred_at | ISO 8601 timestamp indicating when the event occurred. |
organization_id | The ID of the organization associated with the event. |
type | The specific event type (e.g., “organization.directory.user_created”). |
data | Event-specific payload containing details relevant to the event type. |
Register webhook endpoints
Section titled “Register webhook endpoints”Register webhook endpoints in the Scalekit dashboard to receive event notifications. Each endpoint can subscribe to specific event types and receive payloads when those events occur.
-
Access webhook settings
Navigate to Dashboard > Webhooks in your Scalekit environment.
-
Create new endpoint
Click “Create Endpoint” and provide:
- Endpoint URL: Your application’s webhook handler URL
- Event types: Select which events to receive
- Description: Optional description for your reference
-
Copy webhook secret
After creating the endpoint, copy the webhook secret for signature verification.
-
Test the endpoint
Use the test functionality in the dashboard to send sample events to your endpoint.
Listen to webhooks
Section titled “Listen to webhooks”Create HTTP endpoints in your application to receive webhook payloads from Scalekit.
const express = require('express');const app = express();
// Parse JSON payloadsapp.use(express.json());
app.post('/webhook', async (req, res) => { try { // Extract webhook data const event = req.body; const headers = req.headers;
// Verify webhook signature (recommended) const isValid = await scalekit.verifyWebhookPayload( process.env.SCALEKIT_WEBHOOK_SECRET, headers, event );
if (!isValid) { return res.status(401).json({ error: 'Invalid signature' }); }
// Process the event await processWebhookEvent(event);
// Return success response res.status(200).json({ received: true });
} catch (error) { console.error('Webhook processing error:', error); res.status(500).json({ error: 'Internal server error' }); }});from flask import Flask, request, jsonifyimport scalekit
app = Flask(__name__)
@app.route('/webhook', methods=['POST'])def webhook(): try: # Get webhook data event = request.get_json() headers = dict(request.headers)
# Verify webhook signature (recommended) is_valid = scalekit.verify_webhook_payload( os.environ['SCALEKIT_WEBHOOK_SECRET'], headers, event )
if not is_valid: return jsonify({'error': 'Invalid signature'}), 401
# Process the event process_webhook_event(event)
# Return success response return jsonify({'received': True}), 200
except Exception as e: print(f'Webhook processing error: {e}') return jsonify({'error': 'Internal server error'}), 500package main
import ( "net/http" "os" "github.com/gin-gonic/gin" scalekit "github.com/scalekit-inc/go-sdk")
func main() { r := gin.Default()
r.POST("/webhook", func(c *gin.Context) { var event map[string]interface{}
if err := c.ShouldBindJSON(&event); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid JSON"}) return }
headers := make(map[string]string) for key, values := range c.Request.Header { if len(values) > 0 { headers[strings.ToLower(key)] = values[0] } }
// Verify webhook signature (recommended) secret := os.Getenv("SCALEKIT_WEBHOOK_SECRET") isValid, err := scalekit.VerifyWebhookPayload(secret, headers, event) if err != nil || !isValid { c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid signature"}) return }
// Process the event go processWebhookEvent(event)
// Return success response c.JSON(http.StatusOK, gin.H{"received": true}) })
r.Run()}@RestControllerpublic class WebhookController {
@Autowired private ScalekitClient scalekit;
@PostMapping("/webhook") public ResponseEntity<Map<String, Object>> handleWebhook( @RequestBody String body, @RequestHeader Map<String, String> headers) {
try { // Parse JSON payload ObjectMapper mapper = new ObjectMapper(); Map<String, Object> event = mapper.readValue(body, Map.class);
// Verify webhook signature (recommended) String secret = System.getenv("SCALEKIT_WEBHOOK_SECRET"); boolean isValid = scalekit.webhook().verifyWebhookPayload(secret, headers, body.getBytes());
if (!isValid) { return ResponseEntity.status(HttpStatus.UNAUTHORIZED) .body(Map.of("error", "Invalid signature")); }
// Process the event asynchronously processWebhookEvent(event);
// Return success response return ResponseEntity.ok(Map.of("received", true));
} catch (Exception e) { e.printStackTrace(); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body(Map.of("error", "Internal server error")); } }}Respond to webhooks
Section titled “Respond to webhooks”Scalekit expects specific HTTP status codes in response to webhook deliveries.
Success responses
Section titled “Success responses”| Status Code | Description |
|---|---|
200 OK | Webhook processed successfully |
201 Created Recommended | Webhook processed and resource created |
202 Accepted | Webhook accepted for asynchronous processing |
Error responses
Section titled “Error responses”| Status Code | Description |
|---|---|
400 Bad Request | Invalid payload or malformed request |
401 Unauthorized | Invalid webhook signature |
403 Forbidden | Webhook not authorized |
422 Unprocessable Entity | Valid request but cannot process |
500 Internal Server Error | Server error during processing |