メインコンテンツまでスキップ

Webhooks リクエスト

Webhook イベントが発火すると、Logto はそれにサブスクライブしているすべてのエンドポイントに POST リクエストを送信します。全イベントカタログは Webhooks イベント にあります。本ページでは、Logto が配信する リクエストの構造 について説明します。

リクエストヘッダー

Keyカスタマイズ可備考
user-agentデフォルトは Logto (https://logto.io/)
content-typeデフォルトは application/json
logto-signature-sha-256リクエストボディの署名。Webhook のセキュリティ保護 を参照。

カスタマイズ可能なヘッダーは、セキュア Webhook 設定で上書きできます。

リクエストボディの概要

ボディは JSON オブジェクトです。その正確な構造は、イベントが属するファミリーによって異なります:

ファミリーイベント発火タイミング
ユーザーフローPostRegister, PostSignIn, PostResetPasswordエンドユーザーが Experience API でサインアップ・サインイン・パスワードリセットフローを完了したとき。
データ変更User.*, Role.*, Scope.*, Organization.*, OrganizationRole.*, OrganizationScope.*Management API の呼び出しや Experience API 上のユーザーフローで基礎データモデルが変更されたとき。
例外Identifier.Lockout, Message.RateLimited, Grant.LimitExceededセキュリティインシデント時。例:連続した認証失敗でアカウントがロックされた場合など。

すべてのファミリーは 共通フィールド を共有します。各ファミリーはさらに独自のリクエストコンテキストフィールドとイベント固有のペイロードを追加します。

共通フィールド

ファミリーに関係なくすべての配信に含まれるフィールド:

フィールドオプション備考
hookIdstringLogto の Webhook 設定識別子。
eventstringこの配信をトリガーしたイベント。
createdAtstringISO 8601 形式のペイロード作成時刻。
userAgentstringトリガーリクエストのユーザーエージェント。

各ファミリーはまた、トリガーリクエストの IP アドレスも含みます。ユーザーフローイベントでは userIp、データ変更・例外イベントでは ip というフィールド名です。意味は同じですが、後方互換性のため名前の違いが維持されています。

ユーザーフローイベントのペイロード

イベント: PostRegister, PostSignIn, PostResetPassword

エンドユーザーが Experience API でサインアップ・サインイン・パスワードリセットフローを完了したときに発火します。共通フィールド に加え、ボディには以下が含まれます:

フィールドオプション備考
interactionEvent'SignIn' | 'Register' | 'ForgotPassword'ユーザーフローイベントタイプ。PostSignIn / PostRegister / PostResetPassword にそれぞれ対応。フィールド名は歴史的な "interaction" を保持。
sessionIdstringこのイベントのセッション ID(Interaction ID ではありません)。該当する場合のみ。
userIpstringトリガーリクエストの IP アドレス。
userIdstringこのイベントに関連するユーザー ID。該当する場合のみ。
userUserEntityこのイベントに関連するユーザーエンティティ。該当する場合のみ。
applicationIdstringこのイベントに関連するアプリケーション ID。該当する場合のみ。
applicationApplicationEntityこのイベントに関連するアプリケーションエンティティ。該当する場合のみ。

エンティティの構造

type UserEntity = {
id: string;
username?: string;
primaryEmail?: string;
primaryPhone?: string;
name?: string;
avatar?: string;
customData?: object;
identities?: object;
lastSignInAt?: string;
createdAt?: string;
applicationId?: string;
isSuspended?: boolean;
};
enum ApplicationType {
Native = 'Native',
SPA = 'SPA',
Traditional = 'Traditional',
MachineToMachine = 'MachineToMachine',
Protected = 'Protected',
SAML = 'SAML',
}

type ApplicationEntity = {
id: string;
type: ApplicationType;
name: string;
description?: string;
};

全フィールドリファレンスは ユーザー および アプリケーション を参照してください。

データ変更イベントのペイロード

イベント: User.*, Role.*, Scope.*, Organization.*, OrganizationRole.*, OrganizationScope.* 配下のすべてのイベント。Webhooks イベント → データ変更 Webhook イベント で全カタログを確認できます。

ボディには常に以下が含まれます:

  • 共通フィールド
  • ip フィールド(トリガーリクエストの IP アドレス。オプション、判明している場合のみ)
  • API コンテキスト(変更がどのようにトリガーされたかを記述)。トリガー元により 2 種類のいずれか:
  • イベント固有のペイロードdata に影響を受けたエンティティ、または一部イベントでは追加のトップレベルフィールド。イベント固有データペイロード を参照

Experience API コンテキストフィールド

Experience API 上のユーザー向けフロー(例:サインアップ時の User.Created やプロフィール更新時の User.Data.Updated)でトリガーされた場合に含まれます。

フィールドオプション備考
interactionEvent'SignIn' | 'Register' | 'ForgotPassword'変更を生じさせたユーザーフローイベントタイプ。フィールド名は歴史的な "interaction" を保持。
sessionIdstringこのイベントのセッション ID(Interaction ID ではありません)。該当する場合のみ。
applicationIdstringアプリケーション ID。該当する場合のみ。
applicationApplicationEntityアプリケーションエンティティ。該当する場合のみ。

Management API コンテキストフィールド

Management API の呼び出しでトリガーされた場合に含まれます。

フィールドオプション備考
pathstringこの Webhook をトリガーした API 呼び出しのパス。
methodstringAPI 呼び出しの HTTP メソッド。
statusnumberAPI 呼び出しのレスポンスステータスコード。
paramsobjectAPI 呼び出しの koa パスパラメータ。
matchedRoutestringkoa のマッチしたルート。Logto はこのフィールドで有効な Webhook イベントフィルターを判別。

イベント固有データペイロード

すべてのデータ変更イベントは、影響を受けたエンティティを持つトップレベルの data フィールド(削除やメンバーシップイベントなど単一エンティティで要約できない場合は null)を含みます。一部イベントは data 以外にもトップレベルフィールドを持ちます。Organization.Membership.Updated がその一例で、下記で説明します。

ユーザーイベント

イベントフィールドオプション備考
User.CreateddataUserEntity作成されたユーザーエンティティ。
User.Data.UpdateddataUserEntity更新されたユーザーエンティティ。
User.Deleteddatanull/

ロールイベント

type Role = {
id: string;
name: string;
description: string;
type: 'User' | 'MachineToMachine';
isDefault: boolean;
};
type Scope = {
id: string;
name: string;
description: string;
resourceId: string;
createdAt: number;
};
イベントフィールドオプション備考
Role.CreateddataRole作成されたロールエンティティ。
Role.Data.UpdateddataRole更新されたロールエンティティ。
Role.Deleteddatanull/
Role.Scopes.UpdateddataScope[]ロールに割り当てられた更新後のスコープ。
Role.Scopes.UpdatedroleIdstringスコープが割り当てられたロール ID。(事前割り当てスコープ付きロール作成時のみ利用可能)

権限(スコープ)イベント

イベントフィールドオプション備考
Scope.CreateddataScope作成されたスコープエンティティ。
Scope.Data.UpdateddataScope更新されたスコープエンティティ。
Scope.Deleteddatanull/

組織イベント

type Organization = {
id: string;
name: string;
description?: string;
customData: object;
createdAt: number;
};
イベントフィールドオプション備考
Organization.CreateddataOrganization作成された組織エンティティ。
Organization.Data.UpdateddataOrganization更新された組織エンティティ。
Organization.Deleteddatanull/
Organization.Membership.Updateddatanull/変更内容はトップレベルのデルタ配列で記述。Organization.Membership.Updated ペイロード を参照。
Organization.Membership.Updated ペイロード

共通フィールド とトリガー元に応じた API コンテキストフィールド(Management API ルートなら Management API コンテキスト、ジャストインタイムプロビジョニングなら Experience API コンテキスト)に加え、Organization.Membership.Updated イベントは organizationId と、トップレベル(eventcreatedAt などと同階層、data の中ではなく)にオプションのデルタ配列を持ちます(このイベントの data は常に null)。

フィールドオプション備考
organizationIdstringメンバーシップが変更された組織。
addedUserIdsstring[]このトリガーで新たに追加されたユーザー ID。追加がなければ省略。ユーザーメンバーシップに影響しない場合も省略。
removedUserIdsstring[]このトリガーで削除されたユーザー ID。削除がなければ省略。
addedApplicationIdsstring[]新たに追加されたアプリケーション ID。追加がなければ省略。アプリケーションメンバーシップに影響しない場合も省略。
removedApplicationIdsstring[]削除されたアプリケーション ID。削除がなければ省略。

4 つのデルタ配列は オプションかつ加算的 です。これらを期待しないコンシューマーの既存ペイロード構造を壊さず、従来の data: null フィールドもそのまま出力されます。

トリガーと出力される可能性のあるデルタフィールド
トリガー出力される可能性のあるデルタフィールド
POST /organizations/:id/usersaddedUserIds
PUT /organizations/:id/usersaddedUserIds, removedUserIds
DELETE /organizations/:id/users/:userIdremovedUserIds
POST /organizations/:id/applicationsaddedApplicationIds
PUT /organizations/:id/applicationsaddedApplicationIds, removedApplicationIds
DELETE /organizations/:id/applications/:applicationIdremovedApplicationIds
PUT /organization-invitations/:id/status (Accepted)addedUserIds
ジャストインタイムプロビジョニングで新規組織にユーザー追加時addedUserIds
空のデルタは省略(省略 = 変更なし)

空のデルタ配列は 完全に省略 されます。例えば、PUT /organizations/:id/users で既存セットと同じメンバーシップに置き換えた場合、実質的な変更がないためペイロードは { organizationId } だけになり、4 つのデルタフィールドはすべて省略されます。同様に、既存メンバーの再追加や既存メンバーによる招待再受諾も同じです。

コンシューマーは、フィールドが存在しない場合は「その側に変更なし」とみなす必要があります。「空の変更」とはみなさないでください。

配列ごとの上限(サイレント切り捨て)

各デルタ配列は 最大 5000 件 で上限されます。1 回の Management API 呼び出しで 5000 件を超えるユーザー(またはアプリケーション)を追加・削除した場合、該当配列は最初の 5000 件にサイレントで切り捨てられます。ペイロード内に上限発動のマーカーはありません。

管理者向け一括操作で 1 回の呼び出しで 5000 件超のメンバーに影響する可能性がある場合、配列がちょうど 5000 件なら Management API で正規メンバーシップを再取得してください:

  • GET /organizations/:id/users:全ユーザーメンバーシップ
  • GET /organizations/:id/applications:全アプリケーションメンバーシップ

これは GitHub の push イベントが commits を 20 件で上限し、完全リストは compare API で取得するパターンと同じです。

No-op イベントのスキップ

コンシューマー側で no-op 配信(デルタフィールドなしイベント)をスキップするには、デルタ配列の存在でフィルタしてください:

if (
payload.addedUserIds?.length ||
payload.removedUserIds?.length ||
payload.addedApplicationIds?.length ||
payload.removedApplicationIds?.length
) {
// 実際のメンバーシップ変更があった場合のみ処理
}

?.lengthundefined[] の両方で falsy になるため、フィールドが存在しない場合も(将来的に空配列で出力される場合も)この判定で安全です。

ペイロード例

ユーザー追加(POST /organizations/:id/users):

{
"event": "Organization.Membership.Updated",
"organizationId": "org_abc",
"addedUserIds": ["u_001"]
}

ユーザーメンバーシップセットの置き換え(PUT /organizations/:id/users):

{
"event": "Organization.Membership.Updated",
"organizationId": "org_abc",
"addedUserIds": ["u_002"],
"removedUserIds": ["u_001"]
}

ユーザー削除(DELETE /organizations/:id/users/:userId):

{
"event": "Organization.Membership.Updated",
"organizationId": "org_abc",
"removedUserIds": ["u_001"]
}

アプリケーション追加(POST /organizations/:id/applications):

{
"event": "Organization.Membership.Updated",
"organizationId": "org_abc",
"addedApplicationIds": ["app_xyz"]
}

既存メンバーの再追加、no-op の PUT、既存メンバーによる招待再受諾(実質的な変更なし):

{
"event": "Organization.Membership.Updated",
"organizationId": "org_abc"
}

5000 件上限に達した一括操作(サイレント切り捨て):

{
"event": "Organization.Membership.Updated",
"organizationId": "org_abc",
"removedUserIds": ["u_0001", "u_0002", "/* … 合計ちょうど 5000 件 */"]
}

配列がちょうど 5000 件の場合は GET /organizations/:id/users(または /applications)で再取得してください。

組織ロールイベント

type OrganizationRole = {
id: string;
name: string;
description?: string;
};
type OrganizationScope = {
id: string;
name: string;
description?: string;
};
イベントフィールドオプション備考
OrganizationRole.CreateddataOrganizationRole作成された組織ロールエンティティ。
OrganizationRole.Data.UpdateddataOrganizationRole更新された組織ロールエンティティ。
OrganizationRole.Deleteddatanull/
OrganizationRole.Scopes.Updateddatanull/
OrganizationRole.Scopes.UpdatedorganizationRoleIdstringスコープが割り当てられたロール ID。(事前割り当てスコープ付きロール作成時のみ利用可能)

組織権限(スコープ)イベント

イベントフィールドオプション備考
OrganizationScope.CreateddataOrganizationScope作成された組織スコープエンティティ。
OrganizationScope.Data.UpdateddataOrganizationScope更新された組織スコープエンティティ。
OrganizationScope.Deleteddatanull/

例外イベントのペイロード

イベント: Identifier.Lockout, Message.RateLimited, Grant.LimitExceeded

セキュリティインシデント時(例:連続した認証失敗でアカウントがロックされた場合や、アプリの同時認証デバイス上限超過でグラントが破棄された場合)に発火します。

すべての例外イベントは 共通フィールドip フィールド(データ変更イベントと同じ構造)を持ちます。残りのフィールドはイベントごとに異なります。

Identifier.Lockout

ユーザー向けフローから発生するため、Experience API コンテキストフィールド も含まれます。加えて:

enum SignInIdentifier {
Email = 'email',
Phone = 'phone',
Username = 'username',
}
フィールドオプション備考
typeSignInIdentifierユーザーの識別子タイプ(例:email、phone、username)。
valuestringロックアウトを引き起こしたユーザーの識別子値。

Message.RateLimited

ユーザー向けフローから発生するため、Experience API コンテキストフィールド も含まれます。加えて:

フィールドオプション備考
actionstringレート制限されたアクション(例:VerificationCodeSend)。
recipientstring送信レート制限 に達したメールアドレスまたは電話番号。

Grant.LimitExceeded

認可 (Authorization) 成功時に、ユーザーがアプリの 最大同時認証デバイス数maxAllowedGrants)を超えた場合に発火し、Logto がそのアプリの最も古いグラントを破棄します。

このイベントは OIDC 認可 (Authorization) エンドポイントから発火するため、interactionEventsessionId は含まれません。共通フィールドと ip に加え、ボディには以下が含まれます:

フィールドオプション備考
userIdstringグラントが破棄されたユーザー。
applicationIdstringmaxAllowedGrants 上限を超えたアプリケーション。
applicationApplicationEntityアプリケーションエンティティ。配信時に解決できない場合は省略。
maxAllowedGrantsnumberイベント発火時にアプリケーションに設定されていた上限。
preRevocationActiveGrantCountnumber破棄前にこのアプリでユーザーが保持していたアクティブグラント数(今回発行分も含む)。
revokedGrantIdsstring[]実際に破棄されたグラント ID(古い順)。

ペイロード例:

{
"hookId": "hook_abc",
"event": "Grant.LimitExceeded",
"createdAt": "2024-01-01T00:00:00.000Z",
"ip": "192.168.0.1",
"userAgent": "Mozilla/5.0",
"userId": "u_001",
"applicationId": "app_xyz",
"application": {
"id": "app_xyz",
"type": "SPA",
"name": "My app",
"description": "My app description"
},
"maxAllowedGrants": 2,
"preRevocationActiveGrantCount": 3,
"revokedGrantIds": ["grant_001"]
}

配信に関する注意:

  • 破棄されたグラントレコードは破棄処理の一環で削除されるため、revokedGrantIds の ID はグラント一覧エンドポイントやコンソールでは アクティブ グラントのみ返されます。必要ならペイロードを記録してください。
  • 実際に 1 件以上のグラントが 破棄された場合のみ イベントが発火します。上限内であればイベントは発生しません。
  • 上限超過のたびに発火するため、許可された台数を超えて何度もサインインすると、その都度イベントが発生します。
  • 配信は fire-and-forget 方式です。遅延や失敗したエンドポイントでもユーザーの認可 (Authorization) をブロックしません。失敗した配信も他の Webhook と同様に監査ログに記録されます。