Webhooks
GET /orgs/{orgId}/api/v1/admin/webhooks
POST /orgs/{orgId}/api/v1/admin/webhooks
GET /orgs/{orgId}/api/v1/admin/webhooks/{webhookId}
PUT /orgs/{orgId}/api/v1/admin/webhooks/{webhookId}
DELETE /orgs/{orgId}/api/v1/admin/webhooks/{webhookId}
POST /orgs/{orgId}/api/v1/admin/webhooks/{webhookId}/rotate-secret
POST /orgs/{orgId}/api/v1/admin/webhooks/{webhookId}/enable
POST /orgs/{orgId}/api/v1/admin/webhooks/{webhookId}/disable
GET /orgs/{orgId}/api/v1/admin/webhooks/{webhookId}/deliveries
Webhooks allow your systems to receive real-time notifications when events occur in LumoAuth. All webhook payloads are signed with a rotating HMAC secret.
note
All webhook management endpoints require ROLE_TENANT_ADMIN or a valid admin API key.
Webhook Object
Webhook Object
{
"id": "01JF3KWBK...",
"url": "https://api.example.com/hooks/lumoauth",
"description": "User lifecycle events",
"events": ["user.created", "user.updated", "user.deleted"],
"enabled": true,
"signingSecret": "whsec_...",
"createdAt": "2026-01-15T10:30:00Z",
"updatedAt": "2026-03-01T08:00:00Z"
}
Supported Events
| Category | Event Types |
|---|---|
| User | user.created, user.updated, user.deleted, user.login, user.logout, user.blocked, user.unblocked, user.password_changed, user.mfa_enabled, user.mfa_disabled |
| Identity | identity.linked, identity.unlinked |
| Roles & Groups | role.assigned, role.unassigned, group.member_added, group.member_removed |
| Clients | client.created, client.deleted |
| Tokens & Consent | token.issued, token.revoked, consent.granted, consent.revoked |
| Wildcard | * — subscribe to all events |
Create a Webhook
Create Webhook
curl -X POST https://app.lumoauth.dev/orgs/acme-corp/api/v1/admin/webhooks \
-H "Authorization: ApiKey lmk_abc123" \
-H "Content-Type: application/json" \
-d '{
"url": "https://api.example.com/hooks/lumoauth",
"description": "User lifecycle events",
"events": ["user.created", "user.updated", "user.deleted", "user.login"]
}'
201 Created
{
"id": "01JF3KWBK...",
"url": "https://api.example.com/hooks/lumoauth",
"description": "User lifecycle events",
"events": ["user.created", "user.updated", "user.deleted", "user.login"],
"enabled": true,
"signingSecret": "whsec_AbCdEf123..."
}
warning
The signingSecret is only shown once at creation. Store it securely — use rotate-secret to generate a new one if lost.
Rotate Signing Secret
Rotate Signing Secret
curl -X POST https://app.lumoauth.dev/orgs/acme-corp/api/v1/admin/webhooks/01JF3KWBK.../rotate-secret \
-H "Authorization: ApiKey lmk_abc123"
New Secret
{
"signingSecret": "whsec_NewSecret..."
}
Delivery History
Get Delivery History
curl "https://app.lumoauth.dev/orgs/acme-corp/api/v1/admin/webhooks/01JF3KWBK.../deliveries" \
-H "Authorization: ApiKey lmk_abc123"
Delivery History
{
"deliveries": [
{
"id": "del_01JF3K...",
"event": "user.login",
"statusCode": 200,
"duration": 142,
"deliveredAt": "2026-03-01T08:00:00Z",
"request": { "payload": "{ \"type\": \"user.login\", ... }" },
"response": { "body": "ok" }
}
]
}
Verifying Webhook Signatures
LumoAuth signs every webhook payload with HMAC-SHA256. Verify the signature before trusting the payload:
Verify Signature (Node.js)
const crypto = require("crypto");
function verifyWebhook(payload, sigHeader, secret) {
const expected = crypto
.createHmac("sha256", secret)
.update(payload)
.digest("hex");
const received = sigHeader.replace("sha256=", "");
return crypto.timingSafeEqual(
Buffer.from(expected, "hex"),
Buffer.from(received, "hex")
);
}
Verify Signature (Python)
import hmac, hashlib
def verify_webhook(payload: bytes, sig_header: str, secret: str) -> bool:
expected = hmac.new(
secret.encode(), payload, hashlib.sha256
).hexdigest()
received = sig_header.removeprefix("sha256=")
return hmac.compare_digest(expected, received)
tip
Always use a constant-time comparison (timingSafeEqual / compare_digest) to prevent timing attacks.
Payload Format
Example Webhook Payload
{
"id": "evt_01JF3K...",
"type": "user.login",
"orgId": "acme-corp",
"createdAt": "2026-03-01T08:00:00Z",
"data": {
"userId": "01JF3KUSER...",
"email": "alice@example.com",
"ip": "203.0.113.1",
"userAgent": "Mozilla/5.0 ..."
}
}
Webhook requests include the following headers:
| Header | Value |
|---|---|
X-LumoAuth-Signature | sha256=<hex-hmac> |
X-LumoAuth-Event | Event type (e.g. user.login) |
X-LumoAuth-Delivery-Id | Unique delivery ID |
Content-Type | application/json |