Skip to main content

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

CategoryEvent Types
Useruser.created, user.updated, user.deleted, user.login, user.logout, user.blocked, user.unblocked, user.password_changed, user.mfa_enabled, user.mfa_disabled
Identityidentity.linked, identity.unlinked
Roles & Groupsrole.assigned, role.unassigned, group.member_added, group.member_removed
Clientsclient.created, client.deleted
Tokens & Consenttoken.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:

HeaderValue
X-LumoAuth-Signaturesha256=<hex-hmac>
X-LumoAuth-EventEvent type (e.g. user.login)
X-LumoAuth-Delivery-IdUnique delivery ID
Content-Typeapplication/json