How to Set Up Webhooks for Authentication Events in Logto: A Complete Guide

Logto provides a built-in webhook system that sends real-time HTTP callbacks to your endpoint whenever authentication events like PostSignIn, PostRegister, or PostResetPassword occur, configurable via the Admin Console or Management API.

Setting up webhooks for authentication events in Logto enables your application to receive real-time notifications when users sign in, register, or reset passwords. The open-source identity infrastructure stores webhook configurations in the hooks table and delivers JSON payloads containing user context and event metadata to your specified URL. This guide explains how to configure these webhooks using both the Admin Console UI and programmatic approaches, with direct references to the source code in the logto-io/logto repository.

Authentication Events Available in Logto

Logto classifies hook events into two main categories as defined in packages/schemas/src/foundations/jsonb-types/hooks.ts:

InteractionHookEvent

These events trigger during user-facing authentication flows:

  • PostSignIn – Fires after a successful user sign-in
  • PostRegister – Fires after a new user completes registration
  • PostResetPassword – Fires after a password reset completes

DataHookEvent

These events fire when API-driven data changes occur, such as user profile updates or role modifications made outside of interactive sessions.

Creating a Webhook via the Management API

To programmatically set up webhooks for authentication events in Logto, send a POST request to /api/hooks with your target endpoint and desired event types. The request structure follows the CreateHookPayload type used in packages/console/src/pages/Webhooks/CreateFormModal/CreateForm.tsx.

// Replace with your Logto admin access token and desired endpoint
const token = 'YOUR_ADMIN_ACCESS_TOKEN';
const endpoint = 'https://your.example.com/webhook-receiver';

await fetch('https://<logto-host>/api/hooks', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${token}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: 'Auth events webhook',
    events: [
      'PostSignIn',          // InteractionHookEvent.PostSignIn
      'PostRegister',       // InteractionHookEvent.PostRegister
      'PostResetPassword',  // InteractionHookEvent.PostResetPassword
    ],
    config: { url: endpoint },
  }),
})
  .then((res) => res.json())
  .then((hook) => console.log('Created hook ID:', hook.id));

The database schema for these records is defined in packages/schemas/tables/hooks.sql, which stores the endpoint URL, event array, and configuration options.

Configuring Webhooks in the Admin Console

For UI-based configuration, the Logto Admin Console provides a Webhooks section. The frontend implementation in packages/console/src/pages/Webhooks/index.tsx and CreateFormModal/CreateForm.tsx constructs a payload containing name, events[], and config.url, posting it to the same /api/hooks endpoint. This approach handles the same underlying API but provides visual validation and event selection interfaces.

Testing Your Webhook Configuration

Before relying on production events, verify your endpoint receives and parses Logto's payload correctly using the test endpoint defined in packages/core/src/routes/hooks.openapi.json.

await fetch(`https://<logto-host>/api/hooks/${hookId}/test`, {
  method: 'POST',
  headers: { Authorization: `Bearer ${token}` },
  body: JSON.stringify({
    events: ['PostSignIn'],
    config: { url: endpoint },
  }),
});

The test triggers a dummy PostSignIn payload so you can verify that your receiver parses the JSON correctly without waiting for actual user authentication.

Verifying Webhook Payloads and Security

Each webhook request includes a signing key header (X-Logto-Signature) for authenticity verification. The payload structure follows the HookEventPayload union defined in packages/schemas/src/types/hook.ts, containing event, hookId, createdAt, userAgent, userIp, and event-specific data.

app.post('/webhook-receiver', express.json(), (req, res) => {
  const { event, hookId, createdAt, user, data } = req.body;
  console.log(`Webhook ${hookId} received ${event} at ${createdAt}`);
  // `event` will be one of the InteractionHookEvent strings.
  // `user` contains the user details for sign-in/register events.
  // `data` holds additional context for data-hook events.
  // Verify signature if you care about authenticity.
  res.sendStatus(204);
});

Rotating Signing Keys

For security maintenance, rotate your webhook signing key periodically via the Management API endpoint documented in packages/core/src/routes/hooks.openapi.json.

await fetch(`https://<logto-host>/api/hooks/${hookId}/signing-key`, {
  method: 'PATCH',
  headers: { Authorization: `Bearer ${token}` },
})
  .then((res) => res.json())
  .then((hook) => console.log('New signing key:', hook.signingKey));

Monitoring Webhook Execution

Logto stores execution logs and exposes them via GET /api/hooks/{id}/recent-logs. This endpoint supports pagination, time-range filtering (start_time, end_time), and optional capping for the last 24 hours of activity, helping you debug failed deliveries. The implementation references packages/schemas/src/consts/product-event.ts for product-level event logging.

Summary

  • Logto webhooks trigger on specific authentication events defined in packages/schemas/src/foundations/jsonb-types/hooks.ts, primarily InteractionHookEvent.PostSignIn, PostRegister, and PostResetPassword.
  • Configure webhooks via the Admin Console (React components in packages/console/src/pages/Webhooks/) or programmatically using the Management API endpoints defined in packages/core/src/routes/hooks.openapi.json.
  • Secure your integration by verifying the X-Logto-Signature header against your signing key and periodically rotating keys via PATCH /api/hooks/{id}/signing-key.
  • Monitor delivery health using the recent-logs endpoint to retrieve execution history with pagination support for the last 24 hours.

Frequently Asked Questions

What is the difference between InteractionHookEvent and DataHookEvent in Logto?

InteractionHookEvent triggers during user-facing authentication flows like sign-in, registration, and password resets, while DataHookEvent fires when API calls modify user data or roles. For authentication event notifications, you typically subscribe to InteractionHookEvent types such as PostSignIn or PostRegister as defined in packages/schemas/src/foundations/jsonb-types/hooks.ts.

How do I verify the authenticity of webhook requests from Logto?

Logto includes an X-Logto-Signature header in each webhook request containing a cryptographic signature. You should validate this signature against your stored signing key to ensure the payload originated from your Logto instance. Rotate your signing key periodically using the PATCH /api/hooks/{id}/signing-key endpoint defined in packages/core/src/routes/hooks.openapi.json to maintain security.

Can I test Logto webhooks before enabling them in production?

Yes, Logto provides a test endpoint at POST /api/hooks/{id}/test that sends a mock payload to your configured URL without requiring an actual authentication event. This allows you to verify your receiver correctly parses the HookEventPayload structure—including the event, user, and data fields—before handling real user traffic.

What information is included in the webhook payload?

The payload follows the HookEventPayload schema defined in packages/schemas/src/types/hook.ts and includes the event name (e.g., PostSignIn), hookId, createdAt timestamp, userAgent, userIp, and a data object containing context-specific information such as the user record for authentication events.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →