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

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 呼び出しのパス。
methodstring✅API 呼び出しの HTTP メソッド。
statusnumber✅API 呼び出しのレスポンスステータスコード。
paramsobject✅API 呼び出しの koa パスパラメータ。
matchedRoutestring✅koa のマッチしたルート。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 と、トップレベル(event や createdAt などと同階層、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
) {
// 実際のメンバーシップ変更があった場合のみ処理
}

?.length は undefined と [] の両方で 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) エンドポイントから発火するため、interactionEvent や sessionId は含まれません。共通フィールドと 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 と同様に監査ログに記録されます。