Webhooks
Webhooks allow your application to receive real-time HTTP callbacks when events occur in AuthStack. This enables you to build reactive integrations without polling the API.
Overview
Section titled “Overview”Webhooks are configured at the application level. Each OAuth application can have multiple webhook subscriptions that trigger on specific events.
Endpoints
Section titled “Endpoints”| Method | Endpoint | Description |
|---|---|---|
| GET | /api/applications/{appId}/webhooks | List all webhooks for an application |
| POST | /api/applications/{appId}/webhooks | Create a new webhook |
| PUT | /api/applications/{appId}/webhooks/{webhookId} | Update a webhook |
| DELETE | /api/applications/{appId}/webhooks/{webhookId} | Delete a webhook |
| POST | /api/applications/{appId}/webhooks/{webhookId}/regenerate-secret | Regenerate webhook secret |
| GET | /api/applications/{appId}/webhooks/{webhookId}/deliveries | Get delivery history |
| GET | /api/applications/{appId}/webhooks/events | List available event types |
Available Events
Section titled “Available Events”| Event Type | Description |
|---|---|
user.created | Fired when a new user registers |
user.updated | Fired when a user profile is updated |
user.deleted | Fired when a user is deleted |
Creating a Webhook
Section titled “Creating a Webhook”POST /api/applications/{appId}/webhooksAuthorization: Bearer <access_token>Content-Type: application/json
{ "url": "https://your-server.com/webhooks/authstack", "events": ["user.created", "user.updated"], "maxRetries": 3, "retryDelaySeconds": 60}Request Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
url | string | Yes | The HTTPS URL to receive webhook payloads |
events | string[] | Yes | Array of event types to subscribe to |
maxRetries | number | No | Maximum retry attempts (default: 3) |
retryDelaySeconds | number | No | Delay between retries in seconds (default: 60) |
Response
Section titled “Response”{ "id": "550e8400-e29b-41d4-a716-446655440000", "organizationId": "org-id", "applicationId": "app-id", "applicationName": "My App", "url": "https://your-server.com/webhooks/authstack", "secret": "whsec_abc123...", "events": ["user.created", "user.updated"], "isActive": true, "maxRetries": 3, "retryDelaySeconds": 60, "createdAt": "2025-01-15T10:30:00Z"}Webhook Payload
Section titled “Webhook Payload”When an event occurs, AuthStack sends a POST request to your webhook URL:
POST https://your-server.com/webhooks/authstackContent-Type: application/jsonX-Webhook-Signature: sha256=abc123...X-Webhook-Event: user.createdX-Webhook-Delivery-Id: delivery-id
{ "id": "delivery-id", "event": "user.created", "timestamp": "2025-01-15T10:30:00Z", "data": { "userId": "user-id", "email": "user@example.com", "firstName": "John", "lastName": "Doe" }}Headers
Section titled “Headers”| Header | Description |
|---|---|
X-Webhook-Signature | HMAC-SHA256 signature of the payload |
X-Webhook-Event | The event type that triggered this delivery |
X-Webhook-Delivery-Id | Unique identifier for this delivery attempt |
Verifying Signatures
Section titled “Verifying Signatures”Always verify webhook signatures to ensure requests are from AuthStack.
Node.js Example
Section titled “Node.js Example”const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) { const expectedSignature = crypto .createHmac('sha256', secret) .update(payload) .digest('hex');
const expected = `sha256=${expectedSignature}`; return crypto.timingSafeEqual( Buffer.from(signature), Buffer.from(expected) );}
// Express middlewareapp.post('/webhooks/authstack', express.raw({ type: 'application/json' }), (req, res) => { const signature = req.headers['x-webhook-signature']; const payload = req.body.toString();
if (!verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET)) { return res.status(401).send('Invalid signature'); }
const event = JSON.parse(payload);
switch (event.event) { case 'user.created': // Handle new user break; case 'user.updated': // Handle user update break; }
res.status(200).send('OK');});Python Example
Section titled “Python Example”import hmacimport hashlib
def verify_webhook_signature(payload: bytes, signature: str, secret: str) -> bool: expected = hmac.new( secret.encode(), payload, hashlib.sha256 ).hexdigest()
return hmac.compare_digest(f"sha256={expected}", signature)
# Flask example@app.route('/webhooks/authstack', methods=['POST'])def handle_webhook(): signature = request.headers.get('X-Webhook-Signature') payload = request.get_data()
if not verify_webhook_signature(payload, signature, WEBHOOK_SECRET): return 'Invalid signature', 401
event = request.get_json()
if event['event'] == 'user.created': # Handle new user pass
return 'OK', 200Updating a Webhook
Section titled “Updating a Webhook”PUT /api/applications/{appId}/webhooks/{webhookId}Authorization: Bearer <access_token>Content-Type: application/json
{ "url": "https://your-server.com/webhooks/authstack-v2", "events": ["user.created", "user.updated", "user.deleted"], "isActive": true, "maxRetries": 5, "retryDelaySeconds": 120}Regenerating the Secret
Section titled “Regenerating the Secret”If your webhook secret is compromised, regenerate it immediately:
POST /api/applications/{appId}/webhooks/{webhookId}/regenerate-secretAuthorization: Bearer <access_token>Response
Section titled “Response”{ "secret": "whsec_newSecret123..."}Viewing Delivery History
Section titled “Viewing Delivery History”Monitor webhook deliveries and troubleshoot failures:
GET /api/applications/{appId}/webhooks/{webhookId}/deliveries?page=1&pageSize=50Authorization: Bearer <access_token>Response
Section titled “Response”{ "items": [ { "id": "delivery-id", "webhookId": "webhook-id", "event": "user.created", "statusCode": 200, "success": true, "attemptNumber": 1, "deliveredAt": "2025-01-15T10:30:00Z" } ], "totalCount": 150, "page": 1, "pageSize": 50}Retry Behavior
Section titled “Retry Behavior”When a webhook delivery fails (non-2xx response or timeout):
- AuthStack waits for
retryDelaySeconds - Retries up to
maxRetriestimes - Each retry is logged in the delivery history
A delivery is considered failed if:
- HTTP status code is not 2xx
- Request times out (30 seconds)
- Connection error occurs
Best Practices
Section titled “Best Practices”- Always verify signatures - Never process unverified webhooks
- Respond quickly - Return 200 within 30 seconds to avoid timeouts
- Process asynchronously - Queue webhook events for background processing
- Handle duplicates - Use delivery IDs to deduplicate events
- Use HTTPS - Webhook URLs must use HTTPS in production
- Monitor deliveries - Check delivery history for failures
- Regenerate secrets periodically - Rotate secrets as a security practice
Error Handling
Section titled “Error Handling”| Status Code | Description |
|---|---|
| 400 | Invalid request (missing URL, invalid events) |
| 401 | Unauthorized - invalid or expired token |
| 403 | Forbidden - not authorized for this application |
| 404 | Webhook or application not found |
| 500 | Server error |