How to Configure Webhooks in Logto: Complete Management API Guide
Logto delivers real-time event notifications to your HTTP endpoints through configurable webhooks managed via the Management API or Admin Console.
Configuring webhooks in Logto enables your system to react instantly to authentication events like user creation, sign-in, and password resets. The webhook architecture spans from PostgreSQL storage to React-based administration interfaces, providing cryptographically signed payloads for secure verification. This guide explains the database schema, REST API endpoints, and security mechanisms implemented in the logto-io/logto repository.
Webhook Architecture Overview
The Logto webhook system operates across five distinct layers, from persistent storage to the frontend interface.
Database Schema
The hooks table defined in packages/schemas/tables/hooks.sql stores webhook metadata including the tenant ID, endpoint URL, subscribed events, enabled status, signing key, and custom headers. Each webhook record is scoped to a specific tenant and includes a unique signingKey generated by generateStandardSecret() during creation.
Core Service Routes
The Management API implementation resides in packages/core/src/routes/hook.ts. This file defines the CRUD endpoints, test functionality, and log retrieval routes. The route handlers validate incoming data using Zod schemas from packages/schemas/src/types/hook.ts, specifically the Hooks.createGuard and hookConfigGuard validators.
Middleware Integration
The koaManagementApiHooks middleware (packages/core/src/middleware/koa-management-api-hooks.js) attaches the hook library to the Koa request context. This allows route handlers to access libraries.hooks for triggering deliveries through triggerInteractionHooks or triggerTestHook.
Hook Library
The createHookLibrary function in packages/core/src/tenants/Libraries.ts provides the execution engine. It fetches enabled webhooks subscribed to specific events, constructs JSON payloads, calculates HMAC-SHA256 signatures, and dispatches HTTP POST requests to configured endpoints.
Admin Console Frontend
The React-based UI consumes these APIs through components in packages/console/src/pages/TenantSettings/TenantMembers/hooks.ts, while shared constants and event definitions live in packages/console/src/consts/webhooks.ts.
Management API Endpoints
Logto exposes a comprehensive REST API for webhook lifecycle management. All endpoints require a valid Management API access token.
Creating Webhooks
Send a POST request to /api/hooks to create a new webhook. The API automatically generates a cryptographically secure signingKey and returns it in the response.
const createWebhook = async () => {
const response = await fetch(
`https://your-logto-domain/api/hooks`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer YOUR_ACCESS_TOKEN`,
},
body: JSON.stringify({
name: 'My Slack Notifier',
endpointUrl: 'https://hooks.slack.com/services/xxx/yyy/zzz',
events: ['User.Created', 'User.SignedIn'],
enabled: true,
config: {
headers: {
'X-Custom-Header': 'my-value',
},
},
}),
}
);
if (!response.ok) throw new Error('Failed to create webhook');
const hook = await response.json();
console.log('Created webhook:', hook);
};
Retrieving and Updating Webhooks
- List webhooks:
GET /api/hookssupports pagination viakoaPaginationand optional execution statistics via theincludeExecutionStats=truequery parameter. - Get single webhook:
GET /api/hooks/:idretrieves a specific webhook configuration. - Update webhook:
PATCH /api/hooks/:idaccepts partial updates toname,endpointUrl,events, orenabledstatus, validated againstHooks.createGuard. - Delete webhook:
DELETE /api/hooks/:idpermanently removes the webhook configuration.
const listWebhooks = async () => {
const res = await fetch(
`https://your-logto-domain/api/hooks?includeExecutionStats=true`,
{
headers: { Authorization: `Bearer YOUR_ACCESS_TOKEN` },
}
);
const hooks = await res.json();
console.table(hooks.map(h => ({
id: h.id,
name: h.name,
events: h.events,
enabled: h.enabled,
last24hExecutions: h.executionStats?.last24hCalls ?? 0,
})));
};
Testing and Debugging
The POST /api/hooks/:id/test endpoint sends synthetic payloads to your endpoint without requiring a real event to occur. This utilizes the triggerTestHook function from the hook library.
const testWebhook = async (hookId) => {
const res = await fetch(
`https://your-logto-domain/api/hooks/${hookId}/test`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer YOUR_ACCESS_TOKEN`,
},
body: JSON.stringify({
events: ['User.Created'],
config: {
headers: { 'X-Test': 'true' },
},
}),
}
);
if (res.status === 204) {
console.log('Test payload sent successfully');
} else {
const error = await res.json();
console.error('Test failed:', error);
}
};
Retrieving Execution Logs
Monitor webhook delivery through the GET /api/hooks/:id/recent-logs endpoint. It returns execution history from the last 24 hours by default, with optional filtering via start_time, end_time, and logKey parameters.
const fetchRecentLogs = async (hookId) => {
const url = new URL(`https://your-logto-domain/api/hooks/${hookId}/recent-logs`);
url.searchParams.set('start_time', `${Date.now() - 24 * 60 * 60 * 1000}`);
const res = await fetch(url, {
headers: { Authorization: `Bearer YOUR_ACCESS_TOKEN` },
});
const logs = await res.json();
console.log('Recent logs:', logs);
};
Security and Signature Verification
Logto cryptographically signs every webhook request to prevent tampering and verify authenticity.
Signature Header
Each POST request to your endpoint includes a Logto-Signature header containing an HMAC-SHA256 hash of the raw request body. The hash uses the webhook's unique signingKey stored in the hooks table.
Key Rotation
Rotate compromised or expired signing keys using the PATCH /api/hooks/:id/signing-key endpoint. This generates a new key via generateStandardSecret() and returns it in the response body.
const rotateKey = async (hookId) => {
const res = await fetch(
`https://your-logto-domain/api/hooks/${hookId}/signing-key`,
{
method: 'PATCH',
headers: { Authorization: `Bearer YOUR_ACCESS_TOKEN` },
}
);
const updatedHook = await res.json();
console.log('New signing key:', updatedHook.signingKey);
};
Webhook Delivery Lifecycle
Understanding the delivery mechanism helps debug failed requests and optimize endpoint performance.
- Event Trigger: When a user signs in or registers, the interaction middleware (
packages/core/src/routes/interaction/middleware/koa-interaction-hooks.ts) detects the event type. - Hook Resolution: The system calls
libraries.hooks.triggerInteractionHooks, which queries the database for enabled webhooks subscribed to that specific event. - Payload Construction: The library builds a JSON payload containing event data, tenant information, and timestamps.
- Signature Generation: The system calculates the HMAC-SHA256 signature using the webhook's
signingKeyand attaches it as theLogto-Signatureheader. - HTTP Dispatch: The library executes an HTTP POST to the configured
endpointUrl, including any custom headers defined in the webhookconfig. - Log Persistence: Execution results, including HTTP status codes and response times, are stored in the
logstable for retrieval via the recent-logs API.
Summary
- Configure webhooks in Logto through the Management API at
/api/hooksor the Admin Console UI. - The system stores webhook definitions in the
hookstable and validates them using Zod schemas frompackages/schemas/src/types/hook.ts. - Security relies on HMAC-SHA256 signatures in the
Logto-Signatureheader, with keys managed via the signing-key rotation endpoint. - Testing uses the
POST /hooks/:id/testendpoint to send synthetic payloads without triggering real events. - Monitoring is available through the recent-logs endpoint, which queries execution history stored in the
logstable.
Frequently Asked Questions
What events can trigger Logto webhooks?
Logto supports events including User.Created, User.Updated, User.Deleted, User.SignedIn, User.SignedOut, and various organization and role-related events. The complete list is defined in the hookEventGuard schema within packages/schemas/src/types/hook.ts.
How do I verify webhook signatures in my endpoint?
Retrieve the signingKey from your webhook configuration, then compute an HMAC-SHA256 hash of the raw request body. Compare this value to the Logto-Signature header sent by Logto. If they match, the request originated from your Logto instance and was not tampered with during transit.
Can I configure multiple webhooks for the same event?
Yes. Logto supports multiple webhook configurations per tenant, and all enabled webhooks subscribed to a specific event will receive the payload when that event occurs. Each webhook maintains its own signingKey and endpoint URL.
What is the retry policy for failed webhook deliveries?
Logto implements an automatic retry mechanism for failed deliveries based on HTTP response status codes. Temporary failures (5xx status codes and network timeouts) trigger retry attempts, while permanent failures (4xx status codes) are logged but not retried. Check the recent-logs endpoint to view detailed delivery attempts and failure reasons.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →