diff --git a/docs/developers/webhooks/events.mdx b/docs/developers/webhooks/events.mdx
index c57852f074a..66b7dfd1518 100644
--- a/docs/developers/webhooks/events.mdx
+++ b/docs/developers/webhooks/events.mdx
@@ -47,12 +47,12 @@ This guide list the different Logto webhook events and explains when each event
### Organization \{#organization}
-| Event type | Description |
-| ------------------------------- | ------------------------------------------------------------------------------------------ |
-| Organization.Created | A new organization is created. |
-| Organization.Deleted | An organization is deleted. |
-| Organization.Data.Updated | An organization's data is updated, e.g., organization name, description, custom.data, etc. |
-| Organization.Membership.Updated | Members are added or removed from an organization. |
+| Event type | Description |
+| ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Organization.Created | A new organization is created. |
+| Organization.Deleted | An organization is deleted. |
+| Organization.Data.Updated | An organization's data is updated, e.g., organization name, description, custom.data, etc. |
+| Organization.Membership.Updated | Users or applications are added to or removed from an organization. Payload includes [membership delta fields](/developers/webhooks/webhooks-request#organizationmembershipupdated-payload). |
### Organization role \{#organization-role}
@@ -96,6 +96,10 @@ This guide list the different Logto webhook events and explains when each event
| PUT /organizations/:id/users | Organization.Membership.Updated |
| POST /organizations/:id/users | Organization.Membership.Updated |
| DELETE /organizations/:id/users/:userId | Organization.Membership.Updated |
+| PUT /organizations/:id/applications | Organization.Membership.Updated |
+| POST /organizations/:id/applications | Organization.Membership.Updated |
+| DELETE /organizations/:id/applications/:applicationId | Organization.Membership.Updated |
+| PUT /organization-invitations/:id/status (Accepted) | Organization.Membership.Updated |
| POST /organization-roles | OrganizationRole.Created, (OrganizationRole.Scopes.Updated) |
| DELETE /organization-roles/:id | OrganizationRole.Deleted |
| PATCH /organization-roles/:id | OrganizationRole.Data.Updated |
@@ -108,13 +112,14 @@ This guide list the different Logto webhook events and explains when each event
### Experience API triggered events \{#experience-api-triggered-events}
-| User interaction action | Event |
-| ------------------------ | ----------------- |
-| User email/phone linking | User.Data.Updated |
-| User MFAs linking | User.Data.Updated |
-| User social/SSO linking | User.Data.Updated |
-| User password reset | User.Data.Updated |
-| User registration | User.Created |
+| User interaction action | Event |
+| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------- |
+| User email/phone linking | User.Data.Updated |
+| User MFAs linking | User.Data.Updated |
+| User social/SSO linking | User.Data.Updated |
+| User password reset | User.Data.Updated |
+| User registration | User.Created |
+| User auto-provisioned into an organization via [just-in-time provisioning](/organizations/just-in-time-provisioning) (matching email domain or enterprise SSO connector) | Organization.Membership.Updated |
## Exception hook events \{#exception-hook-events}
diff --git a/docs/developers/webhooks/request.mdx b/docs/developers/webhooks/request.mdx
index 5790db7a553..63a238d0232 100644
--- a/docs/developers/webhooks/request.mdx
+++ b/docs/developers/webhooks/request.mdx
@@ -7,23 +7,60 @@ sidebar_position: 4
# Webhooks request
-Once a valid hook event is emitted, Logto will find corresponding webhooks and send a POST request per hook config.
+When a webhook event fires, Logto sends a `POST` request to every endpoint subscribed to it. The full event catalog lives in [Webhooks events](/developers/webhooks/webhooks-events); this page documents the **shape of the request** Logto delivers.
## Request headers \{#request-headers}
-| Key | Customizable | Notes |
-| ----------------------- | ------------ | ----------------------------------------------------------------------------------------------------------- |
-| user-agent | ✅ | `Logto (https://logto.io/)` by default. |
-| content-type | ✅ | `application/json` by default. |
-| logto-signature-sha-256 | | the signature of the request body, refer to [securing your webhooks](/developers/webhooks/secure-webhooks). |
+| Key | Customizable | Notes |
+| ----------------------- | ------------ | -------------------------------------------------------------------------------------------------- |
+| user-agent | ✅ | `Logto (https://logto.io/)` by default. |
+| content-type | ✅ | `application/json` by default. |
+| logto-signature-sha-256 | | Signature of the request body. See [securing your webhooks](/developers/webhooks/secure-webhooks). |
-You can overwrite customizable headers by [customizing request](/developers/webhooks/configure-webhooks/#secure-webhook) headers with the same key.
+Customizable headers can be overridden via the [secure webhook](/developers/webhooks/configure-webhooks/#secure-webhook) configuration.
-## Interaction hook events request body \{#interaction-hook-events-request-body}
+## Request body overview \{#request-body-overview}
-Available events: `PostRegister`, `PostSignIn`, `PostResetPassword`
+The body is a JSON object. Its exact shape depends on which family the event belongs to:
-The request body is a JSON object that contains three types of data field:
+| Family | Events | When it fires |
+| ----------------- | -------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
+| **User flow** | `PostRegister`, `PostSignIn`, `PostResetPassword` | A user completes a sign-up, sign-in, or password-reset flow handled by the Experience API. |
+| **Data mutation** | `User.*`, `Role.*`, `Scope.*`, `Organization.*`, `OrganizationRole.*`, `OrganizationScope.*` | The underlying data model is mutated by a Management API call or a user flow on the Experience API. |
+| **Exception** | `Identifier.Lockout` | A security incident, for example an account locked after consecutive failed verification attempts. |
+
+Every family shares a small set of [common fields](#common-fields). Each family then layers on its own request-context fields plus an event-specific payload.
+
+### Common fields \{#common-fields}
+
+Present in every delivery regardless of family:
+
+| Field | Type | Optional | Notes |
+| --------- | -------- | -------- | ---------------------------------------------- |
+| hookId | `string` | | The webhook configuration identifier in Logto. |
+| event | `string` | | The event that triggered this delivery. |
+| createdAt | `string` | | The payload creation time in ISO 8601 format. |
+| userAgent | `string` | ✅ | The user-agent of the triggering request. |
+
+Each family also includes the IP address of the triggering request, under the field name `userIp` for user-flow events and `ip` for data-mutation and exception events. The semantics are identical; the historical name difference is preserved for backward compatibility.
+
+## User flow event payloads \{#user-flow-event-payloads}
+
+**Events:** `PostRegister`, `PostSignIn`, `PostResetPassword`.
+
+Fired when a user completes a sign-up, sign-in, or password-reset flow handled by the Experience API. In addition to the [common fields](#common-fields), the body carries:
+
+| Field | Type | Optional | Notes |
+| ---------------- | -------------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| interactionEvent | `'SignIn' \| 'Register' \| 'ForgotPassword'` | | The user-flow event type. Maps to `PostSignIn` / `PostRegister` / `PostResetPassword` respectively. The field name retains historical "interaction" naming. |
+| sessionId | `string` | ✅ | The Session ID (not Interaction ID) for this event, if applicable. |
+| userIp | `string` | ✅ | The IP address of the triggering request. |
+| userId | `string` | ✅ | The User ID associated with this event, if applicable. |
+| user | `UserEntity` | ✅ | The user entity associated with this event, if applicable. |
+| applicationId | `string` | ✅ | The Application ID associated with this event, if applicable. |
+| application | `ApplicationEntity` | ✅ | The application entity associated with this event, if applicable. |
+
+#### Entity shapes \{#user-flow-entity-shapes}
```tsx
type UserEntity = {
@@ -60,70 +97,57 @@ type ApplicationEntity = {
};
```
-| Field | Type | Optional | Notes |
-| ---------------- | ------------------- | -------- | ------------------------------------------------------------------ |
-| hookId | `string` | | The identifier in Logto. |
-| event | `string` | | Which event that triggers this hook. |
-| createdAt | `string` | | The create time of payload in ISO format. |
-| interactionEvent | `string` | | The interaction event that triggers this hook. |
-| sessionId | `string` | ✅ | The Session ID (not Interaction ID) for this event, if applicable. |
-| userAgent | `string` | ✅ | The user-agent for the request that triggers this hook. |
-| userIp | `string` | ✅ | The IP address for the request that triggers this hook. |
-| userId | `string` | ✅ | The related User ID for this event, if applicable. |
-| user | `UserEntity` | ✅ | The related user entity for this event, if applicable. |
-| applicationId | `string` | ✅ | The related Application ID for this event, if applicable. |
-| application | `ApplicationEntity` | ✅ | The related application info for this event, if applicable. |
+See [Users](/user-management/user-data) and [Applications](/integrate-logto/application-data-structure) for the full field reference.
-See [Users](/user-management/user-data) and [Applications](/integrate-logto/application-data-structure) reference for detailed field explanations.
+## Data mutation event payloads \{#data-mutation-event-payloads}
-## Data mutation hook events request body \{#data-mutation-hook-events-request-body}
+**Events:** every event under `User.*`, `Role.*`, `Scope.*`, `Organization.*`, `OrganizationRole.*`, `OrganizationScope.*`. See [Webhooks events → Data mutation hook events](/developers/webhooks/webhooks-events#data-mutation-hook-events) for the complete catalog.
-### Standard request body fields \{#standard-request-body-fields}
+The body always carries:
-| Field | Type | Optional | Notes |
-| --------- | -------- | -------- | ----------------------------------------- |
-| hookId | `string` | | The identifier in Logto. |
-| event | `string` | | Which event that triggers this hook. |
-| createdAt | `string` | | The create time of payload in ISO format. |
-| userAgent | `string` | ✅ | The user-agent for the request. |
-| ip | `string` | ✅ | The IP address for the request. |
+- The [common fields](#common-fields).
+- An `ip` field, the IP address of the triggering request (optional, present when known).
+- An **API context** describing how the change was triggered. The context is one of two variants depending on the trigger source:
+ - [Experience API context](#experience-api-context-fields), when the change came from a user-facing flow.
+ - [Management API context](#management-api-context-fields), when the change came from a direct Management API call.
+- An **event-specific payload**: the affected entity in `data` and (for some events) additional top-level fields. See [event-specific data payloads](#event-specific-data-payloads).
-### Interaction API context body fields \{#interaction-api-context-body-fields}
+### Experience API context fields \{#experience-api-context-fields}
-Data mutation hook events that are triggered by user interaction API calls.
+Present when the change was triggered by a user-facing flow on the Experience API, for example `User.Created` during sign-up or `User.Data.Updated` during profile updates.
-Available events: `User.Created`, `User.Data.Updated`
+| Field | Type | Optional | Notes |
+| ---------------- | -------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------ |
+| interactionEvent | `'SignIn' \| 'Register' \| 'ForgotPassword'` | ✅ | The user-flow event type that produced the change. Field name retains historical "interaction" naming. |
+| sessionId | `string` | ✅ | The Session ID (not Interaction ID) for this event, if applicable. |
+| applicationId | `string` | ✅ | The Application ID, if applicable. |
+| application | `ApplicationEntity` | ✅ | The application entity, if applicable. |
-| Field | Type | Optional | Notes |
-| ---------------- | ------------------- | -------- | ------------------------------------------------------------------ |
-| interactionEvent | `string` | ✅ | The interaction event that triggers this hook. |
-| sessionId | `string` | ✅ | The Session ID (not Interaction ID) for this event, if applicable. |
-| applicationId | `string` | ✅ | The related Application ID for this event, if applicable. |
-| application | `ApplicationEntity` | ✅ | The related application info for this event, if applicable. |
+### Management API context fields \{#management-api-context-fields}
-### Management API context body fields \{#management-api-context-body-fields}
+Present when the change was triggered by a Management API call.
-Data mutation hook events that are triggered by Management API calls.
+| Field | Type | Optional | Notes |
+| ------------ | -------- | -------- | ------------------------------------------------------------------------------------ |
+| path | `string` | ✅ | The path of the API call that triggered this hook. |
+| method | `string` | ✅ | The HTTP method of the API call. |
+| status | `number` | ✅ | The response status code of the API call. |
+| params | `object` | ✅ | The koa path params of the API call. |
+| matchedRoute | `string` | ✅ | The koa matched route. Logto uses this field to match enabled webhook event filters. |
-| Field | Type | Optional | Notes |
-| ------------ | -------- | -------- | ---------------------------------------------------------------------------------------------------------------------- |
-| path | `string` | ✅ | The path of the API call that triggers this hook. |
-| method | `string` | ✅ | The method of the API call that triggers this hook. |
-| status | `number` | ✅ | The response status code of the API call that triggers this hook. |
-| params | `object` | ✅ | The request koa path params of the API call that triggers this hook. |
-| matchedRoute | `string` | ✅ | The koa matched route of the API call that triggers this hook. Logto uses this field to match the enabled hook events. |
+### Event-specific data payloads \{#event-specific-data-payloads}
-### Data payload body fields \{#data-payload-body-fields}
+Every data-mutation event includes a top-level `data` field carrying the affected entity, or `null` when the change can't be summarized as a single entity (delete and membership events). Some events also include event-specific top-level fields beyond `data`; `Organization.Membership.Updated` is one such case, documented below.
-**User events**
+#### User events \{#user-events}
-| Event | Field | Type | Optional | Notes |
-| ----------------- | ----- | ---------- | -------- | --------------------------------------- |
-| User.Created | data | UserEntity | | The created user entity for this event. |
-| User.Data.Updated | data | UserEntity | | The updated user entity for this event. |
-| User.Deleted | data | null | / | |
+| Event | Field | Type | Optional | Notes |
+| ----------------- | ----- | ------------ | -------- | ------------------------ |
+| User.Created | data | `UserEntity` | | The created user entity. |
+| User.Data.Updated | data | `UserEntity` | | The updated user entity. |
+| User.Deleted | data | `null` | / | |
-**Role events**
+#### Role events \{#role-events}
```tsx
type Role = {
@@ -145,23 +169,23 @@ type Scope = {
};
```
-| Event | Field | Type | Optional | Notes |
-| ------------------ | ------ | ------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------- |
-| Role.Created | data | Role | | The created role entity for this event. |
-| Role.Data.Updated | data | Role | | The updated role entity for this event. |
-| Role.Deleted | data | null | | |
-| Role.Scope.Updated | data | Scope[] | | The updated scopes assigned to the role. |
-| Role.Scope.Updated | roleId | string | ✅ | The role ID that scopes are assigned to. (Only available when the event was triggered by create new role with pre-assigned scopes) |
+| Event | Field | Type | Optional | Notes |
+| ------------------- | ------ | --------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------- |
+| Role.Created | data | `Role` | | The created role entity. |
+| Role.Data.Updated | data | `Role` | | The updated role entity. |
+| Role.Deleted | data | `null` | / | |
+| Role.Scopes.Updated | data | `Scope[]` | | The updated scopes assigned to the role. |
+| Role.Scopes.Updated | roleId | `string` | ✅ | The role ID that scopes are assigned to. (Only available when the event was triggered by creating a role with pre-assigned scopes.) |
-**Permission(Scope) events**
+#### Permission (Scope) events \{#permission-events}
-| Event | Field | Type | Optional | Notes |
-| ------------------ | ----- | ----- | -------- | ---------------------------------------- |
-| Scope.Created | data | Scope | | The created scope entity for this event. |
-| Scope.Data.Updated | data | Scope | | The updated scope entity for this event. |
-| Scope.Deleted | data | null | / | |
+| Event | Field | Type | Optional | Notes |
+| ------------------ | ----- | ------- | -------- | ------------------------- |
+| Scope.Created | data | `Scope` | | The created scope entity. |
+| Scope.Data.Updated | data | `Scope` | | The updated scope entity. |
+| Scope.Deleted | data | `null` | / | |
-**Organization events**
+#### Organization events \{#organization-events}
```tsx
type Organization = {
@@ -173,14 +197,139 @@ type Organization = {
};
```
-| Event | Field | Type | Optional | Notes |
-| ------------------------------- | ----- | ------------ | -------- | ----------------------------------------------- |
-| Organization.Created | data | Organization | | The created organization entity for this event. |
-| Organization.Data.Updated | data | Organization | | The updated organization entity for this event. |
-| Organization.Deleted | data | null | / | |
-| Organization.Membership.Updated | data | null | / | |
+| Event | Field | Type | Optional | Notes |
+| ------------------------------- | ----- | -------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Organization.Created | data | `Organization` | | The created organization entity. |
+| Organization.Data.Updated | data | `Organization` | | The updated organization entity. |
+| Organization.Deleted | data | `null` | / | |
+| Organization.Membership.Updated | data | `null` | / | The change is described by optional top-level delta arrays. See [Organization.Membership.Updated payload](#organizationmembershipupdated-payload) below. |
+
+##### Organization.Membership.Updated payload \{#organizationmembershipupdated-payload}
+
+In addition to the [common fields](#common-fields) and the API-context fields that apply for the trigger source ([Management API context](#management-api-context-fields) for Management API routes, [Experience API context](#experience-api-context-fields) for just-in-time provisioning), the `Organization.Membership.Updated` event carries an `organizationId` plus optional delta arrays at the top level of the payload (next to `event`, `createdAt`, etc., **not** inside `data`, which is always `null` for this event).
+
+| Field | Type | Optional | Notes |
+| --------------------- | ---------- | -------- | --------------------------------------------------------------------------------------------------------------------------------- |
+| organizationId | `string` | | The organization whose membership changed. |
+| addedUserIds | `string[]` | ✅ | User IDs newly added by this trigger. Omitted when no users were added, or when the trigger does not affect user membership. |
+| removedUserIds | `string[]` | ✅ | User IDs removed by this trigger. Omitted when no users were removed. |
+| addedApplicationIds | `string[]` | ✅ | Application IDs newly added. Omitted when no applications were added, or when the trigger does not affect application membership. |
+| removedApplicationIds | `string[]` | ✅ | Application IDs removed. Omitted when no applications were removed. |
+
+The four delta arrays are **optional and additive**: they don't change the existing payload shape for consumers that don't expect them, and the legacy `data: null` field is still emitted unchanged.
+
+###### Triggers and which delta fields they may emit \{#membership-triggers}
+
+| Trigger | Possible delta fields |
+| -------------------------------------------------------------------- | ---------------------------------------------- |
+| `POST /organizations/:id/users` | `addedUserIds` |
+| `PUT /organizations/:id/users` | `addedUserIds`, `removedUserIds` |
+| `DELETE /organizations/:id/users/:userId` | `removedUserIds` |
+| `POST /organizations/:id/applications` | `addedApplicationIds` |
+| `PUT /organizations/:id/applications` | `addedApplicationIds`, `removedApplicationIds` |
+| `DELETE /organizations/:id/applications/:applicationId` | `removedApplicationIds` |
+| `PUT /organization-invitations/:id/status` (`Accepted`) | `addedUserIds` |
+| Just-in-time provisioning when adding the user to a new organization | `addedUserIds` |
+
+###### Empty deltas are omitted (absent ≠ empty change) \{#empty-deltas-are-omitted}
+
+Empty delta arrays are **omitted entirely** from the payload. For example, a `PUT /organizations/:id/users` that replaces the membership set with the existing set produces no real change, and the payload reduces to just `{ organizationId }` with all four delta fields absent. The same applies to a re-add of an existing member and a re-accept of an invitation by a user who is already a member.
+
+**Consumers must treat a missing field as "no change on that side," not as "an empty change."**
+
+###### Per-array cap (silent truncation) \{#membership-delta-cap}
+
+Each delta array is capped at **5000 entries**. When a single Management API call adds or removes more than 5000 users (or applications) in one operation, the corresponding delta array is silently truncated to its first 5000 entries. **There is no in-payload marker** that a cap fired.
+
+If your application performs administrative bulk operations that can plausibly affect more than 5000 members in one call, treat an array of exactly 5000 entries as a signal to reconcile authoritative membership via the Management API:
+
+- `GET /organizations/:id/users`: full user membership.
+- `GET /organizations/:id/applications`: full application membership.
+
+This follows the same pattern as GitHub's `push` event, which caps `commits` at 20 entries and points consumers at the compare API for the full list.
+
+###### Skipping no-op events \{#skipping-no-op-events}
+
+To skip no-op deliveries (events with no delta fields) on the consumer side, filter on delta-array presence:
+
+```ts
+if (
+ payload.addedUserIds?.length ||
+ payload.removedUserIds?.length ||
+ payload.addedApplicationIds?.length ||
+ payload.removedApplicationIds?.length
+) {
+ // real membership change, handle it
+}
+```
-**OrganizationRole events**
+`?.length` is falsy for both `undefined` and `[]`, so the same predicate is robust whether the field is absent or (in some hypothetical future) emitted as an empty array.
+
+###### Example payloads \{#membership-example-payloads}
+
+**Add a user (`POST /organizations/:id/users`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "addedUserIds": ["u_001"]
+}
+```
+
+**Replace the user membership set (`PUT /organizations/:id/users`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "addedUserIds": ["u_002"],
+ "removedUserIds": ["u_001"]
+}
+```
+
+**Remove a user (`DELETE /organizations/:id/users/:userId`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "removedUserIds": ["u_001"]
+}
+```
+
+**Add an application (`POST /organizations/:id/applications`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "addedApplicationIds": ["app_xyz"]
+}
+```
+
+**Re-add an existing member, no-op `PUT`, or re-accept of an already-member invitation (no real change):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc"
+}
+```
+
+**Bulk operation that hits the 5000 cap (silently truncated):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "removedUserIds": ["u_0001", "u_0002", "/* … exactly 5000 entries total */"]
+}
+```
+
+Seeing an array of exactly 5000 entries should prompt a reconciling `GET /organizations/:id/users` (or `/applications`).
+
+#### Organization role events \{#organization-role-events}
```tsx
type OrganizationRole = {
@@ -198,27 +347,32 @@ type OrganizationScope = {
};
```
-| Event | Field | Type | Optional | Notes |
-| ------------------------------ | ------------------ | ---------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------- |
-| OrganizationRole.Created | data | OrganizationRole | | The created organization role entity for this event. |
-| OrganizationRole.Data.Updated | data | OrganizationRole | | The updated organization role entity for this event. |
-| OrganizationRole.Deleted | data | null | / | |
-| OrganizationRole.Scope.Updated | data | null | / | |
-| OrganizationRole.Scope.Updated | organizationRoleId | string | ✅ | The role ID that scopes are assigned to. (Only available when the event was triggered by create new role with pre-assigned scopes) |
+| Event | Field | Type | Optional | Notes |
+| ------------------------------- | ------------------ | ------------------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------- |
+| OrganizationRole.Created | data | `OrganizationRole` | | The created organization role entity. |
+| OrganizationRole.Data.Updated | data | `OrganizationRole` | | The updated organization role entity. |
+| OrganizationRole.Deleted | data | `null` | / | |
+| OrganizationRole.Scopes.Updated | data | `null` | / | |
+| OrganizationRole.Scopes.Updated | organizationRoleId | `string` | ✅ | The role ID that scopes are assigned to. (Only available when the event was triggered by creating a role with pre-assigned scopes.) |
+
+#### Organization permission (scope) events \{#organization-permission-events}
-**Organization permission(OrganizationScope) events**
+| Event | Field | Type | Optional | Notes |
+| ------------------------------ | ----- | ------------------- | -------- | -------------------------------------- |
+| OrganizationScope.Created | data | `OrganizationScope` | | The created organization scope entity. |
+| OrganizationScope.Data.Updated | data | `OrganizationScope` | | The updated organization scope entity. |
+| OrganizationScope.Deleted | data | `null` | / | |
-| Event | Field | Type | Optional | Notes |
-| ------------------------------ | ----- | ----------------- | -------- | -------------------------------------- |
-| OrganizationScope.Created | data | OrganizationScope | | The created organization scope entity. |
-| OrganizationScope.Data.Updated | data | OrganizationScope | | The updated organization scope entity. |
-| OrganizationScope.Deleted | data | null | / | |
+## Exception event payloads \{#exception-event-payloads}
-## Exception hook events request body \{#exception-hook-events-request-body}
+**Events:** `Identifier.Lockout`.
-Available events: `Identifier.Lockout`
+Fired on security incidents, for example an account locked after consecutive failed verification attempts. These events always originate from a user-facing flow, so the body carries:
-The request body is a JSON object that contains the standard request body fields and additional fields as below:
+- The [common fields](#common-fields).
+- The `ip` field (same shape as data-mutation events).
+- The [Experience API context fields](#experience-api-context-fields).
+- The exception-specific fields below.
```tsx
enum SignInIdentifier {
@@ -228,16 +382,7 @@ enum SignInIdentifier {
}
```
-| Field | Type | Optional | Notes |
-| ---------------- | ------------------- | -------- | ------------------------------------------------------------------ |
-| hookId | `string` | | The identifier in Logto. |
-| event | `string` | | Which event that triggers this hook. |
-| createdAt | `string` | | The create time of payload in ISO format. |
-| userAgent | `string` | ✅ | The user-agent for the request. |
-| ip | `string` | ✅ | The IP address for the request. |
-| interactionEvent | `string` | ✅ | The interaction event that triggers this hook. |
-| sessionId | `string` | ✅ | The Session ID (not Interaction ID) for this event, if applicable. |
-| applicationId | `string` | ✅ | The related Application ID for this event, if applicable. |
-| application | `ApplicationEntity` | ✅ | The related application info for this event, if applicable. |
-| type | `SignInIdentifier` | | The user's identifier type, e.g., email, phone or username. |
-| value | `string` | | The user's identifier value that triggered the lockout. |
+| Field | Type | Optional | Notes |
+| ----- | ------------------ | -------- | ----------------------------------------------------------- |
+| type | `SignInIdentifier` | | The user's identifier type, e.g., email, phone or username. |
+| value | `string` | | The user's identifier value that triggered the lockout. |
diff --git a/i18n/de/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx b/i18n/de/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx
index 3d77af6b78c..ccb4b658131 100644
--- a/i18n/de/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx
+++ b/i18n/de/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx
@@ -7,26 +7,26 @@ sidebar_position: 3
# Webhooks-Ereignisse
-Dieser Leitfaden listet die verschiedenen Logto Webhook-Ereignisse auf und erklärt, wann jedes Ereignis auftritt.
+Dieser Leitfaden listet die verschiedenen Logto-Webhooks-Ereignisse auf und erklärt, wann jedes Ereignis auftritt.
## Benutzerinteraktions-Hook-Ereignisse \{#user-interaction-hook-events}
-| Ereignistyp | Beschreibung |
-| ----------------- | ------------------------------------------------------------------------------------------------- |
-| PostRegister | Ein Benutzer erstellt erfolgreich ein neues Konto über die UI-Oberfläche. |
-| PostSignIn | Ein Benutzer meldet sich erfolgreich über die UI-Oberfläche an. |
-| PostResetPassword | Das Passwort eines Benutzers wird erfolgreich über den „Passwort vergessen“-Ablauf zurückgesetzt. |
+| Ereignistyp | Beschreibung |
+| ----------------- | ------------------------------------------------------------------------------------------------ |
+| PostRegister | Ein Benutzer erstellt erfolgreich ein neues Konto über die UI-Oberfläche. |
+| PostSignIn | Ein Benutzer meldet sich erfolgreich über die UI-Oberfläche an. |
+| PostResetPassword | Das Passwort eines Benutzers wird erfolgreich über den "Passwort vergessen"-Fluss zurückgesetzt. |
## Datenmutations-Hook-Ereignisse \{#data-mutation-hook-events}
### Benutzer \{#user}
-| Ereignistyp | Beschreibung |
-| ----------------------------- | -------------------------------------------------------------------------------------------- |
-| User.Created | Ein neues Benutzerkonto wird erstellt. |
-| User.Deleted | Ein Benutzerkonto wird gelöscht. |
-| User.Data.Updated | Benutzerdaten werden aktualisiert, z. B. E-Mail, Avatar, custom.data, Social-Identifier usw. |
-| User.SuspensionStatus.Updated | Der Sperrstatus eines Benutzers wird geändert (gesperrt oder reaktiviert). |
+| Ereignistyp | Beschreibung |
+| ----------------------------- | ------------------------------------------------------------------------------------------ |
+| User.Created | Ein neues Benutzerkonto wird erstellt. |
+| User.Deleted | Ein Benutzerkonto wird gelöscht. |
+| User.Data.Updated | Benutzerdaten werden aktualisiert, z. B. E-Mail, Avatar, custom.data, soziale Kennung usw. |
+| User.SuspensionStatus.Updated | Der Sperrstatus eines Benutzers wird geändert (gesperrt oder reaktiviert). |
### Rolle \{#role}
@@ -37,39 +37,39 @@ Dieser Leitfaden listet die verschiedenen Logto Webhook-Ereignisse auf und erkl
| Role.Data.Updated | Die Daten einer Rolle werden aktualisiert, z. B. Rollenname, Beschreibung und Standardrollenstatus. |
| Role.Scopes.Updated | Berechtigungen, die einer Rolle zugewiesen sind, werden hinzugefügt oder entfernt. |
-### Berechtigung (Berechtigung) \{#permission-scope}
+### Berechtigung (Scope) \{#permission-scope}
-| Ereignistyp | Beschreibung |
-| ------------------ | ------------------------------------------------------------------------- |
-| Scope.Created | Eine neue API-Berechtigung wird erstellt. |
-| Scope.Deleted | Eine API-Berechtigung wird gelöscht. |
-| Scope.Data.Updated | Die Daten einer API-Berechtigung werden aktualisiert, z. B. Beschreibung. |
+| Ereignistyp | Beschreibung |
+| ------------------ | -------------------------------------------------------------------------------------- |
+| Scope.Created | Eine neue API-Berechtigung wird erstellt. |
+| Scope.Deleted | Eine API-Berechtigung wird gelöscht. |
+| Scope.Data.Updated | Die Daten einer API-Berechtigung werden aktualisiert, z. B. Berechtigungsbeschreibung. |
### Organisation \{#organization}
-| Ereignistyp | Beschreibung |
-| ------------------------------- | -------------------------------------------------------------------------------------------- |
-| Organization.Created | Eine neue Organisation wird erstellt. |
-| Organization.Deleted | Eine Organisation wird gelöscht. |
-| Organization.Data.Updated | Die Daten einer Organisation werden aktualisiert, z. B. Name, Beschreibung, custom.data usw. |
-| Organization.Membership.Updated | Mitglieder werden zu einer Organisation hinzugefügt oder entfernt. |
+| Ereignistyp | Beschreibung |
+| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Organization.Created | Eine neue Organisation wird erstellt. |
+| Organization.Deleted | Eine Organisation wird gelöscht. |
+| Organization.Data.Updated | Die Daten einer Organisation werden aktualisiert, z. B. Organisationsname, Beschreibung, custom.data usw. |
+| Organization.Membership.Updated | Benutzer oder Anwendungen werden zu einer Organisation hinzugefügt oder daraus entfernt. Die Nutzlast enthält [Mitgliedschaftsdelta-Felder](/developers/webhooks/webhooks-request#organizationmembershipupdated-payload). |
### Organisationsrolle \{#organization-role}
-| Ereignistyp | Beschreibung |
-| ------------------------------- | ----------------------------------------------------------------------------------------------------------- |
-| OrganizationRole.Created | Eine neue Organisationsrolle wird erstellt. |
-| OrganizationRole.Deleted | Eine Organisationsrolle wird gelöscht. |
-| OrganizationRole.Data.Updated | Die Daten einer Organisationsrolle werden aktualisiert, z. B. Name und Beschreibung der Organisationsrolle. |
-| OrganizationRole.Scopes.Updated | Berechtigungen, die einer Organisationsrolle zugewiesen sind, werden hinzugefügt oder entfernt. |
+| Ereignistyp | Beschreibung |
+| ------------------------------- | ------------------------------------------------------------------------------------------------------- |
+| OrganizationRole.Created | Eine neue Organisationsrolle wird erstellt. |
+| OrganizationRole.Deleted | Eine Organisationsrolle wird gelöscht. |
+| OrganizationRole.Data.Updated | Die Daten einer Organisationsrolle werden aktualisiert, z. B. Organisationsrollenname und Beschreibung. |
+| OrganizationRole.Scopes.Updated | Berechtigungen, die einer Organisationsrolle zugewiesen sind, werden hinzugefügt oder entfernt. |
-### Organisationsberechtigung (Berechtigung) \{#organization-permission-scope}
+### Organisationsberechtigung (Scope) \{#organization-permission-scope}
-| Ereignistyp | Beschreibung |
-| ------------------------------ | ---------------------------------------------------------------------------------------------------------------- |
-| OrganizationScope.Created | Eine neue Organisationsberechtigung wird erstellt. |
-| OrganizationScope.Deleted | Eine Organisationsberechtigung wird gelöscht. |
-| OrganizationScope.Data.Updated | Die Daten einer Organisationsberechtigung werden aktualisiert, z. B. Beschreibung der Organisationsberechtigung. |
+| Ereignistyp | Beschreibung |
+| ------------------------------ | ------------------------------------------------------------------------------------------------------------ |
+| OrganizationScope.Created | Eine neue Organisationsberechtigung wird erstellt. |
+| OrganizationScope.Deleted | Eine Organisationsberechtigung wird gelöscht. |
+| OrganizationScope.Data.Updated | Die Daten einer Organisationsberechtigung werden aktualisiert, z. B. Organisationsberechtigungsbeschreibung. |
### Management API ausgelöste Ereignisse \{#management-api-triggered-events}
@@ -96,6 +96,10 @@ Dieser Leitfaden listet die verschiedenen Logto Webhook-Ereignisse auf und erkl
| PUT /organizations/:id/users | Organization.Membership.Updated |
| POST /organizations/:id/users | Organization.Membership.Updated |
| DELETE /organizations/:id/users/:userId | Organization.Membership.Updated |
+| PUT /organizations/:id/applications | Organization.Membership.Updated |
+| POST /organizations/:id/applications | Organization.Membership.Updated |
+| DELETE /organizations/:id/applications/:applicationId | Organization.Membership.Updated |
+| PUT /organization-invitations/:id/status (Accepted) | Organization.Membership.Updated |
| POST /organization-roles | OrganizationRole.Created, (OrganizationRole.Scopes.Updated) |
| DELETE /organization-roles/:id | OrganizationRole.Deleted |
| PATCH /organization-roles/:id | OrganizationRole.Data.Updated |
@@ -108,21 +112,22 @@ Dieser Leitfaden listet die verschiedenen Logto Webhook-Ereignisse auf und erkl
### Experience API ausgelöste Ereignisse \{#experience-api-triggered-events}
-| Benutzerinteraktionsaktion | Ereignis |
-| ----------------------------------- | ----------------- |
-| Benutzer E-Mail/Telefon-Verknüpfung | User.Data.Updated |
-| Benutzer MFA-Verknüpfung | User.Data.Updated |
-| Benutzer Social/SSO-Verknüpfung | User.Data.Updated |
-| Benutzer Passwort zurücksetzen | User.Data.Updated |
-| Benutzerregistrierung | User.Created |
+| Benutzerinteraktionsaktion | Ereignis |
+| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- |
+| Benutzer-E-Mail/Telefon-Verknüpfung | User.Data.Updated |
+| Benutzer-MFAs-Verknüpfung | User.Data.Updated |
+| Benutzer-Soziale/SSO-Verknüpfung | User.Data.Updated |
+| Benutzer-Passwort-Zurücksetzung | User.Data.Updated |
+| Benutzerregistrierung | User.Created |
+| Benutzer automatisch in eine Organisation bereitgestellt über [Just-in-Time-Bereitstellung](/organizations/just-in-time-provisioning) (übereinstimmende E-Mail-Domain oder Enterprise SSO Connector) | Organization.Membership.Updated |
## Ausnahme-Hook-Ereignisse \{#exception-hook-events}
### Sicherheit \{#security}
-| Ereignistyp | Beschreibung |
-| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
-| Identifier.Lockout | Ein Benutzerkonto wird aufgrund aufeinanderfolgender fehlgeschlagener Identitätsüberprüfungsversuche gesperrt. Kann in folgenden Abläufen ausgelöst werden:
- Passwortüberprüfung fehlgeschlagen
- Codeüberprüfung fehlgeschlagen
- Einmal-Token-Überprüfung fehlgeschlagen
|
+| Ereignistyp | Beschreibung |
+| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Identifier.Lockout | Ein Benutzerkonto wird aufgrund aufeinanderfolgender fehlgeschlagener Identitätsüberprüfungsversuche gesperrt. Kann in den folgenden Flüssen ausgelöst werden:
- Passwortüberprüfung fehlgeschlagen
- Codeüberprüfung fehlgeschlagen
- Einmal-Token-Überprüfung fehlgeschlagen
|
## FAQs \{#faqs}
@@ -133,6 +138,6 @@ Dieser Leitfaden listet die verschiedenen Logto Webhook-Ereignisse auf und erkl
-`PostRegister` wird ausgelöst, wenn ein Benutzer erfolgreich ein neues Konto über den Benutzerregistrierungsablauf erstellt; `User.Created` wird ausgelöst, wenn ein neues Benutzerkonto über die Management API erstellt wird.
+`PostRegister` wird ausgelöst, wenn ein Benutzer erfolgreich ein neues Konto über den Benutzeranmeldefluss erstellt; `User.Created` wird ausgelöst, wenn ein neues Benutzerkonto über die Management API erstellt wird.
diff --git a/i18n/de/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx b/i18n/de/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx
index 2fb794fcc0b..c08a2950aa7 100644
--- a/i18n/de/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx
+++ b/i18n/de/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx
@@ -7,23 +7,60 @@ sidebar_position: 4
# Webhooks-Anfrage
-Sobald ein gültiges Hook-Ereignis ausgelöst wird, sucht Logto die entsprechenden Webhooks und sendet pro Hook-Konfiguration eine POST-Anfrage.
+Wenn ein Webhook-Ereignis ausgelöst wird, sendet Logto eine `POST`-Anfrage an jeden abonnierten Endpunkt. Der vollständige Ereigniskatalog befindet sich unter [Webhooks-Ereignisse](/developers/webhooks/webhooks-events); diese Seite dokumentiert die **Struktur der Anfrage**, die Logto liefert.
## Anfrage-Header \{#request-headers}
-| Key | Anpassbar | Hinweise |
-| ----------------------- | --------- | ------------------------------------------------------------------------------------------------- |
-| user-agent | ✅ | Standardmäßig `Logto (https://logto.io/)`. |
-| content-type | ✅ | Standardmäßig `application/json`. |
-| logto-signature-sha-256 | | Die Signatur des Anfrage-Bodys, siehe [Webhooks absichern](/developers/webhooks/secure-webhooks). |
+| Key | Anpassbar | Hinweise |
+| ----------------------- | --------- | ---------------------------------------------------------------------------------------------------- |
+| user-agent | ✅ | Standardmäßig `Logto (https://logto.io/)`. |
+| content-type | ✅ | Standardmäßig `application/json`. |
+| logto-signature-sha-256 | | Signatur des Anfragetextes. Siehe [Sicherung deiner Webhooks](/developers/webhooks/secure-webhooks). |
-Du kannst anpassbare Header überschreiben, indem du [Anfrage-Header anpasst](/developers/webhooks/configure-webhooks/#secure-webhook) mit dem gleichen Schlüssel.
+Anpassbare Header können über die [sichere Webhook](/developers/webhooks/configure-webhooks/#secure-webhook)-Konfiguration überschrieben werden.
-## Interaction-Hook-Events Anfrage-Body \{#interaction-hook-events-request-body}
+## Überblick über den Anfragetext \{#request-body-overview}
-Verfügbare Ereignisse: `PostRegister`, `PostSignIn`, `PostResetPassword`
+Der Text ist ein JSON-Objekt. Seine genaue Struktur hängt davon ab, zu welcher Familie das Ereignis gehört:
-Der Anfrage-Body ist ein JSON-Objekt, das drei Arten von Datenfeldern enthält:
+| Familie | Ereignisse | Wann es ausgelöst wird |
+| ----------------- | -------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
+| **Benutzerfluss** | `PostRegister`, `PostSignIn`, `PostResetPassword` | Ein Benutzer schließt einen Anmelde-, Anmelde- oder Passwortzurücksetzungsfluss ab, der von der Experience API behandelt wird. |
+| **Datenmutation** | `User.*`, `Role.*`, `Scope.*`, `Organization.*`, `OrganizationRole.*`, `OrganizationScope.*` | Das zugrunde liegende Datenmodell wird verändert — durch einen Management API-Aufruf oder durch einen Benutzerfluss in der Experience API. |
+| **Ausnahme** | `Identifier.Lockout` | Ein Sicherheitsvorfall — zum Beispiel ein Konto, das nach aufeinanderfolgenden fehlgeschlagenen Verifizierungsversuchen gesperrt wurde. |
+
+Jede Familie teilt einen kleinen Satz von [gemeinsamen Feldern](#common-fields). Jede Familie fügt dann ihre eigenen Anfragekontextfelder sowie eine ereignisspezifische Nutzlast hinzu.
+
+### Gemeinsame Felder \{#common-fields}
+
+In jeder Lieferung unabhängig von der Familie vorhanden:
+
+| Feld | Typ | Optional | Anmerkungen |
+| --------- | -------- | -------- | ---------------------------------------------------- |
+| hookId | `string` | | Die Webhook-Konfigurationskennung in Logto. |
+| event | `string` | | Das Ereignis, das diese Lieferung ausgelöst hat. |
+| createdAt | `string` | | Die Erstellungszeit der Nutzlast im ISO 8601-Format. |
+| userAgent | `string` | ✅ | Der User-Agent der auslösenden Anfrage. |
+
+Jede Familie enthält auch die IP-Adresse der auslösenden Anfrage — unter dem Feldnamen `userIp` für Benutzerflussereignisse und `ip` für Datenmutations- und Ausnahmeereignisse. Die Semantik ist identisch; der historische Namensunterschied wird aus Gründen der Rückwärtskompatibilität beibehalten.
+
+## Nutzlasten von Benutzerflussereignissen \{#user-flow-event-payloads}
+
+**Ereignisse:** `PostRegister`, `PostSignIn`, `PostResetPassword`.
+
+Ausgelöst, wenn ein Benutzer einen Anmelde-, Anmelde- oder Passwortzurücksetzungsfluss abschließt, der von der Experience API behandelt wird. Zusätzlich zu den [gemeinsamen Feldern](#common-fields) enthält der Text:
+
+| Feld | Typ | Optional | Anmerkungen |
+| ---------------- | -------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| interactionEvent | `'SignIn' \| 'Register' \| 'ForgotPassword'` | | Der Benutzerfluss-Ereignistyp. Entspricht `PostSignIn` / `PostRegister` / `PostResetPassword`. Der Feldname behält die historische "Interaktions"-Benennung bei. |
+| sessionId | `string` | ✅ | Die Sitzungs-ID (nicht Interaktions-ID) für dieses Ereignis, falls zutreffend. |
+| userIp | `string` | ✅ | Die IP-Adresse der auslösenden Anfrage. |
+| userId | `string` | ✅ | Die Benutzer-ID, die mit diesem Ereignis verknüpft ist, falls zutreffend. |
+| user | `UserEntity` | ✅ | Die Benutzerentität, die mit diesem Ereignis verknüpft ist, falls zutreffend. |
+| applicationId | `string` | ✅ | Die Anwendungs-ID, die mit diesem Ereignis verknüpft ist, falls zutreffend. |
+| application | `ApplicationEntity` | ✅ | Die Anwendungsentität, die mit diesem Ereignis verknüpft ist, falls zutreffend. |
+
+#### Entitätsstrukturen \{#user-flow-entity-shapes}
```tsx
type UserEntity = {
@@ -60,70 +97,57 @@ type ApplicationEntity = {
};
```
-| Feld | Typ | Optional | Hinweise |
-| ---------------- | ------------------- | -------- | ------------------------------------------------------------------------------ |
-| hookId | `string` | | Die Kennung in Logto. |
-| event | `string` | | Das Ereignis, das diesen Hook auslöst. |
-| createdAt | `string` | | Das Erstellungsdatum der Nutzlast im ISO-Format. |
-| interactionEvent | `string` | | Das Interaktionsereignis, das diesen Hook auslöst. |
-| sessionId | `string` | ✅ | Die Session-ID (nicht Interaction-ID) für dieses Ereignis, falls zutreffend. |
-| userAgent | `string` | ✅ | Der User-Agent für die Anfrage, die diesen Hook auslöst. |
-| userIp | `string` | ✅ | Die IP-Adresse für die Anfrage, die diesen Hook auslöst. |
-| userId | `string` | ✅ | Die zugehörige Benutzer-ID für dieses Ereignis, falls zutreffend. |
-| user | `UserEntity` | ✅ | Die zugehörige Benutzer-Entität für dieses Ereignis, falls zutreffend. |
-| applicationId | `string` | ✅ | Die zugehörige Anwendungs-ID für dieses Ereignis, falls zutreffend. |
-| application | `ApplicationEntity` | ✅ | Die zugehörigen Anwendungsinformationen für dieses Ereignis, falls zutreffend. |
+Siehe [Benutzer](/user-management/user-data) und [Anwendungen](/integrate-logto/application-data-structure) für die vollständige Feldreferenz.
-Siehe [Benutzer](/user-management/user-data) und [Anwendungen](/integrate-logto/application-data-structure) für detaillierte Feldbeschreibungen.
+## Nutzlasten von Datenmutationsereignissen \{#data-mutation-event-payloads}
-## Datenmutations-Hook-Events Anfrage-Body \{#data-mutation-hook-events-request-body}
+**Ereignisse:** jedes Ereignis unter `User.*`, `Role.*`, `Scope.*`, `Organization.*`, `OrganizationRole.*`, `OrganizationScope.*` — siehe [Webhooks-Ereignisse → Datenmutations-Hook-Ereignisse](/developers/webhooks/webhooks-events#data-mutation-hook-events) für den vollständigen Katalog.
-### Standard-Anfrage-Body-Felder \{#standard-request-body-fields}
+Der Text enthält immer:
-| Feld | Typ | Optional | Hinweise |
-| --------- | -------- | -------- | ------------------------------------------------ |
-| hookId | `string` | | Die Kennung in Logto. |
-| event | `string` | | Das Ereignis, das diesen Hook auslöst. |
-| createdAt | `string` | | Das Erstellungsdatum der Nutzlast im ISO-Format. |
-| userAgent | `string` | ✅ | Der User-Agent für die Anfrage. |
-| ip | `string` | ✅ | Die IP-Adresse für die Anfrage. |
+- Die [gemeinsamen Felder](#common-fields).
+- Ein `ip`-Feld — die IP-Adresse der auslösenden Anfrage (optional, vorhanden, wenn bekannt).
+- Einen **API-Kontext**, der beschreibt, wie die Änderung ausgelöst wurde. Der Kontext ist eine von zwei Varianten, abhängig von der Auslöserquelle:
+ - [Experience API-Kontext](#experience-api-context-fields) — wenn die Änderung aus einem benutzerorientierten Fluss stammt.
+ - [Management API-Kontext](#management-api-context-fields) — wenn die Änderung aus einem direkten Management API-Aufruf stammt.
+- Eine **ereignisspezifische Nutzlast** — die betroffene Entität in `data` und (für einige Ereignisse) zusätzliche Felder auf oberster Ebene. Siehe [ereignisspezifische Daten-Nutzlasten](#event-specific-data-payloads).
-### Interaction-API-Kontext-Body-Felder \{#interaction-api-context-body-fields}
+### Experience API-Kontextfelder \{#experience-api-context-fields}
-Datenmutations-Hook-Events, die durch Benutzer-Interaktions-API-Aufrufe ausgelöst werden.
+Vorhanden, wenn die Änderung durch einen benutzerorientierten Fluss in der Experience API ausgelöst wurde — zum Beispiel `User.Created` während der Anmeldung oder `User.Data.Updated` während der Profilaktualisierungen.
-Verfügbare Ereignisse: `User.Created`, `User.Data.Updated`
+| Feld | Typ | Optional | Anmerkungen |
+| ---------------- | -------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------- |
+| interactionEvent | `'SignIn' \| 'Register' \| 'ForgotPassword'` | ✅ | Der Benutzerfluss-Ereignistyp, der die Änderung hervorgebracht hat. Der Feldname behält die historische "Interaktions"-Benennung bei. |
+| sessionId | `string` | ✅ | Die Sitzungs-ID (nicht Interaktions-ID) für dieses Ereignis, falls zutreffend. |
+| applicationId | `string` | ✅ | Die Anwendungs-ID, falls zutreffend. |
+| application | `ApplicationEntity` | ✅ | Die Anwendungsentität, falls zutreffend. |
-| Feld | Typ | Optional | Hinweise |
-| ---------------- | ------------------- | -------- | ------------------------------------------------------------------------------ |
-| interactionEvent | `string` | ✅ | Das Interaktionsereignis, das diesen Hook auslöst. |
-| sessionId | `string` | ✅ | Die Session-ID (nicht Interaction-ID) für dieses Ereignis, falls zutreffend. |
-| applicationId | `string` | ✅ | Die zugehörige Anwendungs-ID für dieses Ereignis, falls zutreffend. |
-| application | `ApplicationEntity` | ✅ | Die zugehörigen Anwendungsinformationen für dieses Ereignis, falls zutreffend. |
+### Management API-Kontextfelder \{#management-api-context-fields}
-### Management-API-Kontext-Body-Felder \{#management-api-context-body-fields}
+Vorhanden, wenn die Änderung durch einen Management API-Aufruf ausgelöst wurde.
-Datenmutations-Hook-Events, die durch Management API-Aufrufe ausgelöst werden.
+| Feld | Typ | Optional | Anmerkungen |
+| ------------ | -------- | -------- | --------------------------------------------------------------------------------------------------------------- |
+| path | `string` | ✅ | Der Pfad des API-Aufrufs, der diesen Hook ausgelöst hat. |
+| method | `string` | ✅ | Die HTTP-Methode des API-Aufrufs. |
+| status | `number` | ✅ | Der Antwortstatuscode des API-Aufrufs. |
+| params | `object` | ✅ | Die koa-Pfadparameter des API-Aufrufs. |
+| matchedRoute | `string` | ✅ | Die koa-übereinstimmende Route. Logto verwendet dieses Feld, um aktivierte Webhook-Ereignisfilter abzugleichen. |
-| Feld | Typ | Optional | Hinweise |
-| ------------ | -------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------- |
-| path | `string` | ✅ | Der Pfad des API-Aufrufs, der diesen Hook auslöst. |
-| method | `string` | ✅ | Die Methode des API-Aufrufs, der diesen Hook auslöst. |
-| status | `number` | ✅ | Der Antwort-Statuscode des API-Aufrufs, der diesen Hook auslöst. |
-| params | `object` | ✅ | Die Koa-Pfad-Parameter des API-Aufrufs, der diesen Hook auslöst. |
-| matchedRoute | `string` | ✅ | Die Koa-Matched-Route des API-Aufrufs, der diesen Hook auslöst. Logto verwendet dieses Feld, um die aktivierten Hook-Events zuzuordnen. |
+### Ereignisspezifische Daten-Nutzlasten \{#event-specific-data-payloads}
-### Daten-Payload-Body-Felder \{#data-payload-body-fields}
+Jedes Datenmutationsereignis enthält ein oberstes `data`-Feld, das die betroffene Entität trägt, oder `null`, wenn die Änderung nicht als einzelne Entität zusammengefasst werden kann (Lösch- und Mitgliedschaftsereignisse). Einige Ereignisse enthalten auch ereignisspezifische Felder auf oberster Ebene über `data` hinaus — `Organization.Membership.Updated` ist ein solcher Fall, der unten dokumentiert ist.
-**Benutzer-Ereignisse**
+#### Benutzerereignisse \{#user-events}
-| Ereignis | Feld | Typ | Optional | Hinweise |
-| ----------------- | ---- | ---------- | -------- | ------------------------------------------------------- |
-| User.Created | data | UserEntity | | Die erstellte Benutzer-Entität für dieses Ereignis. |
-| User.Data.Updated | data | UserEntity | | Die aktualisierte Benutzer-Entität für dieses Ereignis. |
-| User.Deleted | data | null | / | |
+| Ereignis | Feld | Typ | Optional | Anmerkungen |
+| ----------------- | ---- | ------------ | -------- | ---------------------------------- |
+| User.Created | data | `UserEntity` | | Die erstellte Benutzerentität. |
+| User.Data.Updated | data | `UserEntity` | | Die aktualisierte Benutzerentität. |
+| User.Deleted | data | `null` | / | |
-**Rollen-Ereignisse**
+#### Rollenereignisse \{#role-events}
```tsx
type Role = {
@@ -145,23 +169,23 @@ type Scope = {
};
```
-| Ereignis | Feld | Typ | Optional | Hinweise |
-| ------------------ | ------ | ------------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| Role.Created | data | Rolle (Role) | | Die erstellte Rollen-Entität für dieses Ereignis. |
-| Role.Data.Updated | data | Rolle (Role) | | Die aktualisierte Rollen-Entität für dieses Ereignis. |
-| Role.Deleted | data | null | | |
-| Role.Scope.Updated | data | Scope[] | | Die aktualisierten Berechtigungen (Scopes), die der Rolle zugewiesen sind. |
-| Role.Scope.Updated | roleId | string | ✅ | Die Rollen-ID, der Berechtigungen zugewiesen sind. (Nur verfügbar, wenn das Ereignis durch das Erstellen einer neuen Rolle mit vorab zugewiesenen Berechtigungen ausgelöst wurde) |
+| Ereignis | Feld | Typ | Optional | Anmerkungen |
+| ------------------- | ------ | --------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Role.Created | data | `Role` | | Die erstellte Rollenentität. |
+| Role.Data.Updated | data | `Role` | | Die aktualisierte Rollenentität. |
+| Role.Deleted | data | `null` | / | |
+| Role.Scopes.Updated | data | `Scope[]` | | Die aktualisierten Berechtigungen, die der Rolle zugewiesen sind. |
+| Role.Scopes.Updated | roleId | `string` | ✅ | Die Rollen-ID, der Berechtigungen zugewiesen sind. (Nur verfügbar, wenn das Ereignis durch das Erstellen einer Rolle mit vorab zugewiesenen Berechtigungen ausgelöst wurde.) |
-**Berechtigungs- (Scope-) Ereignisse**
+#### Berechtigung (Scope) Ereignisse \{#permission-events}
-| Ereignis | Feld | Typ | Optional | Hinweise |
-| ------------------ | ---- | ----- | -------- | ------------------------------------------------------------ |
-| Scope.Created | data | Scope | | Die erstellte Berechtigungs-Entität für dieses Ereignis. |
-| Scope.Data.Updated | data | Scope | | Die aktualisierte Berechtigungs-Entität für dieses Ereignis. |
-| Scope.Deleted | data | null | / | |
+| Ereignis | Feld | Typ | Optional | Anmerkungen |
+| ------------------ | ---- | ------- | -------- | --------------------------------------- |
+| Scope.Created | data | `Scope` | | Die erstellte Berechtigungsentität. |
+| Scope.Data.Updated | data | `Scope` | | Die aktualisierte Berechtigungsentität. |
+| Scope.Deleted | data | `null` | / | |
-**Organisations-Ereignisse**
+#### Organisationsevents \{#organization-events}
```tsx
type Organization = {
@@ -173,14 +197,145 @@ type Organization = {
};
```
-| Ereignis | Feld | Typ | Optional | Hinweise |
-| ------------------------------- | ---- | --------------------------- | -------- | ------------------------------------------------------------ |
-| Organization.Created | data | Organisation (Organization) | | Die erstellte Organisations-Entität für dieses Ereignis. |
-| Organization.Data.Updated | data | Organisation (Organization) | | Die aktualisierte Organisations-Entität für dieses Ereignis. |
-| Organization.Deleted | data | null | / | |
-| Organization.Membership.Updated | data | null | / | |
+| Ereignis | Feld | Typ | Optional | Anmerkungen |
+| ------------------------------- | ---- | -------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| Organization.Created | data | `Organization` | | Die erstellte Organisationsentität. |
+| Organization.Data.Updated | data | `Organization` | | Die aktualisierte Organisationsentität. |
+| Organization.Deleted | data | `null` | / | |
+| Organization.Membership.Updated | data | `null` | / | Die Änderung wird durch optionale Delta-Arrays auf oberster Ebene beschrieben. Siehe [Organization.Membership.Updated Nutzlast](#organizationmembershipupdated-payload) unten. |
+
+##### Organization.Membership.Updated Nutzlast \{#organizationmembershipupdated-payload}
+
+Zusätzlich zu den [gemeinsamen Feldern](#common-fields) und den API-Kontextfeldern, die für die Triggerquelle gelten ([Management API-Kontext](#management-api-context-fields) für Management API-Routen, [Experience API-Kontext](#experience-api-context-fields) für die Just-in-Time-Bereitstellung), trägt das `Organization.Membership.Updated`-Ereignis eine `organizationId` sowie optionale Delta-Arrays auf oberster Ebene der Nutzlast (neben `event`, `createdAt` usw.; **nicht** innerhalb von `data`, das für dieses Ereignis immer `null` ist).
+
+| Feld | Typ | Optional | Anmerkungen |
+| --------------------- | ---------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| organizationId | `string` | | Die Organisation, deren Mitgliedschaft sich geändert hat. |
+| addedUserIds | `string[]` | ✅ | Benutzer-IDs, die durch diesen Auslöser neu hinzugefügt wurden. Weggelassen, wenn keine Benutzer hinzugefügt wurden oder wenn der Auslöser die Benutzerzugehörigkeit nicht beeinflusst. |
+| removedUserIds | `string[]` | ✅ | Benutzer-IDs, die durch diesen Auslöser entfernt wurden. Weggelassen, wenn keine Benutzer entfernt wurden. |
+| addedApplicationIds | `string[]` | ✅ | Anwendungs-IDs, die neu hinzugefügt wurden. Weggelassen, wenn keine Anwendungen hinzugefügt wurden oder wenn der Auslöser die Anwendungszugehörigkeit nicht beeinflusst. |
+| removedApplicationIds | `string[]` | ✅ | Anwendungs-IDs, die entfernt wurden. Weggelassen, wenn keine Anwendungen entfernt wurden. |
+
+Die vier Delta-Arrays sind **optional und additiv** — sie ändern nicht die bestehende Nutzlaststruktur für Verbraucher, die sie nicht erwarten, und das Legacy-Feld `data: null` wird weiterhin unverändert ausgegeben.
+
+###### Auslöser und welche Delta-Felder sie möglicherweise ausgeben \{#membership-triggers}
+
+| Auslöser | Mögliche Delta-Felder |
+| ------------------------------------------------------------------------------------- | ---------------------------------------------- |
+| `POST /organizations/:id/users` | `addedUserIds` |
+| `PUT /organizations/:id/users` | `addedUserIds`, `removedUserIds` |
+| `DELETE /organizations/:id/users/:userId` | `removedUserIds` |
+| `POST /organizations/:id/applications` | `addedApplicationIds` |
+| `PUT /organizations/:id/applications` | `addedApplicationIds`, `removedApplicationIds` |
+| `DELETE /organizations/:id/applications/:applicationId` | `removedApplicationIds` |
+| `PUT /organization-invitations/:id/status` (`Accepted`) | `addedUserIds` |
+| Just-in-time Bereitstellung beim Hinzufügen des Benutzers zu einer neuen Organisation | `addedUserIds` |
+
+Hinweis: Die Just-in-Time-Bereitstellung löst `Organization.Membership.Updated` nicht für eine Organisation aus, in der der Benutzer bereits Mitglied ist.
+
+Hinweis: Die Just-in-Time-Bereitstellung löst `Organization.Membership.Updated` nicht für eine Organisation aus, in der der Benutzer bereits Mitglied ist.
+
+Hinweis: Die Just-in-Time-Bereitstellung löst `Organization.Membership.Updated` nicht für eine Organisation aus, in der der Benutzer bereits Mitglied ist.
+
+###### Leere Deltas werden weggelassen — abwesend ≠ leere Änderung \{#empty-deltas-are-omitted}
+
+Leere Delta-Arrays werden **vollständig weggelassen** aus der Nutzlast. Zum Beispiel, ein `PUT /organizations/:id/users`, das die Mitgliedschaftsmenge mit der bestehenden Menge ersetzt, erzeugt keine wirkliche Änderung, und die Nutzlast reduziert sich auf nur `{ organizationId }` mit allen vier Delta-Feldern abwesend. Dasselbe gilt für das erneute Hinzufügen eines bestehenden Mitglieds, das erneute Akzeptieren einer Einladung durch einen Benutzer, der bereits Mitglied ist, der bereits Mitglied ist.
+
+**Verbraucher müssen ein fehlendes Feld als "keine Änderung auf dieser Seite" behandeln, nicht als "eine leere Änderung".**
+
+###### Pro-Array-Limit (stille Kürzung) \{#membership-delta-cap}
+
+Jedes Delta-Array ist auf **5000 Einträge** begrenzt. Wenn ein einzelner Management API-Aufruf mehr als 5000 Benutzer (oder Anwendungen) in einem Vorgang hinzufügt oder entfernt, wird das entsprechende Delta-Array stillschweigend auf seine ersten 5000 Einträge gekürzt — **es gibt keinen Marker in der Nutzlast**, dass ein Limit ausgelöst wurde.
+
+Wenn deine Anwendung administrative Massenoperationen durchführt, die plausibel mehr als 5000 Mitglieder in einem Aufruf betreffen können, behandle ein Array von genau 5000 Einträgen als Signal, um die autoritative Mitgliedschaft über die Management API abzugleichen:
+
+- `GET /organizations/:id/users` — vollständige Benutzerzugehörigkeit.
+- `GET /organizations/:id/applications` — vollständige Anwendungszugehörigkeit.
+
+Dies folgt demselben Muster wie das `push`-Ereignis von GitHub, das `commits` auf 20 Einträge begrenzt und Verbraucher auf die Vergleichs-API für die vollständige Liste verweist.
+
+###### Überspringen von No-Op-Ereignissen \{#skipping-no-op-events}
+
+Jeder `PUT` gegen die Mitgliedschaftsrouten gibt ein Ereignis aus, unabhängig davon, ob sich tatsächlich etwas geändert hat — damit jeder zustandsersetzende Aufruf mindestens eine Webhook-Lieferung zu Prüfzwecken hat. Um No-Op-Lieferungen auf der Verbraucherseite zu überspringen, filtere nach Delta-Array-Präsenz:
+
+```ts
+if (
+ payload.addedUserIds?.length ||
+ payload.removedUserIds?.length ||
+ payload.addedApplicationIds?.length ||
+ payload.removedApplicationIds?.length
+) {
+ // echte Mitgliedschaftsänderung — bearbeite sie
+}
+```
+
+`?.length` ist sowohl für `undefined` als auch für `[]` falsch, sodass dasselbe Prädikat robust ist, unabhängig davon, ob das Feld fehlt oder (in einer hypothetischen Zukunft) als leeres Array ausgegeben wird.
+
+###### Beispiel-Nutzlasten \{#membership-example-payloads}
+
+**Einen Benutzer hinzufügen (`POST /organizations/:id/users`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "addedUserIds": ["u_001"]
+}
+```
+
+**Die Benutzerzugehörigkeitsmenge ersetzen (`PUT /organizations/:id/users`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "addedUserIds": ["u_002"],
+ "removedUserIds": ["u_001"]
+}
+```
+
+**Einen Benutzer entfernen (`DELETE /organizations/:id/users/:userId`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "removedUserIds": ["u_001"]
+}
+```
+
+**Eine Anwendung hinzufügen (`POST /organizations/:id/applications`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "addedApplicationIds": ["app_xyz"]
+}
+```
+
+**Ein bestehendes Mitglied erneut hinzufügen, No-Op `PUT` oder erneutes Akzeptieren einer bereits bestehenden Einladung (keine wirkliche Änderung):**
-**OrganisationRollen-Ereignisse**
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc"
+}
+```
+
+**Massenoperation, die das 5000-Limit erreicht (still gekürzt):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "removedUserIds": ["u_0001", "u_0002", "/* … genau 5000 Einträge insgesamt */"]
+}
+```
+
+Das Sehen eines Arrays von genau 5000 Einträgen sollte einen abgleichenden `GET /organizations/:id/users` (oder `/applications`) auslösen.
+
+#### Organisationsrollenereignisse \{#organization-role-events}
```tsx
type OrganizationRole = {
@@ -198,27 +353,32 @@ type OrganizationScope = {
};
```
-| Ereignis | Feld | Typ | Optional | Hinweise |
-| ------------------------------ | ------------------ | ---------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| OrganizationRole.Created | data | OrganizationRole | | Die erstellte Organisationsrollen-Entität für dieses Ereignis. |
-| OrganizationRole.Data.Updated | data | OrganizationRole | | Die aktualisierte Organisationsrollen-Entität für dieses Ereignis. |
-| OrganizationRole.Deleted | data | null | / | |
-| OrganizationRole.Scope.Updated | data | null | / | |
-| OrganizationRole.Scope.Updated | organizationRoleId | string | ✅ | Die Rollen-ID, der Berechtigungen zugewiesen sind. (Nur verfügbar, wenn das Ereignis durch das Erstellen einer neuen Rolle mit vorab zugewiesenen Berechtigungen ausgelöst wurde) |
+| Ereignis | Feld | Typ | Optional | Anmerkungen |
+| ------------------------------- | ------------------ | ------------------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| OrganizationRole.Created | data | `OrganizationRole` | | Die erstellte Organisationsrollenentität. |
+| OrganizationRole.Data.Updated | data | `OrganizationRole` | | Die aktualisierte Organisationsrollenentität. |
+| OrganizationRole.Deleted | data | `null` | / | |
+| OrganizationRole.Scopes.Updated | data | `null` | / | |
+| OrganizationRole.Scopes.Updated | organizationRoleId | `string` | ✅ | Die Rollen-ID, der Berechtigungen zugewiesen sind. (Nur verfügbar, wenn das Ereignis durch das Erstellen einer Rolle mit vorab zugewiesenen Berechtigungen ausgelöst wurde.) |
+
+#### Organisationsberechtigung (Scope) Ereignisse \{#organization-permission-events}
-**Organisationsberechtigungs- (OrganizationScope-) Ereignisse**
+| Ereignis | Feld | Typ | Optional | Anmerkungen |
+| ------------------------------ | ---- | ------------------- | -------- | ---------------------------------------------------- |
+| OrganizationScope.Created | data | `OrganizationScope` | | Die erstellte Organisationsberechtigungsentität. |
+| OrganizationScope.Data.Updated | data | `OrganizationScope` | | Die aktualisierte Organisationsberechtigungsentität. |
+| OrganizationScope.Deleted | data | `null` | / | |
-| Ereignis | Feld | Typ | Optional | Hinweise |
-| ------------------------------ | ---- | ----------------- | -------- | ----------------------------------------------------- |
-| OrganizationScope.Created | data | OrganizationScope | | Die erstellte Organisationsberechtigungs-Entität. |
-| OrganizationScope.Data.Updated | data | OrganizationScope | | Die aktualisierte Organisationsberechtigungs-Entität. |
-| OrganizationScope.Deleted | data | null | / | |
+## Ausnahmeereignis-Nutzlasten \{#exception-event-payloads}
-## Ausnahme-Hook-Events Anfrage-Body \{#exception-hook-events-request-body}
+**Ereignisse:** `Identifier.Lockout`.
-Verfügbare Ereignisse: `Identifier.Lockout`
+Ausgelöst bei Sicherheitsvorfällen — zum Beispiel, ein Konto, das nach aufeinanderfolgenden fehlgeschlagenen Verifizierungsversuchen gesperrt wurde. Diese Ereignisse stammen immer aus einem benutzerorientierten Fluss, daher enthält der Text:
-Der Anfrage-Body ist ein JSON-Objekt, das die Standard-Anfrage-Body-Felder und zusätzliche Felder wie unten enthält:
+- Die [gemeinsamen Felder](#common-fields).
+- Das `ip`-Feld (gleiche Struktur wie bei Datenmutationsereignissen).
+- Die [Experience API-Kontextfelder](#experience-api-context-fields).
+- Die unten stehenden ausnahmespezifischen Felder.
```tsx
enum SignInIdentifier {
@@ -228,16 +388,7 @@ enum SignInIdentifier {
}
```
-| Feld | Typ | Optional | Hinweise |
-| ---------------- | ------------------- | -------- | ------------------------------------------------------------------------------ |
-| hookId | `string` | | Die Kennung in Logto. |
-| event | `string` | | Das Ereignis, das diesen Hook auslöst. |
-| createdAt | `string` | | Das Erstellungsdatum der Nutzlast im ISO-Format. |
-| userAgent | `string` | ✅ | Der User-Agent für die Anfrage. |
-| ip | `string` | ✅ | Die IP-Adresse für die Anfrage. |
-| interactionEvent | `string` | ✅ | Das Interaktionsereignis, das diesen Hook auslöst. |
-| sessionId | `string` | ✅ | Die Session-ID (nicht Interaction-ID) für dieses Ereignis, falls zutreffend. |
-| applicationId | `string` | ✅ | Die zugehörige Anwendungs-ID für dieses Ereignis, falls zutreffend. |
-| application | `ApplicationEntity` | ✅ | Die zugehörigen Anwendungsinformationen für dieses Ereignis, falls zutreffend. |
-| type | `SignInIdentifier` | | Der Identifikatortyp des Benutzers, z. B. E-Mail, Telefon oder Benutzername. |
-| value | `string` | | Der Identifikatorwert des Benutzers, der die Sperrung ausgelöst hat. |
+| Feld | Typ | Optional | Anmerkungen |
+| ----- | ------------------ | -------- | ---------------------------------------------------------------------------- |
+| type | `SignInIdentifier` | | Der Identifikatortyp des Benutzers, z. B. E-Mail, Telefon oder Benutzername. |
+| value | `string` | | Der Identifikatorwert des Benutzers, der die Sperrung ausgelöst hat. |
diff --git a/i18n/es/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx b/i18n/es/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx
index eda14ecbaba..d44feb0ac3f 100644
--- a/i18n/es/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx
+++ b/i18n/es/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx
@@ -9,13 +9,13 @@ sidebar_position: 3
Esta guía enumera los diferentes eventos de webhook de Logto y explica cuándo ocurre cada evento.
-## Eventos de hook de interacción de usuario \{#user-interaction-hook-events}
+## Eventos de hook de interacción del usuario \{#user-interaction-hook-events}
-| Tipo de evento | Descripción |
-| ----------------- | --------------------------------------------------------------------------------------------------- |
-| PostRegister | Un usuario crea exitosamente una nueva cuenta a través de la interfaz de usuario. |
-| PostSignIn | Un usuario inicia sesión exitosamente a través de la interfaz de usuario. |
-| PostResetPassword | La contraseña de un usuario se restablece exitosamente mediante el flujo de "Olvidé mi contraseña". |
+| Tipo de evento | Descripción |
+| ----------------- | ---------------------------------------------------------------------------------------------------- |
+| PostRegister | Un usuario crea exitosamente una nueva cuenta a través de la interfaz de usuario. |
+| PostSignIn | Un usuario inicia sesión exitosamente a través de la interfaz de usuario. |
+| PostResetPassword | La contraseña de un usuario se restablece exitosamente a través del flujo de "Olvidé mi contraseña". |
## Eventos de hook de mutación de datos \{#data-mutation-hook-events}
@@ -35,24 +35,24 @@ Esta guía enumera los diferentes eventos de webhook de Logto y explica cuándo
| Role.Created | Se crea un nuevo rol. |
| Role.Deleted | Se elimina un rol. |
| Role.Data.Updated | Se actualizan los datos de un rol, por ejemplo, nombre del rol, descripción y estado de rol predeterminado. |
-| Role.Scopes.Updated | Se agregan o eliminan permisos asignados a un rol. |
+| Role.Scopes.Updated | Se añaden o eliminan permisos asignados a un rol. |
### Permiso (Alcance) \{#permission-scope}
-| Tipo de evento | Descripción |
-| ------------------ | -------------------------------------------------------------------------------------- |
-| Scope.Created | Se crea un nuevo permiso de API. |
-| Scope.Deleted | Se elimina un permiso de API. |
-| Scope.Data.Updated | Se actualizan los datos de un permiso de API, por ejemplo, la descripción del permiso. |
+| Tipo de evento | Descripción |
+| ------------------ | ----------------------------------------------------------------------------------- |
+| Scope.Created | Se crea un nuevo permiso de API. |
+| Scope.Deleted | Se elimina un permiso de API. |
+| Scope.Data.Updated | Se actualizan los datos de un permiso de API, por ejemplo, descripción del permiso. |
### Organización \{#organization}
-| Tipo de evento | Descripción |
-| ------------------------------- | ------------------------------------------------------------------------------------------------ |
-| Organization.Created | Se crea una nueva organización. |
-| Organization.Deleted | Se elimina una organización. |
-| Organization.Data.Updated | Se actualizan los datos de una organización, por ejemplo, nombre, descripción, custom.data, etc. |
-| Organization.Membership.Updated | Se agregan o eliminan miembros de una organización. |
+| Tipo de evento | Descripción |
+| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Organization.Created | Se crea una nueva organización. |
+| Organization.Deleted | Se elimina una organización. |
+| Organization.Data.Updated | Se actualizan los datos de una organización, por ejemplo, nombre de la organización, descripción, custom.data, etc. |
+| Organization.Membership.Updated | Se añaden o eliminan usuarios o aplicaciones de una organización. La carga útil incluye [campos delta de membresía](/developers/webhooks/webhooks-request#organizationmembershipupdated-payload). |
### Rol de organización \{#organization-role}
@@ -61,15 +61,15 @@ Esta guía enumera los diferentes eventos de webhook de Logto y explica cuándo
| OrganizationRole.Created | Se crea un nuevo rol de organización. |
| OrganizationRole.Deleted | Se elimina un rol de organización. |
| OrganizationRole.Data.Updated | Se actualizan los datos de un rol de organización, por ejemplo, nombre y descripción del rol de organización. |
-| OrganizationRole.Scopes.Updated | Se agregan o eliminan permisos asignados a un rol de organización. |
+| OrganizationRole.Scopes.Updated | Se añaden o eliminan permisos asignados a un rol de organización. |
### Permiso de organización (alcance) \{#organization-permission-scope}
-| Tipo de evento | Descripción |
-| ------------------------------ | --------------------------------------------------------------------------------------------------------------- |
-| OrganizationScope.Created | Se crea un nuevo permiso de organización. |
-| OrganizationScope.Deleted | Se elimina un permiso de organización. |
-| OrganizationScope.Data.Updated | Se actualizan los datos de un permiso de organización, por ejemplo, la descripción del permiso de organización. |
+| Tipo de evento | Descripción |
+| ------------------------------ | ------------------------------------------------------------------------------------------------------------ |
+| OrganizationScope.Created | Se crea un nuevo permiso de organización. |
+| OrganizationScope.Deleted | Se elimina un permiso de organización. |
+| OrganizationScope.Data.Updated | Se actualizan los datos de un permiso de organización, por ejemplo, descripción del permiso de organización. |
### Eventos desencadenados por Management API \{#management-api-triggered-events}
@@ -96,6 +96,10 @@ Esta guía enumera los diferentes eventos de webhook de Logto y explica cuándo
| PUT /organizations/:id/users | Organization.Membership.Updated |
| POST /organizations/:id/users | Organization.Membership.Updated |
| DELETE /organizations/:id/users/:userId | Organization.Membership.Updated |
+| PUT /organizations/:id/applications | Organization.Membership.Updated |
+| POST /organizations/:id/applications | Organization.Membership.Updated |
+| DELETE /organizations/:id/applications/:applicationId | Organization.Membership.Updated |
+| PUT /organization-invitations/:id/status (Accepted) | Organization.Membership.Updated |
| POST /organization-roles | OrganizationRole.Created, (OrganizationRole.Scopes.Updated) |
| DELETE /organization-roles/:id | OrganizationRole.Deleted |
| PATCH /organization-roles/:id | OrganizationRole.Data.Updated |
@@ -108,21 +112,22 @@ Esta guía enumera los diferentes eventos de webhook de Logto y explica cuándo
### Eventos desencadenados por Experience API \{#experience-api-triggered-events}
-| Acción de interacción de usuario | Evento |
-| ----------------------------------------- | ----------------- |
-| Enlace de correo/teléfono de usuario | User.Data.Updated |
-| Enlace de MFA de usuario | User.Data.Updated |
-| Enlace social/SSO de usuario | User.Data.Updated |
-| Restablecimiento de contraseña de usuario | User.Data.Updated |
-| Registro de usuario | User.Created |
+| Acción de interacción del usuario | Evento |
+| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- |
+| Enlace de correo electrónico / teléfono del usuario | User.Data.Updated |
+| Enlace de MFA del usuario | User.Data.Updated |
+| Enlace social / SSO del usuario | User.Data.Updated |
+| Restablecimiento de contraseña del usuario | User.Data.Updated |
+| Registro de usuario | User.Created |
+| Usuario aprovisionado automáticamente en una organización a través de [aprovisionamiento Just-in-Time](/organizations/just-in-time-provisioning) (coincidencia de dominio de correo electrónico o conector SSO empresarial) | Organization.Membership.Updated |
## Eventos de hook de excepción \{#exception-hook-events}
### Seguridad \{#security}
-| Tipo de evento | Descripción |
-| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| Identifier.Lockout | Una cuenta de usuario es bloqueada debido a intentos consecutivos fallidos de verificación de identidad. Puede ser desencadenado en los siguientes flujos:
- Fallo en la verificación de contraseña
- Fallo en la verificación de código
- Fallo en la verificación de token de un solo uso
|
+| Tipo de evento | Descripción |
+| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Identifier.Lockout | Una cuenta de usuario se bloquea debido a intentos consecutivos fallidos de verificación de identidad. Puede desencadenarse en los siguientes flujos:
- Fallo en la verificación de contraseña
- Fallo en la verificación de código
- Fallo en la verificación de token de un solo uso
|
## Preguntas frecuentes \{#faqs}
diff --git a/i18n/es/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx b/i18n/es/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx
index 2c78eebcb1a..2abfa2329e6 100644
--- a/i18n/es/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx
+++ b/i18n/es/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx
@@ -5,25 +5,62 @@ sidebar_label: Solicitud de Webhooks (Webhooks request)
sidebar_position: 4
---
-# Solicitud de Webhooks (Webhooks request)
+# Solicitud de Webhooks
-Una vez que se emite un evento de hook válido, Logto buscará los webhooks correspondientes y enviará una solicitud POST por cada configuración de hook.
+Cuando se activa un evento de webhook, Logto envía una solicitud `POST` a cada endpoint suscrito a él. El catálogo completo de eventos se encuentra en [Eventos de Webhooks](/developers/webhooks/webhooks-events); esta página documenta la **forma de la solicitud** que Logto entrega.
## Encabezados de la solicitud \{#request-headers}
-| Key | Personalizable | Notas |
-| ----------------------- | -------------- | ----------------------------------------------------------------------------------------------------------- |
-| user-agent | ✅ | `Logto (https://logto.io/)` por defecto. |
-| content-type | ✅ | `application/json` por defecto. |
-| logto-signature-sha-256 | | la firma del cuerpo de la solicitud, consulta [asegura tus webhooks](/developers/webhooks/secure-webhooks). |
+| Key | Personalizable | Notas |
+| ----------------------- | -------------- | ------------------------------------------------------------------------------------------------------ |
+| user-agent | ✅ | `Logto (https://logto.io/)` por defecto. |
+| content-type | ✅ | `application/json` por defecto. |
+| logto-signature-sha-256 | | Firma del cuerpo de la solicitud. Ver [asegurando tus webhooks](/developers/webhooks/secure-webhooks). |
-Puedes sobrescribir los encabezados personalizables [personalizando los encabezados de la solicitud](/developers/webhooks/configure-webhooks/#secure-webhook) con la misma clave.
+Los encabezados personalizables se pueden sobrescribir a través de la configuración de [webhook seguro](/developers/webhooks/configure-webhooks/#secure-webhook).
-## Cuerpo de la solicitud de eventos de interaction hook \{#interaction-hook-events-request-body}
+## Resumen del cuerpo de la solicitud \{#request-body-overview}
-Eventos disponibles: `PostRegister`, `PostSignIn`, `PostResetPassword`
+El cuerpo es un objeto JSON. Su forma exacta depende de a qué familia pertenece el evento:
-El cuerpo de la solicitud es un objeto JSON que contiene tres tipos de campos de datos:
+| Familia | Eventos | Cuándo se activa |
+| --------------------- | -------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
+| **Flujo de usuario** | `PostRegister`, `PostSignIn`, `PostResetPassword` | Un usuario completa un flujo de registro, inicio de sesión o restablecimiento de contraseña manejado por la Experience API. |
+| **Mutación de datos** | `User.*`, `Role.*`, `Scope.*`, `Organization.*`, `OrganizationRole.*`, `OrganizationScope.*` | El modelo de datos subyacente se muta, ya sea por una llamada a la Management API o por un flujo de usuario en la Experience API. |
+| **Excepción** | `Identifier.Lockout` | Un incidente de seguridad, por ejemplo, una cuenta bloqueada después de intentos fallidos consecutivos de verificación. |
+
+Cada familia comparte un pequeño conjunto de [campos comunes](#common-fields). Luego, cada familia agrega sus propios campos de contexto de solicitud más una carga útil específica del evento.
+
+### Campos comunes \{#common-fields}
+
+Presentes en cada entrega independientemente de la familia:
+
+| Campo | Tipo | Opcional | Notas |
+| --------- | -------- | -------- | --------------------------------------------------------- |
+| hookId | `string` | | El identificador de configuración del webhook en Logto. |
+| event | `string` | | El evento que activó esta entrega. |
+| createdAt | `string` | | La hora de creación de la carga útil en formato ISO 8601. |
+| userAgent | `string` | ✅ | El user-agent de la solicitud que activó el evento. |
+
+Cada familia también incluye la dirección IP de la solicitud que activó el evento, bajo el nombre de campo `userIp` para eventos de flujo de usuario y `ip` para eventos de mutación de datos y excepciones. La semántica es idéntica; la diferencia de nombre histórica se conserva para compatibilidad con versiones anteriores.
+
+## Cargas útiles de eventos de flujo de usuario \{#user-flow-event-payloads}
+
+**Eventos:** `PostRegister`, `PostSignIn`, `PostResetPassword`.
+
+Se activan cuando un usuario completa un flujo de registro, inicio de sesión o restablecimiento de contraseña manejado por la Experience API. Además de los [campos comunes](#common-fields), el cuerpo lleva:
+
+| Campo | Tipo | Opcional | Notas |
+| ---------------- | -------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| interactionEvent | `'SignIn' \| 'Register' \| 'ForgotPassword'` | | El tipo de evento de flujo de usuario. Se mapea a `PostSignIn` / `PostRegister` / `PostResetPassword` respectivamente. El nombre del campo conserva el nombre histórico "interaction". |
+| sessionId | `string` | ✅ | El ID de la sesión (no el ID de interacción) para este evento, si corresponde. |
+| userIp | `string` | ✅ | La dirección IP de la solicitud que activó el evento. |
+| userId | `string` | ✅ | El ID de usuario asociado con este evento, si corresponde. |
+| user | `UserEntity` | ✅ | La entidad de usuario asociada con este evento, si corresponde. |
+| applicationId | `string` | ✅ | El ID de la aplicación asociado con este evento, si corresponde. |
+| application | `ApplicationEntity` | ✅ | La entidad de la aplicación asociada con este evento, si corresponde. |
+
+#### Formas de las entidades \{#user-flow-entity-shapes}
```tsx
type UserEntity = {
@@ -60,70 +97,57 @@ type ApplicationEntity = {
};
```
-| Campo | Tipo | Opcional | Notas |
-| ---------------- | ------------------- | -------- | ------------------------------------------------------------------------ |
-| hookId | `string` | | El identificador en Logto. |
-| event | `string` | | Qué evento dispara este hook. |
-| createdAt | `string` | | La fecha de creación del payload en formato ISO. |
-| interactionEvent | `string` | | El evento de interacción que dispara este hook. |
-| sessionId | `string` | ✅ | El ID de sesión (no el ID de interacción) para este evento, si aplica. |
-| userAgent | `string` | ✅ | El user-agent de la solicitud que dispara este hook. |
-| userIp | `string` | ✅ | La dirección IP de la solicitud que dispara este hook. |
-| userId | `string` | ✅ | El ID de usuario relacionado para este evento, si aplica. |
-| user | `UserEntity` | ✅ | La entidad de usuario relacionada para este evento, si aplica. |
-| applicationId | `string` | ✅ | El ID de aplicación relacionado para este evento, si aplica. |
-| application | `ApplicationEntity` | ✅ | La información de la aplicación relacionada para este evento, si aplica. |
+Consulta [Usuarios](/user-management/user-data) y [Aplicaciones](/integrate-logto/application-data-structure) para la referencia completa de campos.
-Consulta la referencia de [Usuarios](/user-management/user-data) y [Aplicaciones](/integrate-logto/application-data-structure) para explicaciones detalladas de los campos.
+## Cargas útiles de eventos de mutación de datos \{#data-mutation-event-payloads}
-## Cuerpo de la solicitud de eventos de data mutation hook \{#data-mutation-hook-events-request-body}
+**Eventos:** cada evento bajo `User.*`, `Role.*`, `Scope.*`, `Organization.*`, `OrganizationRole.*`, `OrganizationScope.*` — consulta [Eventos de Webhooks → Eventos de mutación de datos](/developers/webhooks/webhooks-events#data-mutation-hook-events) para el catálogo completo.
-### Campos estándar del cuerpo de la solicitud \{#standard-request-body-fields}
+El cuerpo siempre lleva:
-| Campo | Tipo | Opcional | Notas |
-| --------- | -------- | -------- | ------------------------------------------------ |
-| hookId | `string` | | El identificador en Logto. |
-| event | `string` | | Qué evento dispara este hook. |
-| createdAt | `string` | | La fecha de creación del payload en formato ISO. |
-| userAgent | `string` | ✅ | El user-agent de la solicitud. |
-| ip | `string` | ✅ | La dirección IP de la solicitud. |
+- Los [campos comunes](#common-fields).
+- Un campo `ip` — la dirección IP de la solicitud que activó el evento (opcional, presente cuando se conoce).
+- Un **contexto de API** que describe cómo se activó el cambio. El contexto es una de dos variantes dependiendo de la fuente del disparador:
+ - [Campos de contexto de la Experience API](#experience-api-context-fields) — cuando el cambio proviene de un flujo orientado al usuario.
+ - [Campos de contexto de la Management API](#management-api-context-fields) — cuando el cambio proviene de una llamada directa a la Management API.
+- Una **carga útil específica del evento** — la entidad afectada en `data` y (para algunos eventos) campos adicionales de nivel superior. Consulta [cargas útiles de datos específicas del evento](#event-specific-data-payloads).
-### Campos del cuerpo de contexto de Interaction API \{#interaction-api-context-body-fields}
+### Campos de contexto de la Experience API \{#experience-api-context-fields}
-Eventos de data mutation hook que son disparados por llamadas a la API de interacción de usuario.
+Presentes cuando el cambio fue activado por un flujo orientado al usuario en la Experience API — por ejemplo, `User.Created` durante el registro o `User.Data.Updated` durante las actualizaciones de perfil.
-Eventos disponibles: `User.Created`, `User.Data.Updated`
+| Campo | Tipo | Opcional | Notas |
+| ---------------- | -------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------- |
+| interactionEvent | `'SignIn' \| 'Register' \| 'ForgotPassword'` | ✅ | El tipo de evento de flujo de usuario que produjo el cambio. El nombre del campo conserva el nombre histórico "interaction". |
+| sessionId | `string` | ✅ | El ID de la sesión (no el ID de interacción) para este evento, si corresponde. |
+| applicationId | `string` | ✅ | El ID de la aplicación, si corresponde. |
+| application | `ApplicationEntity` | ✅ | La entidad de la aplicación, si corresponde. |
-| Campo | Tipo | Opcional | Notas |
-| ---------------- | ------------------- | -------- | ------------------------------------------------------------------------ |
-| interactionEvent | `string` | ✅ | El evento de interacción que dispara este hook. |
-| sessionId | `string` | ✅ | El ID de sesión (no el ID de interacción) para este evento, si aplica. |
-| applicationId | `string` | ✅ | El ID de aplicación relacionado para este evento, si aplica. |
-| application | `ApplicationEntity` | ✅ | La información de la aplicación relacionada para este evento, si aplica. |
+### Campos de contexto de la Management API \{#management-api-context-fields}
-### Campos del cuerpo de contexto de Management API \{#management-api-context-body-fields}
+Presentes cuando el cambio fue activado por una llamada a la Management API.
-Eventos de data mutation hook que son disparados por llamadas a la Management API.
+| Campo | Tipo | Opcional | Notas |
+| ------------ | -------- | -------- | ------------------------------------------------------------------------------------------------------------------ |
+| path | `string` | ✅ | La ruta de la llamada a la API que activó este hook. |
+| method | `string` | ✅ | El método HTTP de la llamada a la API. |
+| status | `number` | ✅ | El código de estado de respuesta de la llamada a la API. |
+| params | `object` | ✅ | Los parámetros de ruta de koa de la llamada a la API. |
+| matchedRoute | `string` | ✅ | La ruta coincidente de koa. Logto usa este campo para coincidir con los filtros de eventos de webhook habilitados. |
-| Campo | Tipo | Opcional | Notas |
-| ------------ | -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
-| path | `string` | ✅ | La ruta de la llamada a la API que dispara este hook. |
-| method | `string` | ✅ | El método de la llamada a la API que dispara este hook. |
-| status | `number` | ✅ | El código de estado de la respuesta de la llamada a la API que dispara este hook. |
-| params | `object` | ✅ | Los parámetros de ruta koa de la solicitud de la API que dispara este hook. |
-| matchedRoute | `string` | ✅ | La ruta koa coincidente de la llamada a la API que dispara este hook. Logto usa este campo para emparejar los eventos habilitados de hook. |
+### Cargas útiles de datos específicas del evento \{#event-specific-data-payloads}
-### Campos del cuerpo de datos del payload \{#data-payload-body-fields}
+Cada evento de mutación de datos incluye un campo `data` de nivel superior que lleva la entidad afectada, o `null` cuando el cambio no se puede resumir como una sola entidad (eventos de eliminación y membresía). Algunos eventos también incluyen campos de nivel superior específicos del evento más allá de `data` — `Organization.Membership.Updated` es uno de esos casos, documentado a continuación.
-**Eventos de usuario**
+#### Eventos de usuario \{#user-events}
-| Evento | Campo | Tipo | Opcional | Notas |
-| ----------------- | ----- | ---------- | -------- | --------------------------------------------------- |
-| User.Created | data | UserEntity | | La entidad de usuario creada para este evento. |
-| User.Data.Updated | data | UserEntity | | La entidad de usuario actualizada para este evento. |
-| User.Deleted | data | null | / | |
+| Evento | Campo | Tipo | Opcional | Notas |
+| ----------------- | ----- | ------------ | -------- | ---------------------------------- |
+| User.Created | data | `UserEntity` | | La entidad de usuario creada. |
+| User.Data.Updated | data | `UserEntity` | | La entidad de usuario actualizada. |
+| User.Deleted | data | `null` | / | |
-**Eventos de rol (Role)**
+#### Eventos de rol \{#role-events}
```tsx
type Role = {
@@ -145,23 +169,23 @@ type Scope = {
};
```
-| Evento | Campo | Tipo | Opcional | Notas |
-| ------------------ | ------ | ------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| Role.Created | data | Role | | La entidad de rol creada para este evento. |
-| Role.Data.Updated | data | Role | | La entidad de rol actualizada para este evento. |
-| Role.Deleted | data | null | | |
-| Role.Scope.Updated | data | Scope[] | | Los alcances (scopes) actualizados asignados al rol. |
-| Role.Scope.Updated | roleId | string | ✅ | El ID del rol al que se asignan los alcances. (Solo disponible cuando el evento fue disparado por la creación de un nuevo rol con alcances preasignados) |
+| Evento | Campo | Tipo | Opcional | Notas |
+| ------------------- | ------ | --------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
+| Role.Created | data | `Role` | | La entidad de rol creada. |
+| Role.Data.Updated | data | `Role` | | La entidad de rol actualizada. |
+| Role.Deleted | data | `null` | / | |
+| Role.Scopes.Updated | data | `Scope[]` | | Los alcances actualizados asignados al rol. |
+| Role.Scopes.Updated | roleId | `string` | ✅ | El ID del rol al que se asignan los alcances. (Solo disponible cuando el evento fue activado al crear un rol con alcances preasignados.) |
-**Eventos de permiso (Scope)**
+#### Eventos de permiso (alcance) \{#permission-events}
-| Evento | Campo | Tipo | Opcional | Notas |
-| ------------------ | ----- | ----- | -------- | --------------------------------------------------- |
-| Scope.Created | data | Scope | | La entidad de alcance creada para este evento. |
-| Scope.Data.Updated | data | Scope | | La entidad de alcance actualizada para este evento. |
-| Scope.Deleted | data | null | / | |
+| Evento | Campo | Tipo | Opcional | Notas |
+| ------------------ | ----- | ------- | -------- | ---------------------------------- |
+| Scope.Created | data | `Scope` | | La entidad de alcance creada. |
+| Scope.Data.Updated | data | `Scope` | | La entidad de alcance actualizada. |
+| Scope.Deleted | data | `null` | / | |
-**Eventos de organización (Organization)**
+#### Eventos de organización \{#organization-events}
```tsx
type Organization = {
@@ -173,14 +197,141 @@ type Organization = {
};
```
-| Evento | Campo | Tipo | Opcional | Notas |
-| ------------------------------- | ----- | ------------ | -------- | -------------------------------------------------------- |
-| Organization.Created | data | Organization | | La entidad de organización creada para este evento. |
-| Organization.Data.Updated | data | Organization | | La entidad de organización actualizada para este evento. |
-| Organization.Deleted | data | null | / | |
-| Organization.Membership.Updated | data | null | / | |
+| Evento | Campo | Tipo | Opcional | Notas |
+| ------------------------------- | ----- | -------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Organization.Created | data | `Organization` | | La entidad de organización creada. |
+| Organization.Data.Updated | data | `Organization` | | La entidad de organización actualizada. |
+| Organization.Deleted | data | `null` | / | |
+| Organization.Membership.Updated | data | `null` | / | El cambio se describe mediante matrices delta opcionales de nivel superior. Ver [carga útil de Organization.Membership.Updated](#organizationmembershipupdated-payload) a continuación. |
+
+##### Carga útil de Organization.Membership.Updated \{#organizationmembershipupdated-payload}
+
+Además de los [campos comunes](#common-fields) y de los campos de contexto de API que correspondan a la fuente del disparador ([contexto de Management API](#management-api-context-fields) para las rutas de la Management API, [contexto de Experience API](#experience-api-context-fields) para el aprovisionamiento just-in-time), el evento `Organization.Membership.Updated` lleva un `organizationId` más matrices delta opcionales en el nivel superior de la carga útil (junto a `event`, `createdAt`, etc.; **no** dentro de `data`, que siempre es `null` para este evento).
+
+| Campo | Tipo | Opcional | Notas |
+| --------------------- | ---------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| organizationId | `string` | | La organización cuya membresía cambió. |
+| addedUserIds | `string[]` | ✅ | IDs de usuario recién agregados por este disparador. Omitido cuando no se agregaron usuarios, o cuando el disparador no afecta la membresía de usuarios. |
+| removedUserIds | `string[]` | ✅ | IDs de usuario eliminados por este disparador. Omitido cuando no se eliminaron usuarios. |
+| addedApplicationIds | `string[]` | ✅ | IDs de aplicación recién agregados. Omitido cuando no se agregaron aplicaciones, o cuando el disparador no afecta la membresía de aplicaciones. |
+| removedApplicationIds | `string[]` | ✅ | IDs de aplicación eliminados. Omitido cuando no se eliminaron aplicaciones. |
+
+Las cuatro matrices delta son **opcionales y aditivas** — no cambian la forma de la carga útil existente para los consumidores que no las esperan, y el campo heredado `data: null` todavía se emite sin cambios.
+
+###### Disparadores y qué campos delta pueden emitir \{#membership-triggers}
+
+| Disparador | Campos delta posibles |
+| ---------------------------------------------------------------------------- | ---------------------------------------------- |
+| `POST /organizations/:id/users` | `addedUserIds` |
+| `PUT /organizations/:id/users` | `addedUserIds`, `removedUserIds` |
+| `DELETE /organizations/:id/users/:userId` | `removedUserIds` |
+| `POST /organizations/:id/applications` | `addedApplicationIds` |
+| `PUT /organizations/:id/applications` | `addedApplicationIds`, `removedApplicationIds` |
+| `DELETE /organizations/:id/applications/:applicationId` | `removedApplicationIds` |
+| `PUT /organization-invitations/:id/status` (`Accepted`) | `addedUserIds` |
+| Aprovisionamiento Just-in-Time al añadir al usuario a una nueva organización | `addedUserIds` |
+
+Nota: el aprovisionamiento just-in-time no emite `Organization.Membership.Updated` para una organización de la que el usuario ya es miembro.
+
+###### Las deltas vacías se omiten — ausente ≠ cambio vacío \{#empty-deltas-are-omitted}
+
+Las matrices delta vacías se **omiten por completo** de la carga útil. Por ejemplo, un `PUT /organizations/:id/users` que reemplaza el conjunto de membresía con el conjunto existente no produce un cambio real, y la carga útil se reduce a solo `{ organizationId }` con los cuatro campos delta ausentes. Lo mismo se aplica a una re-adición de un miembro existente, una re-aceptación de una invitación por parte de un usuario que ya es miembro que ya es miembro.
+
+**Los consumidores deben tratar un campo faltante como "sin cambio en ese lado", no como "un cambio vacío".**
+
+###### Límite por matriz (truncamiento silencioso) \{#membership-delta-cap}
+
+Cada matriz delta está limitada a **5000 entradas**. Cuando una sola llamada a la Management API agrega o elimina más de 5000 usuarios (o aplicaciones) en una operación, la matriz delta correspondiente se trunca silenciosamente a sus primeras 5000 entradas — **no hay un marcador en la carga útil** que indique que se activó un límite.
+
+Si tu aplicación realiza operaciones administrativas masivas que pueden afectar plausiblemente a más de 5000 miembros en una llamada, trata una matriz de exactamente 5000 entradas como una señal para reconciliar la membresía autorizada a través de la Management API:
+
+- `GET /organizations/:id/users` — membresía completa de usuarios.
+- `GET /organizations/:id/applications` — membresía completa de aplicaciones.
+
+Esto sigue el mismo patrón que el evento `push` de GitHub, que limita `commits` a 20 entradas y señala a los consumidores hacia la API de comparación para la lista completa.
+
+###### Omitiendo eventos sin cambios \{#skipping-no-op-events}
+
+Cada `PUT` contra las rutas de membresía emite un evento independientemente de si algo realmente cambió — para que cualquier llamada de reemplazo de estado tenga al menos una entrega de webhook para fines de auditoría. Para omitir entregas sin cambios en el lado del consumidor, filtra en la presencia de matrices delta:
+
+```ts
+if (
+ payload.addedUserIds?.length ||
+ payload.removedUserIds?.length ||
+ payload.addedApplicationIds?.length ||
+ payload.removedApplicationIds?.length
+) {
+ // cambio real de membresía — manejarlo
+}
+```
+
+`?.length` es falso tanto para `undefined` como para `[]`, por lo que el mismo predicado es robusto ya sea que el campo esté ausente o (en algún futuro hipotético) se emita como una matriz vacía.
+
+###### Ejemplos de cargas útiles \{#membership-example-payloads}
+
+**Agregar un usuario (`POST /organizations/:id/users`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "addedUserIds": ["u_001"]
+}
+```
+
+**Reemplazar el conjunto de membresía de usuarios (`PUT /organizations/:id/users`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "addedUserIds": ["u_002"],
+ "removedUserIds": ["u_001"]
+}
+```
+
+**Eliminar un usuario (`DELETE /organizations/:id/users/:userId`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "removedUserIds": ["u_001"]
+}
+```
-**Eventos de OrganizationRole**
+**Agregar una aplicación (`POST /organizations/:id/applications`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "addedApplicationIds": ["app_xyz"]
+}
+```
+
+**Re-agregar un miembro existente, `PUT` sin cambios, o re-aceptación de una invitación ya miembro (sin cambio real):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc"
+}
+```
+
+**Operación masiva que alcanza el límite de 5000 (truncada silenciosamente):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "removedUserIds": ["u_0001", "u_0002", "/* … exactamente 5000 entradas en total */"]
+}
+```
+
+Ver una matriz de exactamente 5000 entradas debería provocar una reconciliación `GET /organizations/:id/users` (o `/applications`).
+
+#### Eventos de rol de organización \{#organization-role-events}
```tsx
type OrganizationRole = {
@@ -198,27 +349,32 @@ type OrganizationScope = {
};
```
-| Evento | Campo | Tipo | Opcional | Notas |
-| ------------------------------ | ------------------ | ---------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| OrganizationRole.Created | data | OrganizationRole | | La entidad de rol de organización creada para este evento. |
-| OrganizationRole.Data.Updated | data | OrganizationRole | | La entidad de rol de organización actualizada para este evento. |
-| OrganizationRole.Deleted | data | null | / | |
-| OrganizationRole.Scope.Updated | data | null | / | |
-| OrganizationRole.Scope.Updated | organizationRoleId | string | ✅ | El ID del rol al que se asignan los alcances. (Solo disponible cuando el evento fue disparado por la creación de un nuevo rol con alcances preasignados) |
+| Evento | Campo | Tipo | Opcional | Notas |
+| ------------------------------- | ------------------ | ------------------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
+| OrganizationRole.Created | data | `OrganizationRole` | | La entidad de rol de organización creada. |
+| OrganizationRole.Data.Updated | data | `OrganizationRole` | | La entidad de rol de organización actualizada. |
+| OrganizationRole.Deleted | data | `null` | / | |
+| OrganizationRole.Scopes.Updated | data | `null` | / | |
+| OrganizationRole.Scopes.Updated | organizationRoleId | `string` | ✅ | El ID del rol al que se asignan los alcances. (Solo disponible cuando el evento fue activado al crear un rol con alcances preasignados.) |
+
+#### Eventos de permiso de organización (alcance) \{#organization-permission-events}
-**Eventos de permiso de organización (OrganizationScope)**
+| Evento | Campo | Tipo | Opcional | Notas |
+| ------------------------------ | ----- | ------------------- | -------- | -------------------------------------------------- |
+| OrganizationScope.Created | data | `OrganizationScope` | | La entidad de alcance de organización creada. |
+| OrganizationScope.Data.Updated | data | `OrganizationScope` | | La entidad de alcance de organización actualizada. |
+| OrganizationScope.Deleted | data | `null` | / | |
-| Evento | Campo | Tipo | Opcional | Notas |
-| ------------------------------ | ----- | ----------------- | -------- | -------------------------------------------------- |
-| OrganizationScope.Created | data | OrganizationScope | | La entidad de alcance de organización creada. |
-| OrganizationScope.Data.Updated | data | OrganizationScope | | La entidad de alcance de organización actualizada. |
-| OrganizationScope.Deleted | data | null | / | |
+## Cargas útiles de eventos de excepción \{#exception-event-payloads}
-## Cuerpo de la solicitud de eventos de excepción hook \{#exception-hook-events-request-body}
+**Eventos:** `Identifier.Lockout`.
-Eventos disponibles: `Identifier.Lockout`
+Se activan en incidentes de seguridad, por ejemplo, una cuenta bloqueada después de intentos fallidos consecutivos de verificación. Estos eventos siempre se originan en un flujo orientado al usuario, por lo que el cuerpo lleva:
-El cuerpo de la solicitud es un objeto JSON que contiene los campos estándar del cuerpo de la solicitud y campos adicionales como se muestra a continuación:
+- Los [campos comunes](#common-fields).
+- El campo `ip` (misma forma que los eventos de mutación de datos).
+- Los [campos de contexto de la Experience API](#experience-api-context-fields).
+- Los campos específicos de la excepción a continuación.
```tsx
enum SignInIdentifier {
@@ -228,16 +384,7 @@ enum SignInIdentifier {
}
```
-| Campo | Tipo | Opcional | Notas |
-| ---------------- | ------------------- | -------- | --------------------------------------------------------------------------------------- |
-| hookId | `string` | | El identificador en Logto. |
-| event | `string` | | Qué evento dispara este hook. |
-| createdAt | `string` | | La fecha de creación del payload en formato ISO. |
-| userAgent | `string` | ✅ | El user-agent de la solicitud. |
-| ip | `string` | ✅ | La dirección IP de la solicitud. |
-| interactionEvent | `string` | ✅ | El evento de interacción que dispara este hook. |
-| sessionId | `string` | ✅ | El ID de sesión (no el ID de interacción) para este evento, si aplica. |
-| applicationId | `string` | ✅ | El ID de aplicación relacionado para este evento, si aplica. |
-| application | `ApplicationEntity` | ✅ | La información de la aplicación relacionada para este evento, si aplica. |
-| type | `SignInIdentifier` | | El tipo de identificador del usuario, por ejemplo, email, teléfono o nombre de usuario. |
-| value | `string` | | El valor del identificador del usuario que disparó el bloqueo. |
+| Campo | Tipo | Opcional | Notas |
+| ----- | ------------------ | -------- | ---------------------------------------------------------------------------------------------------- |
+| type | `SignInIdentifier` | | El tipo de identificador del usuario, por ejemplo, correo electrónico, teléfono o nombre de usuario. |
+| value | `string` | | El valor del identificador del usuario que activó el bloqueo. |
diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx b/i18n/fr/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx
index 6b5e2610a4a..73094c4b106 100644
--- a/i18n/fr/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx
+++ b/i18n/fr/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx
@@ -7,7 +7,7 @@ sidebar_position: 3
# Événements Webhooks
-Ce guide liste les différents événements webhook de Logto et explique quand chaque événement se produit.
+Ce guide répertorie les différents événements de webhook Logto et explique quand chaque événement se produit.
## Événements de hook d'interaction utilisateur \{#user-interaction-hook-events}
@@ -21,57 +21,57 @@ Ce guide liste les différents événements webhook de Logto et explique quand c
### Utilisateur \{#user}
-| Type d'événement | Description |
-| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
-| User.Created | Un nouveau compte utilisateur est créé. |
-| User.Deleted | Un compte utilisateur est supprimé. |
-| User.Data.Updated | Les données du profil utilisateur sont mises à jour, par exemple : e-mail, avatar, custom.data, identifiant social, etc. |
-| User.SuspensionStatus.Updated | Le statut de suspension de l'utilisateur est modifié (suspendu ou réactivé). |
+| Type d'événement | Description |
+| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
+| User.Created | Un nouveau compte utilisateur est créé. |
+| User.Deleted | Un compte utilisateur est supprimé. |
+| User.Data.Updated | Les données du profil utilisateur sont mises à jour, par exemple, email, avatar, custom.data, identifiant social, etc. |
+| User.SuspensionStatus.Updated | Le statut de suspension de l'utilisateur est modifié (suspendu ou réactivé). |
### Rôle \{#role}
-| Type d'événement | Description |
-| ------------------- | --------------------------------------------------------------------------------------------------- |
-| Role.Created | Un nouveau rôle est créé. |
-| Role.Deleted | Un rôle est supprimé. |
-| Role.Data.Updated | Les données d'un rôle sont mises à jour, par exemple : nom du rôle, description, statut par défaut. |
-| Role.Scopes.Updated | Les permissions attribuées à un rôle sont ajoutées ou supprimées. |
+| Type d'événement | Description |
+| ------------------- | ------------------------------------------------------------------------------------------------------------- |
+| Role.Created | Un nouveau rôle est créé. |
+| Role.Deleted | Un rôle est supprimé. |
+| Role.Data.Updated | Les données d'un rôle sont mises à jour, par exemple, nom du rôle, description, et statut de rôle par défaut. |
+| Role.Scopes.Updated | Les permissions attribuées à un rôle sont ajoutées ou supprimées. |
### Permission (Portée) \{#permission-scope}
-| Type d'événement | Description |
-| ------------------ | ----------------------------------------------------------------------------------------------- |
-| Scope.Created | Une nouvelle permission API est créée. |
-| Scope.Deleted | Une permission API est supprimée. |
-| Scope.Data.Updated | Les données d'une permission API sont mises à jour, par exemple : description de la permission. |
+| Type d'événement | Description |
+| ------------------ | ---------------------------------------------------------------------------------------------- |
+| Scope.Created | Une nouvelle permission API est créée. |
+| Scope.Deleted | Une permission API est supprimée. |
+| Scope.Data.Updated | Les données d'une permission API sont mises à jour, par exemple, description de la permission. |
### Organisation \{#organization}
-| Type d'événement | Description |
-| ------------------------------- | --------------------------------------------------------------------------------------------------- |
-| Organization.Created | Une nouvelle organisation est créée. |
-| Organization.Deleted | Une organisation est supprimée. |
-| Organization.Data.Updated | Les données d'une organisation sont mises à jour, par exemple : nom, description, custom.data, etc. |
-| Organization.Membership.Updated | Des membres sont ajoutés ou supprimés d'une organisation. |
+| Type d'événement | Description |
+| ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Organization.Created | Une nouvelle organisation est créée. |
+| Organization.Deleted | Une organisation est supprimée. |
+| Organization.Data.Updated | Les données d'une organisation sont mises à jour, par exemple, nom de l'organisation, description, custom.data, etc. |
+| Organization.Membership.Updated | Des utilisateurs ou des applications sont ajoutés ou supprimés d'une organisation. La charge utile inclut les [champs delta d'adhésion](/developers/webhooks/webhooks-request#organizationmembershipupdated-payload). |
### Rôle d'organisation \{#organization-role}
-| Type d'événement | Description |
-| ------------------------------- | ----------------------------------------------------------------------------------------- |
-| OrganizationRole.Created | Un nouveau rôle d'organisation est créé. |
-| OrganizationRole.Deleted | Un rôle d'organisation est supprimé. |
-| OrganizationRole.Data.Updated | Les données d'un rôle d'organisation sont mises à jour, par exemple : nom et description. |
-| OrganizationRole.Scopes.Updated | Les permissions attribuées à un rôle d'organisation sont ajoutées ou supprimées. |
+| Type d'événement | Description |
+| ------------------------------- | --------------------------------------------------------------------------------------------------------------- |
+| OrganizationRole.Created | Un nouveau rôle d'organisation est créé. |
+| OrganizationRole.Deleted | Un rôle d'organisation est supprimé. |
+| OrganizationRole.Data.Updated | Les données d'un rôle d'organisation sont mises à jour, par exemple, nom et description du rôle d'organisation. |
+| OrganizationRole.Scopes.Updated | Les permissions attribuées à un rôle d'organisation sont ajoutées ou supprimées. |
### Permission d'organisation (portée) \{#organization-permission-scope}
-| Type d'événement | Description |
-| ------------------------------ | ---------------------------------------------------------------------------------------------------------- |
-| OrganizationScope.Created | Une nouvelle permission d'organisation est créée. |
-| OrganizationScope.Deleted | Une permission d'organisation est supprimée. |
-| OrganizationScope.Data.Updated | Les données d'une permission d'organisation sont mises à jour, par exemple : description de la permission. |
+| Type d'événement | Description |
+| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------ |
+| OrganizationScope.Created | Une nouvelle permission d'organisation est créée. |
+| OrganizationScope.Deleted | Une permission d'organisation est supprimée. |
+| OrganizationScope.Data.Updated | Les données d'une permission d'organisation sont mises à jour, par exemple, description de la permission d'organisation. |
-### Événements déclenchés par la Management API \{#management-api-triggered-events}
+### Événements déclenchés par Management API \{#management-api-triggered-events}
| Point de terminaison API | Événement |
| ---------------------------------------------------------- | ----------------------------------------------------------- |
@@ -96,6 +96,10 @@ Ce guide liste les différents événements webhook de Logto et explique quand c
| PUT /organizations/:id/users | Organization.Membership.Updated |
| POST /organizations/:id/users | Organization.Membership.Updated |
| DELETE /organizations/:id/users/:userId | Organization.Membership.Updated |
+| PUT /organizations/:id/applications | Organization.Membership.Updated |
+| POST /organizations/:id/applications | Organization.Membership.Updated |
+| DELETE /organizations/:id/applications/:applicationId | Organization.Membership.Updated |
+| PUT /organization-invitations/:id/status (Accepted) | Organization.Membership.Updated |
| POST /organization-roles | OrganizationRole.Created, (OrganizationRole.Scopes.Updated) |
| DELETE /organization-roles/:id | OrganizationRole.Deleted |
| PATCH /organization-roles/:id | OrganizationRole.Data.Updated |
@@ -106,25 +110,26 @@ Ce guide liste les différents événements webhook de Logto et explique quand c
| POST /organization-roles/:id/scopes | OrganizationRole.Scopes.Updated |
| DELETE /organization-roles/:id/scopes/:organizationScopeId | OrganizationRole.Scopes.Updated |
-### Événements déclenchés par l’Experience API \{#experience-api-triggered-events}
+### Événements déclenchés par Experience API \{#experience-api-triggered-events}
-| Action d'interaction utilisateur | Événement |
-| -------------------------------------------- | ----------------- |
-| Liaison e-mail/téléphone utilisateur | User.Data.Updated |
-| Liaison MFA utilisateur | User.Data.Updated |
-| Liaison social/SSO utilisateur | User.Data.Updated |
-| Réinitialisation du mot de passe utilisateur | User.Data.Updated |
-| Inscription utilisateur | User.Created |
+| Action d'interaction utilisateur | Événement |
+| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- |
+| Liaison email / téléphone utilisateur | User.Data.Updated |
+| Liaison MFA utilisateur | User.Data.Updated |
+| Liaison sociale / SSO utilisateur | User.Data.Updated |
+| Réinitialisation du mot de passe utilisateur | User.Data.Updated |
+| Inscription utilisateur | User.Created |
+| Utilisateur auto-approvisionné dans une organisation via [approvisionnement Just-in-Time](/organizations/just-in-time-provisioning) (correspondance de domaine email ou connecteur SSO d'entreprise) | Organization.Membership.Updated |
-## Événements de hook d’exception \{#exception-hook-events}
+## Événements de hook d'exception \{#exception-hook-events}
### Sécurité \{#security}
-| Type d'événement | Description |
-| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| Identifier.Lockout | Un compte utilisateur est verrouillé suite à des tentatives consécutives de vérification d'identité échouées. Peut être déclenché dans les flux suivants :
- Échec de la vérification du mot de passe
- Échec de la vérification du code
- Échec de la vérification du jeton à usage unique
|
+| Type d'événement | Description |
+| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Identifier.Lockout | Un compte utilisateur est verrouillé en raison de tentatives consécutives de vérification d'identité échouées. Peut être déclenché dans les flux suivants :
- Échec de la vérification du mot de passe
- Échec de la vérification du code
- Échec de la vérification du jeton unique
|
-## FAQ \{#faqs}
+## FAQs \{#faqs}
@@ -133,6 +138,6 @@ Ce guide liste les différents événements webhook de Logto et explique quand c
-`PostRegister` est déclenché lorsqu'un utilisateur crée avec succès un nouveau compte via le flux d'inscription utilisateur ; `User.Created` est déclenché lorsqu'un nouveau compte utilisateur est créé via la Management API.
+`PostRegister` est déclenché lorsqu'un utilisateur crée avec succès un nouveau compte via le flux d'inscription utilisateur ; `User.Created` est déclenché lorsqu'un nouveau compte utilisateur est créé via Management API.
diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx b/i18n/fr/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx
index f0f1991c5eb..d8310f348d6 100644
--- a/i18n/fr/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx
+++ b/i18n/fr/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx
@@ -5,25 +5,62 @@ sidebar_label: Requête Webhooks
sidebar_position: 4
---
-# Requête Webhooks
+# Requête de Webhooks
-Lorsqu'un événement de hook valide est émis, Logto recherche les webhooks correspondants et envoie une requête POST par configuration de hook.
+Lorsqu'un événement de webhook se déclenche, Logto envoie une requête `POST` à chaque point de terminaison qui y est abonné. Le catalogue complet des événements se trouve dans [Événements de Webhooks](/developers/webhooks/webhooks-events) ; cette page documente la **forme de la requête** que Logto délivre.
## En-têtes de requête \{#request-headers}
-| Clé | Personnalisable | Remarques |
-| ----------------------- | --------------- | --------------------------------------------------------------------------------------------------------- |
-| user-agent | ✅ | `Logto (https://logto.io/)` par défaut. |
-| content-type | ✅ | `application/json` par défaut. |
-| logto-signature-sha-256 | | la signature du corps de la requête, voir [sécuriser vos webhooks](/developers/webhooks/secure-webhooks). |
+| Clé | Personnalisable | Remarques |
+| ----------------------- | --------------- | ------------------------------------------------------------------------------------------------------------ |
+| user-agent | ✅ | `Logto (https://logto.io/)` par défaut. |
+| content-type | ✅ | `application/json` par défaut. |
+| logto-signature-sha-256 | | Signature du corps de la requête. Voir [sécurisation de vos webhooks](/developers/webhooks/secure-webhooks). |
-Vous pouvez écraser les en-têtes personnalisables en [personnalisant les en-têtes de requête](/developers/webhooks/configure-webhooks/#secure-webhook) avec la même clé.
+Les en-têtes personnalisables peuvent être remplacés via la configuration du [webhook sécurisé](/developers/webhooks/configure-webhooks/#secure-webhook).
-## Corps de la requête des événements d'interaction hook \{#interaction-hook-events-request-body}
+## Aperçu du corps de la requête \{#request-body-overview}
-Événements disponibles : `PostRegister`, `PostSignIn`, `PostResetPassword`
+Le corps est un objet JSON. Sa forme exacte dépend de la famille à laquelle appartient l'événement :
-Le corps de la requête est un objet JSON qui contient trois types de champs de données :
+| Famille | Événements | Quand il se déclenche |
+| ----------------------- | -------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
+| **Flux utilisateur** | `PostRegister`, `PostSignIn`, `PostResetPassword` | Un utilisateur termine un flux d'inscription, de connexion ou de réinitialisation de mot de passe géré par l'Experience API. |
+| **Mutation de données** | `User.*`, `Role.*`, `Scope.*`, `Organization.*`, `OrganizationRole.*`, `OrganizationScope.*` | Le modèle de données sous-jacent est modifié — par un appel Management API ou par un flux utilisateur sur l'Experience API. |
+| **Exception** | `Identifier.Lockout` | Un incident de sécurité — par exemple, un compte verrouillé après des tentatives de vérification consécutives échouées. |
+
+Chaque famille partage un petit ensemble de [champs communs](#common-fields). Chaque famille ajoute ensuite ses propres champs de contexte de requête ainsi qu'une charge utile spécifique à l'événement.
+
+### Champs communs \{#common-fields}
+
+Présents dans chaque livraison, quelle que soit la famille :
+
+| Champ | Type | Optionnel | Remarques |
+| --------- | -------- | --------- | ---------------------------------------------------------- |
+| hookId | `string` | | L'identifiant de configuration du webhook dans Logto. |
+| event | `string` | | L'événement qui a déclenché cette livraison. |
+| createdAt | `string` | | L'heure de création de la charge utile au format ISO 8601. |
+| userAgent | `string` | ✅ | L'agent utilisateur de la requête déclenchante. |
+
+Chaque famille inclut également l'adresse IP de la requête déclenchante — sous le nom de champ `userIp` pour les événements de flux utilisateur et `ip` pour les événements de mutation de données et d'exception. Les sémantiques sont identiques ; la différence de nom historique est préservée pour la compatibilité ascendante.
+
+## Charges utiles des événements de flux utilisateur \{#user-flow-event-payloads}
+
+**Événements :** `PostRegister`, `PostSignIn`, `PostResetPassword`.
+
+Déclenché lorsqu'un utilisateur termine un flux d'inscription, de connexion ou de réinitialisation de mot de passe géré par l'Experience API. En plus des [champs communs](#common-fields), le corps contient :
+
+| Champ | Type | Optionnel | Remarques |
+| ---------------- | -------------------------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| interactionEvent | `'SignIn' \| 'Register' \| 'ForgotPassword'` | | Le type d'événement de flux utilisateur. Correspond à `PostSignIn` / `PostRegister` / `PostResetPassword` respectivement. Le nom du champ conserve le nom historique "interaction". |
+| sessionId | `string` | ✅ | L'ID de session (pas l'ID d'interaction) pour cet événement, si applicable. |
+| userIp | `string` | ✅ | L'adresse IP de la requête déclenchante. |
+| userId | `string` | ✅ | L'ID utilisateur associé à cet événement, si applicable. |
+| user | `UserEntity` | ✅ | L'entité utilisateur associée à cet événement, si applicable. |
+| applicationId | `string` | ✅ | L'ID de l'application associée à cet événement, si applicable. |
+| application | `ApplicationEntity` | ✅ | L'entité application associée à cet événement, si applicable. |
+
+#### Formes des entités \{#user-flow-entity-shapes}
```tsx
type UserEntity = {
@@ -60,70 +97,57 @@ type ApplicationEntity = {
};
```
-| Champ | Type | Optionnel | Remarques |
-| ---------------- | ------------------- | --------- | ------------------------------------------------------------------------------ |
-| hookId | `string` | | L'identifiant dans Logto. |
-| event | `string` | | L'événement qui déclenche ce hook. |
-| createdAt | `string` | | La date de création du payload au format ISO. |
-| interactionEvent | `string` | | L'événement d'interaction qui déclenche ce hook. |
-| sessionId | `string` | ✅ | L'ID de session (et non l'ID d'interaction) pour cet événement, si applicable. |
-| userAgent | `string` | ✅ | Le user-agent pour la requête qui déclenche ce hook. |
-| userIp | `string` | ✅ | L'adresse IP pour la requête qui déclenche ce hook. |
-| userId | `string` | ✅ | L'ID utilisateur associé à cet événement, si applicable. |
-| user | `UserEntity` | ✅ | L'entité utilisateur associée à cet événement, si applicable. |
-| applicationId | `string` | ✅ | L'ID d'application associé à cet événement, si applicable. |
-| application | `ApplicationEntity` | ✅ | Les informations de l'application associée à cet événement, si applicable. |
+Voir [Utilisateurs](/user-management/user-data) et [Applications](/integrate-logto/application-data-structure) pour la référence complète des champs.
-Voir la référence [Utilisateurs](/user-management/user-data) et [Applications](/integrate-logto/application-data-structure) pour des explications détaillées des champs.
+## Charges utiles des événements de mutation de données \{#data-mutation-event-payloads}
-## Corps de la requête des événements de mutation de données hook \{#data-mutation-hook-events-request-body}
+**Événements :** chaque événement sous `User.*`, `Role.*`, `Scope.*`, `Organization.*`, `OrganizationRole.*`, `OrganizationScope.*` — voir [Événements de Webhooks → Événements de hook de mutation de données](/developers/webhooks/webhooks-events#data-mutation-hook-events) pour le catalogue complet.
-### Champs standards du corps de la requête \{#standard-request-body-fields}
+Le corps contient toujours :
-| Champ | Type | Optionnel | Remarques |
-| --------- | -------- | --------- | --------------------------------------------- |
-| hookId | `string` | | L'identifiant dans Logto. |
-| event | `string` | | L'événement qui déclenche ce hook. |
-| createdAt | `string` | | La date de création du payload au format ISO. |
-| userAgent | `string` | ✅ | Le user-agent pour la requête. |
-| ip | `string` | ✅ | L'adresse IP pour la requête. |
+- Les [champs communs](#common-fields).
+- Un champ `ip` — l'adresse IP de la requête déclenchante (optionnel, présent lorsqu'elle est connue).
+- Un **contexte API** décrivant comment le changement a été déclenché. Le contexte est l'une des deux variantes selon la source du déclencheur :
+ - [Contexte de l'Experience API](#experience-api-context-fields) — lorsque le changement provient d'un flux orienté utilisateur.
+ - [Contexte de la Management API](#management-api-context-fields) — lorsque le changement provient d'un appel direct à la Management API.
+- Une **charge utile spécifique à l'événement** — l'entité affectée dans `data` et (pour certains événements) des champs supplémentaires au niveau supérieur. Voir [charges utiles de données spécifiques à l'événement](#event-specific-data-payloads).
-### Champs du corps de contexte Interaction API \{#interaction-api-context-body-fields}
+### Champs de contexte de l'Experience API \{#experience-api-context-fields}
-Événements de mutation de données hook déclenchés par des appels API d'interaction utilisateur.
+Présents lorsque le changement a été déclenché par un flux orienté utilisateur sur l'Experience API — par exemple, `User.Created` lors de l'inscription ou `User.Data.Updated` lors des mises à jour de profil.
-Événements disponibles : `User.Created`, `User.Data.Updated`
+| Champ | Type | Optionnel | Remarques |
+| ---------------- | -------------------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------ |
+| interactionEvent | `'SignIn' \| 'Register' \| 'ForgotPassword'` | ✅ | Le type d'événement de flux utilisateur qui a produit le changement. Le nom du champ conserve le nom historique "interaction". |
+| sessionId | `string` | ✅ | L'ID de session (pas l'ID d'interaction) pour cet événement, si applicable. |
+| applicationId | `string` | ✅ | L'ID de l'application, si applicable. |
+| application | `ApplicationEntity` | ✅ | L'entité application, si applicable. |
-| Champ | Type | Optionnel | Remarques |
-| ---------------- | ------------------- | --------- | ------------------------------------------------------------------------------ |
-| interactionEvent | `string` | ✅ | L'événement d'interaction qui déclenche ce hook. |
-| sessionId | `string` | ✅ | L'ID de session (et non l'ID d'interaction) pour cet événement, si applicable. |
-| applicationId | `string` | ✅ | L'ID d'application associé à cet événement, si applicable. |
-| application | `ApplicationEntity` | ✅ | Les informations de l'application associée à cet événement, si applicable. |
+### Champs de contexte de la Management API \{#management-api-context-fields}
-### Champs du corps de contexte Management API \{#management-api-context-body-fields}
+Présents lorsque le changement a été déclenché par un appel à la Management API.
-Événements de mutation de données hook déclenchés par des appels Management API.
+| Champ | Type | Optionnel | Remarques |
+| ------------ | -------- | --------- | ------------------------------------------------------------------------------------------------------------------ |
+| path | `string` | ✅ | Le chemin de l'appel API qui a déclenché ce hook. |
+| method | `string` | ✅ | La méthode HTTP de l'appel API. |
+| status | `number` | ✅ | Le code de statut de la réponse de l'appel API. |
+| params | `object` | ✅ | Les paramètres de chemin koa de l'appel API. |
+| matchedRoute | `string` | ✅ | La route correspondante koa. Logto utilise ce champ pour correspondre aux filtres d'événements de webhook activés. |
-| Champ | Type | Optionnel | Remarques |
-| ------------ | -------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
-| path | `string` | ✅ | Le chemin de l'appel API qui déclenche ce hook. |
-| method | `string` | ✅ | La méthode de l'appel API qui déclenche ce hook. |
-| status | `number` | ✅ | Le code de statut de la réponse de l'appel API qui déclenche ce hook. |
-| params | `object` | ✅ | Les paramètres de chemin koa de la requête de l'appel API qui déclenche ce hook. |
-| matchedRoute | `string` | ✅ | La route koa correspondante de l'appel API qui déclenche ce hook. Logto utilise ce champ pour faire correspondre les événements hook activés. |
+### Charges utiles de données spécifiques à l'événement \{#event-specific-data-payloads}
-### Champs du corps de la charge utile de données \{#data-payload-body-fields}
+Chaque événement de mutation de données inclut un champ `data` au niveau supérieur contenant l'entité affectée, ou `null` lorsque le changement ne peut pas être résumé en une seule entité (événements de suppression et d'appartenance). Certains événements incluent également des champs spécifiques à l'événement au niveau supérieur au-delà de `data` — `Organization.Membership.Updated` est un tel cas, documenté ci-dessous.
-**Événements utilisateur**
+#### Événements utilisateur \{#user-events}
-| Événement | Champ | Type | Optionnel | Remarques |
-| ----------------- | ----- | ---------- | --------- | ---------------------------------------------------- |
-| User.Created | data | UserEntity | | L'entité utilisateur créée pour cet événement. |
-| User.Data.Updated | data | UserEntity | | L'entité utilisateur mise à jour pour cet événement. |
-| User.Deleted | data | null | / | |
+| Événement | Champ | Type | Optionnel | Remarques |
+| ----------------- | ----- | ------------ | --------- | --------------------------------- |
+| User.Created | data | `UserEntity` | | L'entité utilisateur créée. |
+| User.Data.Updated | data | `UserEntity` | | L'entité utilisateur mise à jour. |
+| User.Deleted | data | `null` | / | |
-**Événements Rôle (Role)**
+#### Événements de rôle \{#role-events}
```tsx
type Role = {
@@ -145,23 +169,23 @@ type Scope = {
};
```
-| Événement | Champ | Type | Optionnel | Remarques |
-| ------------------ | ------ | ------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
-| Role.Created | data | Role | | L'entité rôle créée pour cet événement. |
-| Role.Data.Updated | data | Role | | L'entité rôle mise à jour pour cet événement. |
-| Role.Deleted | data | null | | |
-| Role.Scope.Updated | data | Scope[] | | Les portées mises à jour attribuées au rôle. |
-| Role.Scope.Updated | roleId | string | ✅ | L'ID du rôle auquel les portées sont attribuées. (Disponible uniquement lorsque l'événement a été déclenché par la création d'un nouveau rôle avec des portées pré-attribuées) |
+| Événement | Champ | Type | Optionnel | Remarques |
+| ------------------- | ------ | --------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Role.Created | data | `Role` | | L'entité de rôle créée. |
+| Role.Data.Updated | data | `Role` | | L'entité de rôle mise à jour. |
+| Role.Deleted | data | `null` | / | |
+| Role.Scopes.Updated | data | `Scope[]` | | Les portées mises à jour assignées au rôle. |
+| Role.Scopes.Updated | roleId | `string` | ✅ | L'ID du rôle auquel les portées sont assignées. (Disponible uniquement lorsque l'événement a été déclenché par la création d'un rôle avec des portées pré-assignées.) |
-**Événements Permission (Scope)**
+#### Événements de permission (Portée) \{#permission-events}
-| Événement | Champ | Type | Optionnel | Remarques |
-| ------------------ | ----- | ----- | --------- | ----------------------------------------------- |
-| Scope.Created | data | Scope | | L'entité portée créée pour cet événement. |
-| Scope.Data.Updated | data | Scope | | L'entité portée mise à jour pour cet événement. |
-| Scope.Deleted | data | null | / | |
+| Événement | Champ | Type | Optionnel | Remarques |
+| ------------------ | ----- | ------- | --------- | ------------------------------- |
+| Scope.Created | data | `Scope` | | L'entité de portée créée. |
+| Scope.Data.Updated | data | `Scope` | | L'entité de portée mise à jour. |
+| Scope.Deleted | data | `null` | / | |
-**Événements Organisation (Organization)**
+#### Événements d'organisation \{#organization-events}
```tsx
type Organization = {
@@ -173,14 +197,139 @@ type Organization = {
};
```
-| Événement | Champ | Type | Optionnel | Remarques |
-| ------------------------------- | ----- | ------------ | --------- | ----------------------------------------------------- |
-| Organization.Created | data | Organization | | L'entité organisation créée pour cet événement. |
-| Organization.Data.Updated | data | Organization | | L'entité organisation mise à jour pour cet événement. |
-| Organization.Deleted | data | null | / | |
-| Organization.Membership.Updated | data | null | / | |
+| Événement | Champ | Type | Optionnel | Remarques |
+| ------------------------------- | ----- | -------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Organization.Created | data | `Organization` | | L'entité d'organisation créée. |
+| Organization.Data.Updated | data | `Organization` | | L'entité d'organisation mise à jour. |
+| Organization.Deleted | data | `null` | / | |
+| Organization.Membership.Updated | data | `null` | / | Le changement est décrit par des tableaux delta optionnels au niveau supérieur. Voir [Charge utile Organization.Membership.Updated](#organizationmembershipupdated-payload) ci-dessous. |
+
+##### Charge utile Organization.Membership.Updated \{#organizationmembershipupdated-payload}
+
+En plus des [champs communs](#common-fields) et des champs de contexte API correspondant à la source du déclencheur ([contexte Management API](#management-api-context-fields) pour les routes de la Management API, [contexte Experience API](#experience-api-context-fields) pour l'approvisionnement just-in-time), l'événement `Organization.Membership.Updated` transporte un `organizationId` ainsi que des tableaux delta optionnels au niveau supérieur de la charge utile (à côté de `event`, `createdAt`, etc. ; **pas** à l'intérieur de `data`, qui est toujours `null` pour cet événement).
+
+| Champ | Type | Optionnel | Remarques |
+| --------------------- | ---------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| organizationId | `string` | | L'organisation dont l'appartenance a changé. |
+| addedUserIds | `string[]` | ✅ | Les IDs des utilisateurs nouvellement ajoutés par ce déclencheur. Omis lorsqu'aucun utilisateur n'a été ajouté, ou lorsque le déclencheur n'affecte pas l'appartenance des utilisateurs. |
+| removedUserIds | `string[]` | ✅ | Les IDs des utilisateurs supprimés par ce déclencheur. Omis lorsqu'aucun utilisateur n'a été supprimé. |
+| addedApplicationIds | `string[]` | ✅ | Les IDs des applications nouvellement ajoutées. Omis lorsqu'aucune application n'a été ajoutée, ou lorsque le déclencheur n'affecte pas l'appartenance des applications. |
+| removedApplicationIds | `string[]` | ✅ | Les IDs des applications supprimées. Omis lorsqu'aucune application n'a été supprimée. |
+
+Les quatre tableaux delta sont **optionnels et additifs** — ils ne modifient pas la forme de la charge utile existante pour les consommateurs qui ne les attendent pas, et le champ `data: null` hérité est toujours émis inchangé.
+
+###### Déclencheurs et champs delta qu'ils peuvent émettre \{#membership-triggers}
+
+| Déclencheur | Champs delta possibles |
+| -------------------------------------------------------------------------------------------- | ---------------------------------------------- |
+| `POST /organizations/:id/users` | `addedUserIds` |
+| `PUT /organizations/:id/users` | `addedUserIds`, `removedUserIds` |
+| `DELETE /organizations/:id/users/:userId` | `removedUserIds` |
+| `POST /organizations/:id/applications` | `addedApplicationIds` |
+| `PUT /organizations/:id/applications` | `addedApplicationIds`, `removedApplicationIds` |
+| `DELETE /organizations/:id/applications/:applicationId` | `removedApplicationIds` |
+| `PUT /organization-invitations/:id/status` (`Accepted`) | `addedUserIds` |
+| Approvisionnement juste-à-temps lors de l'ajout de l'utilisateur à une nouvelle organisation | `addedUserIds` |
+
+###### Les deltas vides sont omis — absent ≠ changement vide \{#empty-deltas-are-omitted}
+
+Les tableaux delta vides sont **entièrement omis** de la charge utile. Par exemple, un `PUT /organizations/:id/users` qui remplace l'ensemble d'appartenance par l'ensemble existant ne produit aucun changement réel, et la charge utile se réduit à simplement `{ organizationId }` avec les quatre champs delta absents. Il en va de même pour une réintégration d'un membre existant, une réacceptation d'une invitation par un utilisateur qui est déjà membre qui est déjà membre.
+
+**Les consommateurs doivent traiter un champ manquant comme "aucun changement de ce côté", et non comme "un changement vide".**
+
+###### Limite par tableau (troncation silencieuse) \{#membership-delta-cap}
+
+Chaque tableau delta est limité à **5000 entrées**. Lorsqu'un seul appel Management API ajoute ou supprime plus de 5000 utilisateurs (ou applications) en une seule opération, le tableau delta correspondant est silencieusement tronqué à ses 5000 premières entrées — **il n'y a pas de marqueur dans la charge utile** indiquant qu'une limite a été atteinte.
+
+Si votre application effectue des opérations administratives en masse qui peuvent vraisemblablement affecter plus de 5000 membres en un seul appel, traitez un tableau de exactement 5000 entrées comme un signal pour réconcilier l'appartenance autoritaire via la Management API :
+
+- `GET /organizations/:id/users` — appartenance complète des utilisateurs.
+- `GET /organizations/:id/applications` — appartenance complète des applications.
+
+Cela suit le même modèle que l'événement `push` de GitHub, qui limite `commits` à 20 entrées et pointe les consommateurs vers l'API de comparaison pour la liste complète.
+
+###### Ignorer les événements sans effet \{#skipping-no-op-events}
+
+Chaque `PUT` contre les routes d'appartenance émet un événement, qu'il y ait eu un changement ou non — afin que tout appel de remplacement d'état ait au moins une livraison de webhook à des fins d'audit. Pour ignorer les livraisons sans effet du côté consommateur, filtrez sur la présence des tableaux delta :
+
+```ts
+if (
+ payload.addedUserIds?.length ||
+ payload.removedUserIds?.length ||
+ payload.addedApplicationIds?.length ||
+ payload.removedApplicationIds?.length
+) {
+ // changement réel d'appartenance — traitez-le
+}
+```
-**Événements OrganisationRôle (OrganizationRole)**
+`?.length` est faux pour `undefined` et `[]`, donc le même prédicat est robuste que le champ soit absent ou (dans un avenir hypothétique) émis comme un tableau vide.
+
+###### Exemples de charges utiles \{#membership-example-payloads}
+
+**Ajouter un utilisateur (`POST /organizations/:id/users`) :**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "addedUserIds": ["u_001"]
+}
+```
+
+**Remplacer l'ensemble d'appartenance utilisateur (`PUT /organizations/:id/users`) :**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "addedUserIds": ["u_002"],
+ "removedUserIds": ["u_001"]
+}
+```
+
+**Supprimer un utilisateur (`DELETE /organizations/:id/users/:userId`) :**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "removedUserIds": ["u_001"]
+}
+```
+
+**Ajouter une application (`POST /organizations/:id/applications`) :**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "addedApplicationIds": ["app_xyz"]
+}
+```
+
+**Réintégrer un membre existant, `PUT` sans effet, ou réacceptation d'une invitation déjà membre (aucun changement réel) :**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc"
+}
+```
+
+**Opération en masse qui atteint la limite de 5000 (troncation silencieuse) :**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "removedUserIds": ["u_0001", "u_0002", "/* … exactement 5000 entrées au total */"]
+}
+```
+
+Voir un tableau de exactement 5000 entrées devrait inciter à un `GET /organizations/:id/users` de réconciliation (ou `/applications`).
+
+#### Événements de rôle d'organisation \{#organization-role-events}
```tsx
type OrganizationRole = {
@@ -198,27 +347,32 @@ type OrganizationScope = {
};
```
-| Événement | Champ | Type | Optionnel | Remarques |
-| ------------------------------ | ------------------ | ---------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
-| OrganizationRole.Created | data | OrganizationRole | | L'entité rôle d'organisation créée pour cet événement. |
-| OrganizationRole.Data.Updated | data | OrganizationRole | | L'entité rôle d'organisation mise à jour pour cet événement. |
-| OrganizationRole.Deleted | data | null | / | |
-| OrganizationRole.Scope.Updated | data | null | / | |
-| OrganizationRole.Scope.Updated | organizationRoleId | string | ✅ | L'ID du rôle auquel les portées sont attribuées. (Disponible uniquement lorsque l'événement a été déclenché par la création d'un nouveau rôle avec des portées pré-attribuées) |
+| Événement | Champ | Type | Optionnel | Remarques |
+| ------------------------------- | ------------------ | ------------------ | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| OrganizationRole.Created | data | `OrganizationRole` | | L'entité de rôle d'organisation créée. |
+| OrganizationRole.Data.Updated | data | `OrganizationRole` | | L'entité de rôle d'organisation mise à jour. |
+| OrganizationRole.Deleted | data | `null` | / | |
+| OrganizationRole.Scopes.Updated | data | `null` | / | |
+| OrganizationRole.Scopes.Updated | organizationRoleId | `string` | ✅ | L'ID du rôle auquel les portées sont assignées. (Disponible uniquement lorsque l'événement a été déclenché par la création d'un rôle avec des portées pré-assignées.) |
+
+#### Événements de permission d'organisation (portée) \{#organization-permission-events}
-**Événements Permission d'organisation (OrganizationScope)**
+| Événement | Champ | Type | Optionnel | Remarques |
+| ------------------------------ | ----- | ------------------- | --------- | ---------------------------------------------- |
+| OrganizationScope.Created | data | `OrganizationScope` | | L'entité de portée d'organisation créée. |
+| OrganizationScope.Data.Updated | data | `OrganizationScope` | | L'entité de portée d'organisation mise à jour. |
+| OrganizationScope.Deleted | data | `null` | / | |
-| Événement | Champ | Type | Optionnel | Remarques |
-| ------------------------------ | ----- | ----------------- | --------- | ------------------------------------------- |
-| OrganizationScope.Created | data | OrganizationScope | | L'entité portée d'organisation créée. |
-| OrganizationScope.Data.Updated | data | OrganizationScope | | L'entité portée d'organisation mise à jour. |
-| OrganizationScope.Deleted | data | null | / | |
+## Charges utiles des événements d'exception \{#exception-event-payloads}
-## Corps de la requête des événements d'exception hook \{#exception-hook-events-request-body}
+**Événements :** `Identifier.Lockout`.
-Événements disponibles : `Identifier.Lockout`
+Déclenché lors d'incidents de sécurité — par exemple, un compte verrouillé après des tentatives de vérification consécutives échouées. Ces événements proviennent toujours d'un flux orienté utilisateur, donc le corps contient :
-Le corps de la requête est un objet JSON qui contient les champs standards du corps de la requête et des champs additionnels comme ci-dessous :
+- Les [champs communs](#common-fields).
+- Le champ `ip` (même forme que les événements de mutation de données).
+- Les [champs de contexte de l'Experience API](#experience-api-context-fields).
+- Les champs spécifiques à l'exception ci-dessous.
```tsx
enum SignInIdentifier {
@@ -228,16 +382,7 @@ enum SignInIdentifier {
}
```
-| Champ | Type | Optionnel | Remarques |
-| ---------------- | ------------------- | --------- | ------------------------------------------------------------------------------ |
-| hookId | `string` | | L'identifiant dans Logto. |
-| event | `string` | | L'événement qui déclenche ce hook. |
-| createdAt | `string` | | La date de création du payload au format ISO. |
-| userAgent | `string` | ✅ | Le user-agent pour la requête. |
-| ip | `string` | ✅ | L'adresse IP pour la requête. |
-| interactionEvent | `string` | ✅ | L'événement d'interaction qui déclenche ce hook. |
-| sessionId | `string` | ✅ | L'ID de session (et non l'ID d'interaction) pour cet événement, si applicable. |
-| applicationId | `string` | ✅ | L'ID d'application associé à cet événement, si applicable. |
-| application | `ApplicationEntity` | ✅ | Les informations de l'application associée à cet événement, si applicable. |
-| type | `SignInIdentifier` | | Le type d'identifiant utilisateur, ex : email, téléphone ou nom d'utilisateur. |
-| value | `string` | | La valeur de l'identifiant utilisateur qui a déclenché le verrouillage. |
+| Champ | Type | Optionnel | Remarques |
+| ----- | ------------------ | --------- | ------------------------------------------------------------------------------------------- |
+| type | `SignInIdentifier` | | Le type d'identifiant de l'utilisateur, par exemple, email, téléphone ou nom d'utilisateur. |
+| value | `string` | | La valeur de l'identifiant de l'utilisateur qui a déclenché le verrouillage. |
diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx b/i18n/ja/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx
index a078d59696e..d7eaf37edff 100644
--- a/i18n/ja/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx
+++ b/i18n/ja/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx
@@ -7,69 +7,69 @@ sidebar_position: 3
# Webhooks イベント
-このガイドでは、Logto のさまざまな Webhook イベントと、それぞれのイベントが発生するタイミングについて説明します。
+このガイドでは、Logto のさまざまな webhook イベントを一覧にし、各イベントが発生するタイミングを説明します。
## ユーザーインタラクションフックイベント \{#user-interaction-hook-events}
-| イベントタイプ | 説明 |
-| ----------------- | ------------------------------------------------------------------------------------------ |
-| PostRegister | ユーザーが UI インターフェースを通じて新しいアカウントを正常に作成したときに発生します。 |
-| PostSignIn | ユーザーが UI インターフェースを通じて正常にサインインしたときに発生します。 |
-| PostResetPassword | 「パスワードを忘れた」フローでユーザーのパスワードが正常にリセットされたときに発生します。 |
+| イベントタイプ | 説明 |
+| ----------------- | ---------------------------------------------------------------------------------- |
+| PostRegister | ユーザーが UI インターフェースを通じて新しいアカウントを正常に作成します。 |
+| PostSignIn | ユーザーが UI インターフェースを通じて正常にサインインします。 |
+| PostResetPassword | ユーザーのパスワードが「パスワードを忘れた」フローを通じて正常にリセットされます。 |
## データ変更フックイベント \{#data-mutation-hook-events}
### ユーザー \{#user}
-| イベントタイプ | 説明 |
-| ----------------------------- | ------------------------------------------------------------------------------------------------------------------- |
-| User.Created | 新しいユーザーアカウントが作成されたときに発生します。 |
-| User.Deleted | ユーザーアカウントが削除されたときに発生します。 |
-| User.Data.Updated | ユーザープロファイルデータが更新されたときに発生します(例:メール、アバター、custom.data、ソーシャル識別子など)。 |
-| User.SuspensionStatus.Updated | ユーザーの停止ステータスが変更されたとき(停止または再有効化)に発生します。 |
+| イベントタイプ | 説明 |
+| ----------------------------- | --------------------------------------------------------------------------------------------------- |
+| User.Created | 新しいユーザーアカウントが作成されます。 |
+| User.Deleted | ユーザーアカウントが削除されます。 |
+| User.Data.Updated | ユーザープロフィールデータが更新されます。例:メール、アバター、custom.data、ソーシャル識別子など。 |
+| User.SuspensionStatus.Updated | ユーザーの停止ステータスが変更されます(停止または再有効化)。 |
-### ロール (Role) \{#role}
+### ロール \{#role}
-| イベントタイプ | 説明 |
-| ------------------- | ---------------------------------------------------------------------------------------------- |
-| Role.Created | 新しいロールが作成されたときに発生します。 |
-| Role.Deleted | ロールが削除されたときに発生します。 |
-| Role.Data.Updated | ロールのデータが更新されたときに発生します(例:ロール名、説明、デフォルトロールステータス)。 |
-| Role.Scopes.Updated | ロールに割り当てられた権限が追加または削除されたときに発生します。 |
+| イベントタイプ | 説明 |
+| ------------------- | ------------------------------------------------------------------------------ |
+| Role.Created | 新しいロールが作成されます。 |
+| Role.Deleted | ロールが削除されます。 |
+| Role.Data.Updated | ロールのデータが更新されます。例:ロール名、説明、デフォルトロールステータス。 |
+| Role.Scopes.Updated | ロールに割り当てられた権限が追加または削除されます。 |
### 権限 (スコープ) \{#permission-scope}
-| イベントタイプ | 説明 |
-| ------------------ | ---------------------------------------------------------------- |
-| Scope.Created | 新しい API 権限が作成されたときに発生します。 |
-| Scope.Deleted | API 権限が削除されたときに発生します。 |
-| Scope.Data.Updated | API 権限のデータが更新されたときに発生します(例:権限の説明)。 |
+| イベントタイプ | 説明 |
+| ------------------ | ------------------------------------------------ |
+| Scope.Created | 新しい API 権限が作成されます。 |
+| Scope.Deleted | API 権限が削除されます。 |
+| Scope.Data.Updated | API 権限のデータが更新されます。例:権限の説明。 |
-### 組織 (Organization) \{#organization}
+### 組織 \{#organization}
-| イベントタイプ | 説明 |
-| ------------------------------- | -------------------------------------------------------------------------------- |
-| Organization.Created | 新しい組織が作成されたときに発生します。 |
-| Organization.Deleted | 組織が削除されたときに発生します。 |
-| Organization.Data.Updated | 組織のデータが更新されたときに発生します(例:組織名、説明、custom.data など)。 |
-| Organization.Membership.Updated | 組織にメンバーが追加または削除されたときに発生します。 |
+| イベントタイプ | 説明 |
+| ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Organization.Created | 新しい組織が作成されます。 |
+| Organization.Deleted | 組織が削除されます。 |
+| Organization.Data.Updated | 組織のデータが更新されます。例:組織名、説明、custom.data など。 |
+| Organization.Membership.Updated | ユーザーまたはアプリケーションが組織に追加または削除されます。ペイロードには [メンバーシップデルタフィールド](/developers/webhooks/webhooks-request#organizationmembershipupdated-payload) が含まれます。 |
-### 組織ロール (Organization role) \{#organization-role}
+### 組織ロール \{#organization-role}
-| イベントタイプ | 説明 |
-| ------------------------------- | -------------------------------------------------------------------------- |
-| OrganizationRole.Created | 新しい組織ロールが作成されたときに発生します。 |
-| OrganizationRole.Deleted | 組織ロールが削除されたときに発生します。 |
-| OrganizationRole.Data.Updated | 組織ロールのデータが更新されたときに発生します(例:組織ロール名や説明)。 |
-| OrganizationRole.Scopes.Updated | 組織ロールに割り当てられた権限が追加または削除されたときに発生します。 |
+| イベントタイプ | 説明 |
+| ------------------------------- | ---------------------------------------------------------- |
+| OrganizationRole.Created | 新しい組織ロールが作成されます。 |
+| OrganizationRole.Deleted | 組織ロールが削除されます。 |
+| OrganizationRole.Data.Updated | 組織ロールのデータが更新されます。例:組織ロール名と説明。 |
+| OrganizationRole.Scopes.Updated | 組織ロールに割り当てられた権限が追加または削除されます。 |
### 組織権限 (スコープ) \{#organization-permission-scope}
-| イベントタイプ | 説明 |
-| ------------------------------ | -------------------------------------------------------------------- |
-| OrganizationScope.Created | 新しい組織権限が作成されたときに発生します。 |
-| OrganizationScope.Deleted | 組織権限が削除されたときに発生します。 |
-| OrganizationScope.Data.Updated | 組織権限のデータが更新されたときに発生します(例:組織権限の説明)。 |
+| イベントタイプ | 説明 |
+| ------------------------------ | ---------------------------------------------------- |
+| OrganizationScope.Created | 新しい組織権限が作成されます。 |
+| OrganizationScope.Deleted | 組織権限が削除されます。 |
+| OrganizationScope.Data.Updated | 組織権限のデータが更新されます。例:組織権限の説明。 |
### Management API トリガーイベント \{#management-api-triggered-events}
@@ -96,6 +96,10 @@ sidebar_position: 3
| PUT /organizations/:id/users | Organization.Membership.Updated |
| POST /organizations/:id/users | Organization.Membership.Updated |
| DELETE /organizations/:id/users/:userId | Organization.Membership.Updated |
+| PUT /organizations/:id/applications | Organization.Membership.Updated |
+| POST /organizations/:id/applications | Organization.Membership.Updated |
+| DELETE /organizations/:id/applications/:applicationId | Organization.Membership.Updated |
+| PUT /organization-invitations/:id/status (Accepted) | Organization.Membership.Updated |
| POST /organization-roles | OrganizationRole.Created, (OrganizationRole.Scopes.Updated) |
| DELETE /organization-roles/:id | OrganizationRole.Deleted |
| PATCH /organization-roles/:id | OrganizationRole.Data.Updated |
@@ -108,21 +112,22 @@ sidebar_position: 3
### Experience API トリガーイベント \{#experience-api-triggered-events}
-| ユーザーインタラクションアクション | イベント |
-| ---------------------------------- | ----------------- |
-| ユーザーのメール/電話の連携 | User.Data.Updated |
-| ユーザーの MFA 連携 | User.Data.Updated |
-| ユーザーのソーシャル/SSO 連携 | User.Data.Updated |
-| ユーザーのパスワードリセット | User.Data.Updated |
-| ユーザー登録 | User.Created |
+| ユーザーインタラクションアクション | イベント |
+| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- |
+| ユーザーのメール / 電話のリンク | User.Data.Updated |
+| ユーザーの MFA のリンク | User.Data.Updated |
+| ユーザーのソーシャル / SSO のリンク | User.Data.Updated |
+| ユーザーのパスワードリセット | User.Data.Updated |
+| ユーザー登録 | User.Created |
+| [ジャストインタイムプロビジョニング](/organizations/just-in-time-provisioning) を通じて組織に自動プロビジョニングされたユーザー (メールドメインまたはエンタープライズ SSO コネクターの一致) | Organization.Membership.Updated |
## 例外フックイベント \{#exception-hook-events}
### セキュリティ \{#security}
-| イベントタイプ | 説明 |
-| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| Identifier.Lockout | 連続したアイデンティティ確認失敗によりユーザーアカウントがロックされたときに発生します。次のフローでトリガーされる可能性があります:
- パスワード認証失敗
- コード認証失敗
- ワンタイムトークン認証失敗
|
+| イベントタイプ | 説明 |
+| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Identifier.Lockout | ユーザーアカウントが連続したアイデンティティ検証失敗の試行によりロックされます。次のフローでトリガーされる可能性があります:
- パスワード検証失敗
- コード検証失敗
- ワンタイムトークン検証失敗
|
## よくある質問 \{#faqs}
diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx b/i18n/ja/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx
index cb3869bed3c..a5e338f7bc4 100644
--- a/i18n/ja/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx
+++ b/i18n/ja/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx
@@ -7,23 +7,60 @@ sidebar_position: 4
# Webhooks リクエスト
-有効なフックイベントが発生すると、Logto は対応する Webhook を検索し、各フック設定ごとに POST リクエストを送信します。
+Webhook イベントが発生すると、Logto はそれに登録されたすべてのエンドポイントに `POST` リクエストを送信します。完全なイベントカタログは [Webhooks イベント](/developers/webhooks/webhooks-events) にあります。このページでは、Logto が配信するリクエストの**形状**を記載しています。
## リクエストヘッダー \{#request-headers}
| Key | カスタマイズ可 | 備考 |
| ----------------------- | -------------- | ---------------------------------------------------------------------------------------------------------------- |
-| user-agent | ✅ | デフォルトは `Logto (https://logto.io/)` です。 |
-| content-type | ✅ | デフォルトは `application/json` です。 |
-| logto-signature-sha-256 | | リクエストボディの署名。 [Webhook のセキュリティ保護](/developers/webhooks/secure-webhooks) を参照してください。 |
+| user-agent | ✅ | デフォルトでは `Logto (https://logto.io/)`。 |
+| content-type | ✅ | デフォルトでは `application/json`。 |
+| logto-signature-sha-256 | | リクエストボディの署名。[Webhooks のセキュリティ確保](/developers/webhooks/secure-webhooks) を参照してください。 |
-カスタマイズ可能なヘッダーは、同じキーで [リクエストヘッダーのカスタマイズ](/developers/webhooks/configure-webhooks/#secure-webhook) により上書きできます。
+カスタマイズ可能なヘッダーは、[セキュア Webhook](/developers/webhooks/configure-webhooks/#secure-webhook) 設定を通じて上書きできます。
-## インタラクションフックイベントのリクエストボディ \{#interaction-hook-events-request-body}
+## リクエストボディの概要 \{#request-body-overview}
-利用可能なイベント: `PostRegister`, `PostSignIn`, `PostResetPassword`
+ボディは JSON オブジェクトです。その正確な形状は、イベントが属するファミリーによって異なります:
-リクエストボディは、3 種類のデータフィールドを含む JSON オブジェクトです:
+| ファミリー | イベント | 発生タイミング |
+| ------------------ | -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
+| **ユーザーフロー** | `PostRegister`, `PostSignIn`, `PostResetPassword` | ユーザーが Experience API によって処理されるサインアップ、サインイン、またはパスワードリセットフローを完了したとき。 |
+| **データ変更** | `User.*`, `Role.*`, `Scope.*`, `Organization.*`, `OrganizationRole.*`, `OrganizationScope.*` | 基本データモデルが変更されたとき — Management API コールまたは Experience API 上のユーザーフローによって。 |
+| **例外** | `Identifier.Lockout` | セキュリティインシデント — 例えば、連続した認証失敗後にアカウントがロックされた場合。 |
+
+すべてのファミリーは、[共通フィールド](#common-fields) の小さなセットを共有しています。各ファミリーはその後、独自のリクエストコンテキストフィールドとイベント固有のペイロードを追加します。
+
+### 共通フィールド \{#common-fields}
+
+ファミリーに関係なく、すべての配信に含まれます:
+
+| フィールド | タイプ | オプション | 備考 |
+| ---------- | -------- | ---------- | ------------------------------------------ |
+| hookId | `string` | | Logto 内の Webhook 設定識別子。 |
+| event | `string` | | この配信をトリガーしたイベント。 |
+| createdAt | `string` | | ISO 8601 形式のペイロード作成時間。 |
+| userAgent | `string` | ✅ | トリガーリクエストのユーザーエージェント。 |
+
+各ファミリーには、トリガーリクエストの IP アドレスも含まれています — ユーザーフローイベントでは `userIp` フィールド、データ変更および例外イベントでは `ip` フィールドとして。意味は同じですが、後方互換性のために歴史的な名前の違いが保持されています。
+
+## ユーザーフローイベントペイロード \{#user-flow-event-payloads}
+
+**イベント:** `PostRegister`, `PostSignIn`, `PostResetPassword`.
+
+ユーザーが Experience API によって処理されるサインアップ、サインイン、またはパスワードリセットフローを完了したときに発生します。[共通フィールド](#common-fields) に加えて、ボディには以下が含まれます:
+
+| フィールド | タイプ | オプション | 備考 |
+| ---------------- | -------------------------------------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| interactionEvent | `'SignIn' \| 'Register' \| 'ForgotPassword'` | | ユーザーフローイベントタイプ。`PostSignIn` / `PostRegister` / `PostResetPassword` にそれぞれマッピングされます。フィールド名は歴史的な「インタラクション」命名を保持しています。 |
+| sessionId | `string` | ✅ | このイベントのセッション ID(インタラクション ID ではありません)、該当する場合。 |
+| userIp | `string` | ✅ | トリガーリクエストの IP アドレス。 |
+| userId | `string` | ✅ | このイベントに関連付けられたユーザー ID、該当する場合。 |
+| user | `UserEntity` | ✅ | このイベントに関連付けられたユーザーエンティティ、該当する場合。 |
+| applicationId | `string` | ✅ | このイベントに関連付けられたアプリケーション ID、該当する場合。 |
+| application | `ApplicationEntity` | ✅ | このイベントに関連付けられたアプリケーションエンティティ、該当する場合。 |
+
+#### エンティティの形状 \{#user-flow-entity-shapes}
```tsx
type UserEntity = {
@@ -60,70 +97,57 @@ type ApplicationEntity = {
};
```
-| フィールド | 型 | オプション | 備考 |
-| ---------------- | ------------------- | ---------- | ------------------------------------------------------------------- |
-| hookId | `string` | | Logto 内の識別子。 |
-| event | `string` | | このフックをトリガーしたイベント。 |
-| createdAt | `string` | | ペイロードの作成時刻(ISO 形式)。 |
-| interactionEvent | `string` | | このフックをトリガーしたインタラクションイベント。 |
-| sessionId | `string` | ✅ | このイベントのセッション ID(インタラクション ID ではありません)。 |
-| userAgent | `string` | ✅ | このフックをトリガーしたリクエストのユーザーエージェント。 |
-| userIp | `string` | ✅ | このフックをトリガーしたリクエストの IP アドレス。 |
-| userId | `string` | ✅ | このイベントに関連するユーザー ID。 |
-| user | `UserEntity` | ✅ | このイベントに関連するユーザーエンティティ。 |
-| applicationId | `string` | ✅ | このイベントに関連するアプリケーション ID。 |
-| application | `ApplicationEntity` | ✅ | このイベントに関連するアプリケーション情報。 |
+完全なフィールドリファレンスについては、[ユーザー](/user-management/user-data) および [アプリケーション](/integrate-logto/application-data-structure) を参照してください。
-各フィールドの詳細な説明は [ユーザー](/user-management/user-data) および [アプリケーション](/integrate-logto/application-data-structure) リファレンスを参照してください。
+## データ変更イベントペイロード \{#data-mutation-event-payloads}
-## データ変更フックイベントのリクエストボディ \{#data-mutation-hook-events-request-body}
+**イベント:** `User.*`, `Role.*`, `Scope.*`, `Organization.*`, `OrganizationRole.*`, `OrganizationScope.*` — 完全なカタログについては [Webhooks イベント → データ変更フックイベント](/developers/webhooks/webhooks-events#data-mutation-hook-events) を参照してください。
-### 標準リクエストボディフィールド \{#standard-request-body-fields}
+ボディには常に以下が含まれます:
-| フィールド | 型 | オプション | 備考 |
-| ---------- | -------- | ---------- | ---------------------------------- |
-| hookId | `string` | | Logto 内の識別子。 |
-| event | `string` | | このフックをトリガーしたイベント。 |
-| createdAt | `string` | | ペイロードの作成時刻(ISO 形式)。 |
-| userAgent | `string` | ✅ | リクエストのユーザーエージェント。 |
-| ip | `string` | ✅ | リクエストの IP アドレス。 |
+- [共通フィールド](#common-fields)。
+- `ip` フィールド — トリガーリクエストの IP アドレス(オプション、既知の場合に存在)。
+- 変更がどのようにトリガーされたかを説明する **API コンテキスト**。コンテキストは、トリガーソースに応じて 2 つのバリアントのいずれかです:
+ - [Experience API コンテキスト](#experience-api-context-fields) — 変更がユーザー向けフローから発生した場合。
+ - [Management API コンテキスト](#management-api-context-fields) — 変更が直接の Management API コールから発生した場合。
+- **イベント固有のペイロード** — `data` 内の影響を受けたエンティティと(いくつかのイベントでは)追加のトップレベルフィールド。詳細は [イベント固有のデータペイロード](#event-specific-data-payloads) を参照してください。
-### インタラクション API コンテキストボディフィールド \{#interaction-api-context-body-fields}
+### Experience API コンテキストフィールド \{#experience-api-context-fields}
-ユーザーのインタラクション API コールによってトリガーされるデータ変更フックイベント。
+変更が Experience API 上のユーザー向けフローによってトリガーされた場合に存在します — 例えば、サインアップ中の `User.Created` やプロフィール更新中の `User.Data.Updated`。
-利用可能なイベント: `User.Created`, `User.Data.Updated`
+| フィールド | タイプ | オプション | 備考 |
+| ---------------- | -------------------------------------------- | ---------- | ---------------------------------------------------------------------------------------------------------------- |
+| interactionEvent | `'SignIn' \| 'Register' \| 'ForgotPassword'` | ✅ | 変更を引き起こしたユーザーフローイベントタイプ。フィールド名は歴史的な「インタラクション」命名を保持しています。 |
+| sessionId | `string` | ✅ | このイベントのセッション ID(インタラクション ID ではありません)、該当する場合。 |
+| applicationId | `string` | ✅ | アプリケーション ID、該当する場合。 |
+| application | `ApplicationEntity` | ✅ | アプリケーションエンティティ、該当する場合。 |
-| フィールド | 型 | オプション | 備考 |
-| ---------------- | ------------------- | ---------- | ------------------------------------------------------------------- |
-| interactionEvent | `string` | ✅ | このフックをトリガーしたインタラクションイベント。 |
-| sessionId | `string` | ✅ | このイベントのセッション ID(インタラクション ID ではありません)。 |
-| applicationId | `string` | ✅ | このイベントに関連するアプリケーション ID。 |
-| application | `ApplicationEntity` | ✅ | このイベントに関連するアプリケーション情報。 |
+### Management API コンテキストフィールド \{#management-api-context-fields}
-### Management API コンテキストボディフィールド \{#management-api-context-body-fields}
+変更が Management API コールによってトリガーされた場合に存在します。
-Management API コールによってトリガーされるデータ変更フックイベント。
+| フィールド | タイプ | オプション | 備考 |
+| ------------ | -------- | ---------- | ------------------------------------------------------------------------------------------------------- |
+| path | `string` | ✅ | このフックをトリガーした API コールのパス。 |
+| method | `string` | ✅ | API コールの HTTP メソッド。 |
+| status | `number` | ✅ | API コールのレスポンスステータスコード。 |
+| params | `object` | ✅ | API コールの koa パスパラメータ。 |
+| matchedRoute | `string` | ✅ | koa の一致したルート。Logto はこのフィールドを使用して有効な Webhook イベントフィルターを一致させます。 |
-| フィールド | 型 | オプション | 備考 |
-| ------------ | -------- | ---------- | ------------------------------------------------------------------------------------------------------------------ |
-| path | `string` | ✅ | このフックをトリガーした API コールのパス。 |
-| method | `string` | ✅ | このフックをトリガーした API コールのメソッド。 |
-| status | `number` | ✅ | このフックをトリガーした API コールのレスポンスステータスコード。 |
-| params | `object` | ✅ | このフックをトリガーした API コールの koa パスパラメータ。 |
-| matchedRoute | `string` | ✅ | このフックをトリガーした API コールの koa マッチルート。Logto はこのフィールドで有効なフックイベントを判定します。 |
+### イベント固有のデータペイロード \{#event-specific-data-payloads}
-### データペイロードボディフィールド \{#data-payload-body-fields}
+すべてのデータ変更イベントには、影響を受けたエンティティを含むトップレベルの `data` フィールドが含まれています。変更が単一のエンティティとして要約できない場合(削除およびメンバーシップイベント)、`null` になります。いくつかのイベントには、`data` 以外のイベント固有のトップレベルフィールドも含まれています — `Organization.Membership.Updated` がその一例で、以下に記載されています。
-**ユーザーイベント**
+#### ユーザーイベント \{#user-events}
-| イベント | フィールド | 型 | オプション | 備考 |
-| ----------------- | ---------- | ---------- | ---------- | -------------------------------------- |
-| User.Created | data | UserEntity | | このイベントで作成されたユーザー情報。 |
-| User.Data.Updated | data | UserEntity | | このイベントで更新されたユーザー情報。 |
-| User.Deleted | data | null | / | |
+| イベント | フィールド | タイプ | オプション | 備考 |
+| ----------------- | ---------- | ------------ | ---------- | -------------------------------- |
+| User.Created | data | `UserEntity` | | 作成されたユーザーエンティティ。 |
+| User.Data.Updated | data | `UserEntity` | | 更新されたユーザーエンティティ。 |
+| User.Deleted | data | `null` | / | |
-**ロールイベント**
+#### ロールイベント \{#role-events}
```tsx
type Role = {
@@ -145,23 +169,23 @@ type Scope = {
};
```
-| イベント | フィールド | 型 | オプション | 備考 |
-| ------------------ | ---------- | ------- | ---------- | ------------------------------------------------------------------------------------------- |
-| Role.Created | data | Role | | このイベントで作成されたロール情報。 |
-| Role.Data.Updated | data | Role | | このイベントで更新されたロール情報。 |
-| Role.Deleted | data | null | | |
-| Role.Scope.Updated | data | Scope[] | | ロールに割り当てられた更新済みスコープ。 |
-| Role.Scope.Updated | roleId | string | ✅ | スコープが割り当てられたロール ID。(事前割り当てスコープ付き新規ロール作成時のみ利用可能) |
+| イベント | フィールド | タイプ | オプション | 備考 |
+| ------------------- | ---------- | --------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
+| Role.Created | data | `Role` | | 作成されたロールエンティティ。 |
+| Role.Data.Updated | data | `Role` | | 更新されたロールエンティティ。 |
+| Role.Deleted | data | `null` | / | |
+| Role.Scopes.Updated | data | `Scope[]` | | ロールに割り当てられた更新されたスコープ。 |
+| Role.Scopes.Updated | roleId | `string` | ✅ | スコープが割り当てられたロール ID。(事前に割り当てられたスコープを持つロールの作成によってイベントがトリガーされた場合にのみ利用可能。) |
-**権限(スコープ)イベント**
+#### 権限 (スコープ) イベント \{#permission-events}
-| イベント | フィールド | 型 | オプション | 備考 |
-| ------------------ | ---------- | ----- | ---------- | -------------------------------------- |
-| Scope.Created | data | Scope | | このイベントで作成されたスコープ情報。 |
-| Scope.Data.Updated | data | Scope | | このイベントで更新されたスコープ情報。 |
-| Scope.Deleted | data | null | / | |
+| イベント | フィールド | タイプ | オプション | 備考 |
+| ------------------ | ---------- | ------- | ---------- | -------------------------------- |
+| Scope.Created | data | `Scope` | | 作成されたスコープエンティティ。 |
+| Scope.Data.Updated | data | `Scope` | | 更新されたスコープエンティティ。 |
+| Scope.Deleted | data | `null` | / | |
-**組織イベント**
+#### 組織イベント \{#organization-events}
```tsx
type Organization = {
@@ -173,14 +197,139 @@ type Organization = {
};
```
-| イベント | フィールド | 型 | オプション | 備考 |
-| ------------------------------- | ---------- | ------------ | ---------- | ---------------------------------- |
-| Organization.Created | data | Organization | | このイベントで作成された組織情報。 |
-| Organization.Data.Updated | data | Organization | | このイベントで更新された組織情報。 |
-| Organization.Deleted | data | null | / | |
-| Organization.Membership.Updated | data | null | / | |
+| イベント | フィールド | タイプ | オプション | 備考 |
+| ------------------------------- | ---------- | -------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Organization.Created | data | `Organization` | | 作成された組織エンティティ。 |
+| Organization.Data.Updated | data | `Organization` | | 更新された組織エンティティ。 |
+| Organization.Deleted | data | `null` | / | |
+| Organization.Membership.Updated | data | `null` | / | 変更はオプションのトップレベルのデルタ配列によって説明されます。詳細は [Organization.Membership.Updated ペイロード](#organizationmembershipupdated-payload) を参照してください。 |
+
+##### Organization.Membership.Updated ペイロード \{#organizationmembershipupdated-payload}
+
+[共通フィールド](#common-fields)と、トリガーソースに応じた API コンテキストフィールド(Management API ルートの場合は [Management API コンテキスト](#management-api-context-fields)、ジャストインタイムプロビジョニングの場合は [Experience API コンテキスト](#experience-api-context-fields))に加えて、`Organization.Membership.Updated` イベントは `organizationId` とペイロードのトップレベルにオプションのデルタ配列を持ちます(`event`、`createdAt` などの隣に。このイベントでは常に `null` である `data` 内ではありません)。
+
+| フィールド | タイプ | オプション | 備考 |
+| --------------------- | ---------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| organizationId | `string` | | メンバーシップが変更された組織。 |
+| addedUserIds | `string[]` | ✅ | このトリガーによって新たに追加されたユーザー ID。ユーザーが追加されなかった場合、またはトリガーがユーザーメンバーシップに影響を与えない場合は省略されます。 |
+| removedUserIds | `string[]` | ✅ | このトリガーによって削除されたユーザー ID。削除されたユーザーがいない場合は省略されます。 |
+| addedApplicationIds | `string[]` | ✅ | 新たに追加されたアプリケーション ID。アプリケーションが追加されなかった場合、またはトリガーがアプリケーションメンバーシップに影響を与えない場合は省略されます。 |
+| removedApplicationIds | `string[]` | ✅ | 削除されたアプリケーション ID。削除されたアプリケーションがいない場合は省略されます。 |
+
+4 つのデルタ配列は **オプションで追加的** です — それらを期待しない消費者に対して既存のペイロード形状を変更せず、レガシーの `data: null` フィールドは変更されずに出力されます。
+
+###### トリガーとそれらが発行する可能性のあるデルタフィールド \{#membership-triggers}
+
+| トリガー | 可能なデルタフィールド |
+| -------------------------------------------------------------------- | ---------------------------------------------- |
+| `POST /organizations/:id/users` | `addedUserIds` |
+| `PUT /organizations/:id/users` | `addedUserIds`, `removedUserIds` |
+| `DELETE /organizations/:id/users/:userId` | `removedUserIds` |
+| `POST /organizations/:id/applications` | `addedApplicationIds` |
+| `PUT /organizations/:id/applications` | `addedApplicationIds`, `removedApplicationIds` |
+| `DELETE /organizations/:id/applications/:applicationId` | `removedApplicationIds` |
+| `PUT /organization-invitations/:id/status` (`Accepted`) | `addedUserIds` |
+| ユーザーを新しい組織に追加する際のジャストインタイムプロビジョニング | `addedUserIds` |
+
+###### 空のデルタは省略されます — 不在 ≠ 空の変更 \{#empty-deltas-are-omitted}
+
+空のデルタ配列はペイロードから **完全に省略されます**。例えば、既存のセットでメンバーシップセットを置き換える `PUT /organizations/:id/users` は実際の変更を生じず、ペイロードは `organizationId` のみを持ち、4 つのデルタフィールドはすべて不在です。同様に、既存メンバーの再追加、すでにメンバーであるユーザーによる招待の再受諾も同様です。
+
+**消費者は、欠落しているフィールドを「その側に変更なし」として扱い、「空の変更」として扱わないようにしなければなりません。**
+
+###### 配列ごとの上限(静かに切り捨て) \{#membership-delta-cap}
+
+各デルタ配列は **5000 エントリ** に制限されています。単一の Management API コールが 1 回の操作で 5000 人以上のユーザー(またはアプリケーション)に影響を与える場合、対応するデルタ配列は最初の 5000 エントリに静かに切り捨てられます — **上限が発動したことを示すペイロード内のマーカーはありません**。
+
+管理上の一括操作が 1 回のコールで 5000 人以上のメンバーに影響を与える可能性がある場合、5000 エントリちょうどの配列を見たら、Management API を介して権威あるメンバーシップを調整する信号として扱います:
+
+- `GET /organizations/:id/users` — 完全なユーザーメンバーシップ。
+- `GET /organizations/:id/applications` — 完全なアプリケーションメンバーシップ。
+
+これは、GitHub の `push` イベントと同じパターンに従っており、`commits` を 20 エントリに制限し、消費者に完全なリストのために比較 API を指示します。
+
+###### 無操作イベントのスキップ \{#skipping-no-op-events}
+
+メンバーシップルートに対するすべての `PUT` は、実際に何かが変更されたかどうかに関係なくイベントを発行します — したがって、監査目的で少なくとも 1 つの Webhook 配信があるようにします。消費者側で無操作の配信をスキップするには、デルタ配列の存在でフィルタリングします:
+
+```ts
+if (
+ payload.addedUserIds?.length ||
+ payload.removedUserIds?.length ||
+ payload.addedApplicationIds?.length ||
+ payload.removedApplicationIds?.length
+) {
+ // 実際のメンバーシップ変更 — 処理します
+}
+```
-**組織ロールイベント**
+`?.length` は `undefined` と `[]` の両方に対して偽であるため、フィールドが不在であるか(将来的に仮に)空の配列として出力されるかに関係なく、この述語は堅牢です。
+
+###### ペイロードの例 \{#membership-example-payloads}
+
+**ユーザーを追加する(`POST /organizations/:id/users`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "addedUserIds": ["u_001"]
+}
+```
+
+**ユーザーメンバーシップセットを置き換える(`PUT /organizations/:id/users`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "addedUserIds": ["u_002"],
+ "removedUserIds": ["u_001"]
+}
+```
+
+**ユーザーを削除する(`DELETE /organizations/:id/users/:userId`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "removedUserIds": ["u_001"]
+}
+```
+
+**アプリケーションを追加する(`POST /organizations/:id/applications`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "addedApplicationIds": ["app_xyz"]
+}
+```
+
+**既存メンバーの再追加、無操作の `PUT`、またはすでにメンバーである招待の再受諾(実際の変更なし):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc"
+}
+```
+
+**5000 の上限に達する一括操作(静かに切り捨て):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "removedUserIds": ["u_0001", "u_0002", "/* … exactly 5000 entries total */"]
+}
+```
+
+5000 エントリちょうどの配列を見たら、調整するために `GET /organizations/:id/users`(または `/applications`)を促します。
+
+#### 組織ロールイベント \{#organization-role-events}
```tsx
type OrganizationRole = {
@@ -198,27 +347,32 @@ type OrganizationScope = {
};
```
-| イベント | フィールド | 型 | オプション | 備考 |
-| ------------------------------ | ------------------ | ---------------- | ---------- | ------------------------------------------------------------------------------------------- |
-| OrganizationRole.Created | data | OrganizationRole | | このイベントで作成された組織ロール情報。 |
-| OrganizationRole.Data.Updated | data | OrganizationRole | | このイベントで更新された組織ロール情報。 |
-| OrganizationRole.Deleted | data | null | / | |
-| OrganizationRole.Scope.Updated | data | null | / | |
-| OrganizationRole.Scope.Updated | organizationRoleId | string | ✅ | スコープが割り当てられたロール ID。(事前割り当てスコープ付き新規ロール作成時のみ利用可能) |
+| イベント | フィールド | タイプ | オプション | 備考 |
+| ------------------------------- | ------------------ | ------------------ | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
+| OrganizationRole.Created | data | `OrganizationRole` | | 作成された組織ロールエンティティ。 |
+| OrganizationRole.Data.Updated | data | `OrganizationRole` | | 更新された組織ロールエンティティ。 |
+| OrganizationRole.Deleted | data | `null` | / | |
+| OrganizationRole.Scopes.Updated | data | `null` | / | |
+| OrganizationRole.Scopes.Updated | organizationRoleId | `string` | ✅ | スコープが割り当てられたロール ID。(事前に割り当てられたスコープを持つロールの作成によってイベントがトリガーされた場合にのみ利用可能。) |
+
+#### 組織権限 (スコープ) イベント \{#organization-permission-events}
-**組織権限(OrganizationScope)イベント**
+| イベント | フィールド | タイプ | オプション | 備考 |
+| ------------------------------ | ---------- | ------------------- | ---------- | ------------------------------------ |
+| OrganizationScope.Created | data | `OrganizationScope` | | 作成された組織スコープエンティティ。 |
+| OrganizationScope.Data.Updated | data | `OrganizationScope` | | 更新された組織スコープエンティティ。 |
+| OrganizationScope.Deleted | data | `null` | / | |
-| イベント | フィールド | 型 | オプション | 備考 |
-| ------------------------------ | ---------- | ----------------- | ---------- | ---------------------------- |
-| OrganizationScope.Created | data | OrganizationScope | | 作成された組織スコープ情報。 |
-| OrganizationScope.Data.Updated | data | OrganizationScope | | 更新された組織スコープ情報。 |
-| OrganizationScope.Deleted | data | null | / | |
+## 例外イベントペイロード \{#exception-event-payloads}
-## 例外フックイベントのリクエストボディ \{#exception-hook-events-request-body}
+**イベント:** `Identifier.Lockout`.
-利用可能なイベント: `Identifier.Lockout`
+セキュリティインシデントで発生します — 例えば、連続した認証失敗後にアカウントがロックされた場合。これらのイベントは常にユーザー向けフローから発生するため、ボディには以下が含まれます:
-リクエストボディは、標準リクエストボディフィールドと以下の追加フィールドを含む JSON オブジェクトです:
+- [共通フィールド](#common-fields)。
+- `ip` フィールド(データ変更イベントと同じ形状)。
+- [Experience API コンテキストフィールド](#experience-api-context-fields)。
+- 以下の例外固有のフィールド。
```tsx
enum SignInIdentifier {
@@ -228,16 +382,7 @@ enum SignInIdentifier {
}
```
-| フィールド | 型 | オプション | 備考 |
-| ---------------- | ------------------- | ---------- | ------------------------------------------------------------------- |
-| hookId | `string` | | Logto 内の識別子。 |
-| event | `string` | | このフックをトリガーしたイベント。 |
-| createdAt | `string` | | ペイロードの作成時刻(ISO 形式)。 |
-| userAgent | `string` | ✅ | リクエストのユーザーエージェント。 |
-| ip | `string` | ✅ | リクエストの IP アドレス。 |
-| interactionEvent | `string` | ✅ | このフックをトリガーしたインタラクションイベント。 |
-| sessionId | `string` | ✅ | このイベントのセッション ID(インタラクション ID ではありません)。 |
-| applicationId | `string` | ✅ | このイベントに関連するアプリケーション ID。 |
-| application | `ApplicationEntity` | ✅ | このイベントに関連するアプリケーション情報。 |
-| type | `SignInIdentifier` | | ユーザーの識別子タイプ(例:email、phone、username)。 |
-| value | `string` | | ロックアウトを引き起こしたユーザーの識別子値。 |
+| フィールド | タイプ | オプション | 備考 |
+| ---------- | ------------------ | ---------- | ---------------------------------------------------------------- |
+| type | `SignInIdentifier` | | ユーザーの識別子タイプ、例:メール、電話番号、またはユーザー名。 |
+| value | `string` | | ロックアウトを引き起こしたユーザーの識別子値。 |
diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx b/i18n/ko/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx
index fa66e1940de..61147f38af5 100644
--- a/i18n/ko/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx
+++ b/i18n/ko/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx
@@ -7,69 +7,69 @@ sidebar_position: 3
# Webhooks 이벤트
-이 가이드에서는 다양한 Logto Webhook 이벤트와 각 이벤트가 발생하는 시점을 설명합니다.
+이 가이드는 다양한 Logto webhook 이벤트를 나열하고 각 이벤트가 발생하는 시점을 설명합니다.
## 사용자 상호작용 훅 이벤트 \{#user-interaction-hook-events}
-| 이벤트 타입 | 설명 |
-| ----------------- | -------------------------------------------------------------------------------------- |
-| PostRegister | 사용자가 UI 인터페이스를 통해 새 계정을 성공적으로 생성했을 때 발생합니다. |
-| PostSignIn | 사용자가 UI 인터페이스를 통해 성공적으로 로그인했을 때 발생합니다. |
-| PostResetPassword | 사용자가 "비밀번호 찾기" 플로우를 통해 비밀번호를 성공적으로 재설정했을 때 발생합니다. |
+| 이벤트 유형 | 설명 |
+| ----------------- | ------------------------------------------------------------------------ |
+| PostRegister | 사용자가 UI 인터페이스를 통해 새 계정을 성공적으로 생성합니다. |
+| PostSignIn | 사용자가 UI 인터페이스를 통해 성공적으로 로그인합니다. |
+| PostResetPassword | 사용자의 비밀번호가 "비밀번호 찾기" 흐름을 통해 성공적으로 재설정됩니다. |
-## 데이터 변경 훅 이벤트 \{#data-mutation-hook-events}
+## 데이터 변형 훅 이벤트 \{#data-mutation-hook-events}
### 사용자 \{#user}
-| 이벤트 타입 | 설명 |
-| ----------------------------- | ------------------------------------------------------------------------------------------- |
-| User.Created | 새 사용자 계정이 생성되었습니다. |
-| User.Deleted | 사용자 계정이 삭제되었습니다. |
-| User.Data.Updated | 사용자 프로필 데이터가 업데이트되었습니다. 예: 이메일, 아바타, custom.data, 소셜 식별자 등. |
-| User.SuspensionStatus.Updated | 사용자 정지 상태가 변경되었습니다 (정지 또는 재활성화). |
+| 이벤트 유형 | 설명 |
+| ----------------------------- | --------------------------------------------------------------------------------------- |
+| User.Created | 새 사용자 계정이 생성됩니다. |
+| User.Deleted | 사용자 계정이 삭제됩니다. |
+| User.Data.Updated | 사용자 프로필 데이터가 업데이트됩니다. 예: 이메일, 아바타, custom.data, 소셜 식별자 등. |
+| User.SuspensionStatus.Updated | 사용자 정지 상태가 변경됩니다 (정지 또는 재활성화). |
-### 역할(Role) \{#role}
+### 역할 \{#role}
-| 이벤트 타입 | 설명 |
-| ------------------- | ------------------------------------------------------------------------- |
-| Role.Created | 새 역할이 생성되었습니다. |
-| Role.Deleted | 역할이 삭제되었습니다. |
-| Role.Data.Updated | 역할 데이터가 업데이트되었습니다. 예: 역할 이름, 설명, 기본 역할 상태 등. |
-| Role.Scopes.Updated | 역할에 할당된 권한이 추가되거나 제거되었습니다. |
+| 이벤트 유형 | 설명 |
+| ------------------- | -------------------------------------------------------------------- |
+| Role.Created | 새 역할이 생성됩니다. |
+| Role.Deleted | 역할이 삭제됩니다. |
+| Role.Data.Updated | 역할의 데이터가 업데이트됩니다. 예: 역할 이름, 설명, 기본 역할 상태. |
+| Role.Scopes.Updated | 역할에 할당된 권한이 추가되거나 제거됩니다. |
-### 권한(Permission, Scope) \{#permission-scope}
+### 권한 (스코프) \{#permission-scope}
-| 이벤트 타입 | 설명 |
-| ------------------ | ------------------------------------------------------- |
-| Scope.Created | 새 API 권한이 생성되었습니다. |
-| Scope.Deleted | API 권한이 삭제되었습니다. |
-| Scope.Data.Updated | API 권한 데이터가 업데이트되었습니다. 예: 권한 설명 등. |
+| 이벤트 유형 | 설명 |
+| ------------------ | -------------------------------------------------- |
+| Scope.Created | 새 API 권한이 생성됩니다. |
+| Scope.Deleted | API 권한이 삭제됩니다. |
+| Scope.Data.Updated | API 권한의 데이터가 업데이트됩니다. 예: 권한 설명. |
-### 조직(Organization) \{#organization}
+### 조직 \{#organization}
-| 이벤트 타입 | 설명 |
-| ------------------------------- | ---------------------------------------------------------------------- |
-| Organization.Created | 새 조직이 생성되었습니다. |
-| Organization.Deleted | 조직이 삭제되었습니다. |
-| Organization.Data.Updated | 조직 데이터가 업데이트되었습니다. 예: 조직 이름, 설명, custom.data 등. |
-| Organization.Membership.Updated | 조직에 멤버가 추가되거나 제거되었습니다. |
+| 이벤트 유형 | 설명 |
+| ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Organization.Created | 새 조직이 생성됩니다. |
+| Organization.Deleted | 조직이 삭제됩니다. |
+| Organization.Data.Updated | 조직의 데이터가 업데이트됩니다. 예: 조직 이름, 설명, custom.data 등. |
+| Organization.Membership.Updated | 조직에 사용자 또는 애플리케이션이 추가되거나 제거됩니다. 페이로드에는 [멤버십 델타 필드](/developers/webhooks/webhooks-request#organizationmembershipupdated-payload)가 포함됩니다. |
-### 조직 역할(Organization role) \{#organization-role}
+### 조직 역할 \{#organization-role}
-| 이벤트 타입 | 설명 |
-| ------------------------------- | --------------------------------------------------------------------- |
-| OrganizationRole.Created | 새 조직 역할이 생성되었습니다. |
-| OrganizationRole.Deleted | 조직 역할이 삭제되었습니다. |
-| OrganizationRole.Data.Updated | 조직 역할 데이터가 업데이트되었습니다. 예: 조직 역할 이름 및 설명 등. |
-| OrganizationRole.Scopes.Updated | 조직 역할에 할당된 권한이 추가되거나 제거되었습니다. |
+| 이벤트 유형 | 설명 |
+| ------------------------------- | ---------------------------------------------------------------- |
+| OrganizationRole.Created | 새 조직 역할이 생성됩니다. |
+| OrganizationRole.Deleted | 조직 역할이 삭제됩니다. |
+| OrganizationRole.Data.Updated | 조직 역할의 데이터가 업데이트됩니다. 예: 조직 역할 이름 및 설명. |
+| OrganizationRole.Scopes.Updated | 조직 역할에 할당된 권한이 추가되거나 제거됩니다. |
-### 조직 권한(Organization permission, scope) \{#organization-permission-scope}
+### 조직 권한 (스코프) \{#organization-permission-scope}
-| 이벤트 타입 | 설명 |
-| ------------------------------ | ------------------------------------------------------------- |
-| OrganizationScope.Created | 새 조직 권한이 생성되었습니다. |
-| OrganizationScope.Deleted | 조직 권한이 삭제되었습니다. |
-| OrganizationScope.Data.Updated | 조직 권한 데이터가 업데이트되었습니다. 예: 조직 권한 설명 등. |
+| 이벤트 유형 | 설명 |
+| ------------------------------ | -------------------------------------------------------- |
+| OrganizationScope.Created | 새 조직 권한이 생성됩니다. |
+| OrganizationScope.Deleted | 조직 권한이 삭제됩니다. |
+| OrganizationScope.Data.Updated | 조직 권한의 데이터가 업데이트됩니다. 예: 조직 권한 설명. |
### Management API 트리거 이벤트 \{#management-api-triggered-events}
@@ -96,6 +96,10 @@ sidebar_position: 3
| PUT /organizations/:id/users | Organization.Membership.Updated |
| POST /organizations/:id/users | Organization.Membership.Updated |
| DELETE /organizations/:id/users/:userId | Organization.Membership.Updated |
+| PUT /organizations/:id/applications | Organization.Membership.Updated |
+| POST /organizations/:id/applications | Organization.Membership.Updated |
+| DELETE /organizations/:id/applications/:applicationId | Organization.Membership.Updated |
+| PUT /organization-invitations/:id/status (Accepted) | Organization.Membership.Updated |
| POST /organization-roles | OrganizationRole.Created, (OrganizationRole.Scopes.Updated) |
| DELETE /organization-roles/:id | OrganizationRole.Deleted |
| PATCH /organization-roles/:id | OrganizationRole.Data.Updated |
@@ -108,23 +112,24 @@ sidebar_position: 3
### Experience API 트리거 이벤트 \{#experience-api-triggered-events}
-| 사용자 상호작용 액션 | 이벤트 |
-| ----------------------- | ----------------- |
-| 사용자 이메일/전화 연결 | User.Data.Updated |
-| 사용자 MFA 연결 | User.Data.Updated |
-| 사용자 소셜/SSO 연결 | User.Data.Updated |
-| 사용자 비밀번호 재설정 | User.Data.Updated |
-| 사용자 등록 | User.Created |
+| 사용자 상호작용 액션 | 이벤트 |
+| ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------- |
+| 사용자 이메일 / 전화번호 연결 | User.Data.Updated |
+| 사용자 MFA 연결 | User.Data.Updated |
+| 사용자 소셜 / SSO 연결 | User.Data.Updated |
+| 사용자 비밀번호 재설정 | User.Data.Updated |
+| 사용자 등록 | User.Created |
+| [Just-in-Time 프로비저닝](/organizations/just-in-time-provisioning) (이메일 도메인 또는 엔터프라이즈 SSO 커넥터 일치)을 통해 조직에 자동 프로비저닝된 사용자 | Organization.Membership.Updated |
## 예외 훅 이벤트 \{#exception-hook-events}
-### 보안(Security) \{#security}
+### 보안 \{#security}
-| 이벤트 타입 | 설명 |
-| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| Identifier.Lockout | 연속된 아이덴티티 검증 실패 시 사용자 계정이 잠깁니다. 다음 플로우에서 트리거될 수 있습니다:
- 비밀번호 검증 실패
- 코드 검증 실패
- 일회용 토큰 검증 실패
|
+| 이벤트 유형 | 설명 |
+| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Identifier.Lockout | 연속된 아이덴티티 확인 실패 시도로 인해 사용자 계정이 잠깁니다. 다음 흐름에서 트리거될 수 있습니다:
- 비밀번호 확인 실패
- 코드 확인 실패
- 일회용 토큰 확인 실패
|
-## 자주 묻는 질문(FAQs) \{#faqs}
+## 자주 묻는 질문 \{#faqs}
@@ -133,6 +138,6 @@ sidebar_position: 3
-`PostRegister`는 사용자가 사용자 가입 플로우를 통해 새 계정을 성공적으로 생성했을 때 트리거됩니다. `User.Created`는 Management API를 통해 새 사용자 계정이 생성되었을 때 트리거됩니다.
+`PostRegister`는 사용자가 사용자 가입 흐름을 통해 새 계정을 성공적으로 생성할 때 트리거됩니다. `User.Created`는 Management API를 통해 새 사용자 계정이 생성될 때 트리거됩니다.
diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx b/i18n/ko/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx
index d1efbff6199..330ece96657 100644
--- a/i18n/ko/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx
+++ b/i18n/ko/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx
@@ -7,23 +7,60 @@ sidebar_position: 4
# Webhooks 요청
-유효한 hook 이벤트가 발생하면, Logto는 해당하는 webhooks를 찾아 각 hook 설정마다 POST 요청을 보냅니다.
+Webhook 이벤트가 발생하면, Logto는 해당 이벤트에 구독된 모든 엔드포인트에 `POST` 요청을 보냅니다. 전체 이벤트 카탈로그는 [Webhooks 이벤트](/developers/webhooks/webhooks-events)에 있으며, 이 페이지에서는 Logto가 전달하는 **요청의 형태**를 문서화합니다.
## 요청 헤더 \{#request-headers}
-| Key | Customizable | Notes |
-| ----------------------- | ------------ | ------------------------------------------------------------------------------------------------ |
-| user-agent | ✅ | 기본값은 `Logto (https://logto.io/)` 입니다. |
-| content-type | ✅ | 기본값은 `application/json` 입니다. |
-| logto-signature-sha-256 | | 요청 본문의 서명입니다. [webhooks 보안 설정](/developers/webhooks/secure-webhooks)을 참고하세요. |
+| Key | Customizable | Notes |
+| ----------------------- | ------------ | ------------------------------------------------------------------------------------------- |
+| user-agent | ✅ | 기본값은 `Logto (https://logto.io/)`입니다. |
+| content-type | ✅ | 기본값은 `application/json`입니다. |
+| logto-signature-sha-256 | | 요청 본문의 서명입니다. [Webhooks 보안](/developers/webhooks/secure-webhooks)을 참조하세요. |
-동일한 key로 [요청 헤더 커스터마이즈](/developers/webhooks/configure-webhooks/#secure-webhook)하여 커스터마이즈 가능한 헤더를 덮어쓸 수 있습니다.
+사용자 정의 가능한 헤더는 [보안 webhook](/developers/webhooks/configure-webhooks/#secure-webhook) 구성에서 재정의할 수 있습니다.
-## 상호작용 hook 이벤트 요청 본문 \{#interaction-hook-events-request-body}
+## 요청 본문 개요 \{#request-body-overview}
-사용 가능한 이벤트: `PostRegister`, `PostSignIn`, `PostResetPassword`
+본문은 JSON 객체입니다. 그 정확한 형태는 이벤트가 속한 패밀리에 따라 다릅니다:
-요청 본문은 세 가지 유형의 데이터 필드를 포함하는 JSON 객체입니다:
+| Family | Events | When it fires |
+| ----------------- | -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
+| **User flow** | `PostRegister`, `PostSignIn`, `PostResetPassword` | 사용자가 Experience API에 의해 처리되는 가입, 로그인 또는 비밀번호 재설정 흐름을 완료할 때. |
+| **Data mutation** | `User.*`, `Role.*`, `Scope.*`, `Organization.*`, `OrganizationRole.*`, `OrganizationScope.*` | 기본 데이터 모델이 변경될 때 — Management API 호출 또는 Experience API의 사용자 흐름에 의해. |
+| **Exception** | `Identifier.Lockout` | 보안 사고 — 예를 들어, 연속된 인증 실패 시도 후 계정이 잠긴 경우. |
+
+모든 패밀리는 [공통 필드](#common-fields)의 작은 집합을 공유합니다. 각 패밀리는 자체 요청-컨텍스트 필드와 이벤트별 페이로드를 추가합니다.
+
+### 공통 필드 \{#common-fields}
+
+패밀리와 상관없이 모든 전달에 존재합니다:
+
+| Field | Type | Optional | Notes |
+| --------- | -------- | -------- | ----------------------------------------- |
+| hookId | `string` | | Logto의 webhook 구성 식별자입니다. |
+| event | `string` | | 이 전달을 트리거한 이벤트입니다. |
+| createdAt | `string` | | ISO 8601 형식의 페이로드 생성 시간입니다. |
+| userAgent | `string` | ✅ | 트리거 요청의 사용자 에이전트입니다. |
+
+각 패밀리에는 또한 트리거 요청의 IP 주소가 포함됩니다 — 사용자 흐름 이벤트의 경우 `userIp` 필드, 데이터 변이 및 예외 이벤트의 경우 `ip` 필드로. 의미는 동일하며, 역사적인 이름 차이는 하위 호환성을 위해 유지됩니다.
+
+## 사용자 흐름 이벤트 페이로드 \{#user-flow-event-payloads}
+
+**이벤트:** `PostRegister`, `PostSignIn`, `PostResetPassword`.
+
+사용자가 Experience API에 의해 처리되는 가입, 로그인 또는 비밀번호 재설정 흐름을 완료할 때 발생합니다. [공통 필드](#common-fields) 외에도 본문에는 다음이 포함됩니다:
+
+| Field | Type | Optional | Notes |
+| ---------------- | -------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| interactionEvent | `'SignIn' \| 'Register' \| 'ForgotPassword'` | | 사용자 흐름 이벤트 유형입니다. 각각 `PostSignIn` / `PostRegister` / `PostResetPassword`에 매핑됩니다. 필드 이름은 역사적인 "상호작용" 명명을 유지합니다. |
+| sessionId | `string` | ✅ | 이 이벤트에 대한 세션 ID (상호작용 ID 아님), 해당되는 경우. |
+| userIp | `string` | ✅ | 트리거 요청의 IP 주소입니다. |
+| userId | `string` | ✅ | 이 이벤트와 관련된 사용자 ID, 해당되는 경우. |
+| user | `UserEntity` | ✅ | 이 이벤트와 관련된 사용자 엔티티, 해당되는 경우. |
+| applicationId | `string` | ✅ | 이 이벤트와 관련된 애플리케이션 ID, 해당되는 경우. |
+| application | `ApplicationEntity` | ✅ | 이 이벤트와 관련된 애플리케이션 엔티티, 해당되는 경우. |
+
+#### 엔티티 형태 \{#user-flow-entity-shapes}
```tsx
type UserEntity = {
@@ -60,70 +97,57 @@ type ApplicationEntity = {
};
```
-| Field | Type | Optional | Notes |
-| ---------------- | ------------------- | -------- | --------------------------------------------------------- |
-| hookId | `string` | | Logto의 식별자입니다. |
-| event | `string` | | 이 hook을 트리거한 이벤트입니다. |
-| createdAt | `string` | | 페이로드 생성 시간 (ISO 형식)입니다. |
-| interactionEvent | `string` | | 이 hook을 트리거한 상호작용 이벤트입니다. |
-| sessionId | `string` | ✅ | 이 이벤트의 세션 ID (Interaction ID 아님), 해당되는 경우. |
-| userAgent | `string` | ✅ | 이 hook을 트리거한 요청의 user-agent입니다. |
-| userIp | `string` | ✅ | 이 hook을 트리거한 요청의 IP 주소입니다. |
-| userId | `string` | ✅ | 이 이벤트와 관련된 사용자 ID, 해당되는 경우. |
-| user | `UserEntity` | ✅ | 이 이벤트와 관련된 사용자 엔티티, 해당되는 경우. |
-| applicationId | `string` | ✅ | 이 이벤트와 관련된 애플리케이션 ID, 해당되는 경우. |
-| application | `ApplicationEntity` | ✅ | 이 이벤트와 관련된 애플리케이션 정보, 해당되는 경우. |
+전체 필드 참조는 [사용자](/user-management/user-data) 및 [애플리케이션](/integrate-logto/application-data-structure)을 참조하세요.
-자세한 필드 설명은 [사용자](/user-management/user-data) 및 [애플리케이션](/integrate-logto/application-data-structure) 참고 문서를 확인하세요.
+## 데이터 변이 이벤트 페이로드 \{#data-mutation-event-payloads}
-## 데이터 변이 hook 이벤트 요청 본문 \{#data-mutation-hook-events-request-body}
+**이벤트:** `User.*`, `Role.*`, `Scope.*`, `Organization.*`, `OrganizationRole.*`, `OrganizationScope.*` 아래의 모든 이벤트 — 전체 카탈로그는 [Webhooks 이벤트 → 데이터 변이 훅 이벤트](/developers/webhooks/webhooks-events#data-mutation-hook-events)를 참조하세요.
-### 표준 요청 본문 필드 \{#standard-request-body-fields}
+본문에는 항상 다음이 포함됩니다:
-| Field | Type | Optional | Notes |
-| --------- | -------- | -------- | ------------------------------------ |
-| hookId | `string` | | Logto의 식별자입니다. |
-| event | `string` | | 이 hook을 트리거한 이벤트입니다. |
-| createdAt | `string` | | 페이로드 생성 시간 (ISO 형식)입니다. |
-| userAgent | `string` | ✅ | 요청의 user-agent입니다. |
-| ip | `string` | ✅ | 요청의 IP 주소입니다. |
+- [공통 필드](#common-fields).
+- `ip` 필드 — 트리거 요청의 IP 주소 (선택 사항, 알려진 경우에 존재).
+- 변경이 어떻게 트리거되었는지를 설명하는 **API 컨텍스트**. 컨텍스트는 트리거 소스에 따라 두 가지 변형 중 하나입니다:
+ - [Experience API 컨텍스트](#experience-api-context-fields) — 변경이 사용자 대면 흐름에서 발생한 경우.
+ - [Management API 컨텍스트](#management-api-context-fields) — 변경이 직접적인 Management API 호출에서 발생한 경우.
+- **이벤트별 페이로드** — `data`에 영향을 받은 엔티티와 (일부 이벤트의 경우) 추가 최상위 필드. [이벤트별 데이터 페이로드](#event-specific-data-payloads)를 참조하세요.
-### 상호작용 API 컨텍스트 본문 필드 \{#interaction-api-context-body-fields}
+### Experience API 컨텍스트 필드 \{#experience-api-context-fields}
-사용자 상호작용 API 호출로 트리거되는 데이터 변이 hook 이벤트입니다.
+변경이 Experience API의 사용자 대면 흐름에 의해 트리거된 경우에 존재합니다 — 예를 들어, 가입 중 `User.Created` 또는 프로필 업데이트 중 `User.Data.Updated`.
-사용 가능한 이벤트: `User.Created`, `User.Data.Updated`
+| Field | Type | Optional | Notes |
+| ---------------- | -------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------- |
+| interactionEvent | `'SignIn' \| 'Register' \| 'ForgotPassword'` | ✅ | 변경을 발생시킨 사용자 흐름 이벤트 유형입니다. 필드 이름은 역사적인 "상호작용" 명명을 유지합니다. |
+| sessionId | `string` | ✅ | 이 이벤트에 대한 세션 ID (상호작용 ID 아님), 해당되는 경우. |
+| applicationId | `string` | ✅ | 애플리케이션 ID, 해당되는 경우. |
+| application | `ApplicationEntity` | ✅ | 애플리케이션 엔티티, 해당되는 경우. |
-| Field | Type | Optional | Notes |
-| ---------------- | ------------------- | -------- | --------------------------------------------------------- |
-| interactionEvent | `string` | ✅ | 이 hook을 트리거한 상호작용 이벤트입니다. |
-| sessionId | `string` | ✅ | 이 이벤트의 세션 ID (Interaction ID 아님), 해당되는 경우. |
-| applicationId | `string` | ✅ | 이 이벤트와 관련된 애플리케이션 ID, 해당되는 경우. |
-| application | `ApplicationEntity` | ✅ | 이 이벤트와 관련된 애플리케이션 정보, 해당되는 경우. |
+### Management API 컨텍스트 필드 \{#management-api-context-fields}
-### Management API 컨텍스트 본문 필드 \{#management-api-context-body-fields}
+변경이 Management API 호출에 의해 트리거된 경우에 존재합니다.
-Management API 호출로 트리거되는 데이터 변이 hook 이벤트입니다.
+| Field | Type | Optional | Notes |
+| ------------ | -------- | -------- | -------------------------------------------------------------------------------------------- |
+| path | `string` | ✅ | 이 훅을 트리거한 API 호출의 경로입니다. |
+| method | `string` | ✅ | API 호출의 HTTP 메서드입니다. |
+| status | `number` | ✅ | API 호출의 응답 상태 코드입니다. |
+| params | `object` | ✅ | API 호출의 koa 경로 매개변수입니다. |
+| matchedRoute | `string` | ✅ | koa 매칭된 경로입니다. Logto는 이 필드를 사용하여 활성화된 webhook 이벤트 필터를 매칭합니다. |
-| Field | Type | Optional | Notes |
-| ------------ | -------- | -------- | -------------------------------------------------------------------------------------------------------------------- |
-| path | `string` | ✅ | 이 hook을 트리거한 API 호출의 경로입니다. |
-| method | `string` | ✅ | 이 hook을 트리거한 API 호출의 메서드입니다. |
-| status | `number` | ✅ | 이 hook을 트리거한 API 호출의 응답 상태 코드입니다. |
-| params | `object` | ✅ | 이 hook을 트리거한 API 호출의 koa path params입니다. |
-| matchedRoute | `string` | ✅ | 이 hook을 트리거한 API 호출의 koa 매칭된 라우트입니다. Logto는 이 필드를 사용하여 활성화된 hook 이벤트를 매칭합니다. |
+### 이벤트별 데이터 페이로드 \{#event-specific-data-payloads}
-### 데이터 페이로드 본문 필드 \{#data-payload-body-fields}
+모든 데이터 변이 이벤트는 영향을 받은 엔티티를 포함하는 최상위 `data` 필드를 포함하며, 변경이 단일 엔티티로 요약될 수 없는 경우 (삭제 및 멤버십 이벤트)에는 `null`입니다. 일부 이벤트는 `data` 외에도 이벤트별 최상위 필드를 포함합니다 — `Organization.Membership.Updated`가 그 중 하나이며, 아래에 문서화되어 있습니다.
-**사용자 이벤트**
+#### 사용자 이벤트 \{#user-events}
-| Event | Field | Type | Optional | Notes |
-| ----------------- | ----- | ---------- | -------- | ------------------------------------------- |
-| User.Created | data | UserEntity | | 이 이벤트로 생성된 사용자 엔티티입니다. |
-| User.Data.Updated | data | UserEntity | | 이 이벤트로 업데이트된 사용자 엔티티입니다. |
-| User.Deleted | data | null | / | |
+| Event | Field | Type | Optional | Notes |
+| ----------------- | ----- | ------------ | -------- | ------------------------------- |
+| User.Created | data | `UserEntity` | | 생성된 사용자 엔티티입니다. |
+| User.Data.Updated | data | `UserEntity` | | 업데이트된 사용자 엔티티입니다. |
+| User.Deleted | data | `null` | / | |
-**역할 이벤트**
+#### 역할 이벤트 \{#role-events}
```tsx
type Role = {
@@ -145,23 +169,23 @@ type Scope = {
};
```
-| Event | Field | Type | Optional | Notes |
-| ------------------ | ------ | ------- | -------- | ------------------------------------------------------------------------------ |
-| Role.Created | data | Role | | 이 이벤트로 생성된 역할 엔티티입니다. |
-| Role.Data.Updated | data | Role | | 이 이벤트로 업데이트된 역할 엔티티입니다. |
-| Role.Deleted | data | null | | |
-| Role.Scope.Updated | data | Scope[] | | 역할에 할당된 업데이트된 스코프입니다. |
-| Role.Scope.Updated | roleId | string | ✅ | 스코프가 할당된 역할 ID입니다. (사전 할당된 스코프로 새 역할 생성 시에만 제공) |
+| Event | Field | Type | Optional | Notes |
+| ------------------- | ------ | --------- | -------- | ---------------------------------------------------------------------------------------------------------------------- |
+| Role.Created | data | `Role` | | 생성된 역할 엔티티입니다. |
+| Role.Data.Updated | data | `Role` | | 업데이트된 역할 엔티티입니다. |
+| Role.Deleted | data | `null` | / | |
+| Role.Scopes.Updated | data | `Scope[]` | | 역할에 할당된 업데이트된 스코프입니다. |
+| Role.Scopes.Updated | roleId | `string` | ✅ | 스코프가 할당된 역할 ID입니다. (사전 할당된 스코프와 함께 역할을 생성하여 이벤트가 트리거된 경우에만 사용 가능합니다.) |
-**권한(스코프) 이벤트**
+#### 권한 (스코프) 이벤트 \{#permission-events}
-| Event | Field | Type | Optional | Notes |
-| ------------------ | ----- | ----- | -------- | ------------------------------------------- |
-| Scope.Created | data | Scope | | 이 이벤트로 생성된 스코프 엔티티입니다. |
-| Scope.Data.Updated | data | Scope | | 이 이벤트로 업데이트된 스코프 엔티티입니다. |
-| Scope.Deleted | data | null | / | |
+| Event | Field | Type | Optional | Notes |
+| ------------------ | ----- | ------- | -------- | ------------------------------- |
+| Scope.Created | data | `Scope` | | 생성된 스코프 엔티티입니다. |
+| Scope.Data.Updated | data | `Scope` | | 업데이트된 스코프 엔티티입니다. |
+| Scope.Deleted | data | `null` | / | |
-**조직 이벤트**
+#### 조직 이벤트 \{#organization-events}
```tsx
type Organization = {
@@ -173,14 +197,141 @@ type Organization = {
};
```
-| Event | Field | Type | Optional | Notes |
-| ------------------------------- | ----- | ------------ | -------- | ----------------------------------------- |
-| Organization.Created | data | Organization | | 이 이벤트로 생성된 조직 엔티티입니다. |
-| Organization.Data.Updated | data | Organization | | 이 이벤트로 업데이트된 조직 엔티티입니다. |
-| Organization.Deleted | data | null | / | |
-| Organization.Membership.Updated | data | null | / | |
+| Event | Field | Type | Optional | Notes |
+| ------------------------------- | ----- | -------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Organization.Created | data | `Organization` | | 생성된 조직 엔티티입니다. |
+| Organization.Data.Updated | data | `Organization` | | 업데이트된 조직 엔티티입니다. |
+| Organization.Deleted | data | `null` | / | |
+| Organization.Membership.Updated | data | `null` | / | 변경은 선택적 최상위 델타 배열로 설명됩니다. 아래의 [Organization.Membership.Updated 페이로드](#organizationmembershipupdated-payload)를 참조하세요. |
+
+##### Organization.Membership.Updated 페이로드 \{#organizationmembershipupdated-payload}
+
+[공통 필드](#common-fields)와 트리거 소스에 따라 적용되는 API 컨텍스트 필드(Management API 라우트의 경우 [Management API 컨텍스트](#management-api-context-fields), 적시 프로비저닝의 경우 [Experience API 컨텍스트](#experience-api-context-fields)) 외에도, `Organization.Membership.Updated` 이벤트는 `organizationId`와 페이로드의 최상위에 선택적 델타 배열을 포함합니다 (예: `event`, `createdAt` 등과 함께, 이 이벤트의 경우 항상 `null`인 `data` 내부가 아님).
+
+| Field | Type | Optional | Notes |
+| --------------------- | ---------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------- |
+| organizationId | `string` | | 멤버십이 변경된 조직입니다. |
+| addedUserIds | `string[]` | ✅ | 이 트리거에 의해 새로 추가된 사용자 ID입니다. 사용자가 추가되지 않았거나, 트리거가 사용자 멤버십에 영향을 미치지 않는 경우 생략됩니다. |
+| removedUserIds | `string[]` | ✅ | 이 트리거에 의해 제거된 사용자 ID입니다. 사용자가 제거되지 않은 경우 생략됩니다. |
+| addedApplicationIds | `string[]` | ✅ | 새로 추가된 애플리케이션 ID입니다. 애플리케이션이 추가되지 않았거나, 트리거가 애플리케이션 멤버십에 영향을 미치지 않는 경우 생략됩니다. |
+| removedApplicationIds | `string[]` | ✅ | 제거된 애플리케이션 ID입니다. 애플리케이션이 제거되지 않은 경우 생략됩니다. |
+
+네 개의 델타 배열은 **선택적이고 추가적**입니다 — 이를 기대하지 않는 소비자에게 기존 페이로드 형태를 변경하지 않으며, 레거시 `data: null` 필드는 여전히 변경 없이 출력됩니다.
+
+###### 트리거 및 발행할 수 있는 델타 필드 \{#membership-triggers}
+
+| Trigger | Possible delta fields |
+| ------------------------------------------------------- | ---------------------------------------------- |
+| `POST /organizations/:id/users` | `addedUserIds` |
+| `PUT /organizations/:id/users` | `addedUserIds`, `removedUserIds` |
+| `DELETE /organizations/:id/users/:userId` | `removedUserIds` |
+| `POST /organizations/:id/applications` | `addedApplicationIds` |
+| `PUT /organizations/:id/applications` | `addedApplicationIds`, `removedApplicationIds` |
+| `DELETE /organizations/:id/applications/:applicationId` | `removedApplicationIds` |
+| `PUT /organization-invitations/:id/status` (`Accepted`) | `addedUserIds` |
+| 사용자를 새 조직에 추가할 때의 적시 프로비저닝 | `addedUserIds` |
+
+참고: 적시 프로비저닝은 사용자가 이미 멤버인 조직에 대해 `Organization.Membership.Updated`를 발신하지 않습니다.
+
+###### 빈 델타는 생략됩니다 — 부재 ≠ 빈 변경 \{#empty-deltas-are-omitted}
+
+빈 델타 배열은 **페이로드에서 완전히 생략**됩니다. 예를 들어, 기존 세트로 멤버십 세트를 대체하는 `PUT /organizations/:id/users`는 실제 변경을 발생시키지 않으며, 페이로드는 모든 네 개의 델타 필드가 없는 `{ organizationId }`로 축소됩니다. 동일한 멤버를 다시 추가하거나, 이미 멤버인 사용자가 초대를 다시 수락하거나하는 경우에도 마찬가지입니다.
+
+**소비자는 누락된 필드를 "그 측면에서의 변경 없음"으로 처리해야 하며, "빈 변경"으로 처리해서는 안 됩니다.**
+
+###### 배열당 제한 (조용한 잘림) \{#membership-delta-cap}
+
+각 델타 배열은 **5000 항목**으로 제한됩니다. 단일 Management API 호출이 한 번의 작업에서 5000명 이상의 사용자 (또는 애플리케이션)를 추가하거나 제거할 때, 해당 델타 배열은 처음 5000개의 항목으로 조용히 잘립니다 — **제한이 발동되었다는 페이로드 내 마커는 없습니다.**
+
+애플리케이션이 한 번의 호출로 5000명 이상의 멤버에 영향을 미칠 수 있는 관리 대량 작업을 수행하는 경우, 정확히 5000개의 항목으로 구성된 배열을 권위 있는 멤버십을 Management API를 통해 조정하는 신호로 처리하세요:
+
+- `GET /organizations/:id/users` — 전체 사용자 멤버십.
+- `GET /organizations/:id/applications` — 전체 애플리케이션 멤버십.
+
+이는 GitHub의 `push` 이벤트와 동일한 패턴을 따르며, `commits`를 20개의 항목으로 제한하고 전체 목록에 대해 소비자를 비교 API로 안내합니다.
+
+###### 무의미한 이벤트 건너뛰기 \{#skipping-no-op-events}
+
+멤버십 경로에 대한 모든 `PUT`은 실제로 변경된 것이 있는지 여부에 관계없이 이벤트를 발생시킵니다 — 따라서 모든 상태 대체 호출에는 감사 목적으로 적어도 하나의 webhook 전달이 있습니다. 소비자 측에서 무의미한 전달을 건너뛰려면 델타 배열 존재 여부를 기준으로 필터링하세요:
+
+```ts
+if (
+ payload.addedUserIds?.length ||
+ payload.removedUserIds?.length ||
+ payload.addedApplicationIds?.length ||
+ payload.removedApplicationIds?.length
+) {
+ // 실제 멤버십 변경 — 이를 처리하세요
+}
+```
+
+`?.length`는 `undefined`와 `[]` 모두에 대해 거짓이므로, 필드가 없거나 (어떤 가상의 미래에) 빈 배열로 출력되는 경우에도 동일한 조건이 견고합니다.
+
+###### 예제 페이로드 \{#membership-example-payloads}
+
+**사용자 추가 (`POST /organizations/:id/users`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "addedUserIds": ["u_001"]
+}
+```
+
+**사용자 멤버십 세트 대체 (`PUT /organizations/:id/users`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "addedUserIds": ["u_002"],
+ "removedUserIds": ["u_001"]
+}
+```
+
+**사용자 제거 (`DELETE /organizations/:id/users/:userId`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "removedUserIds": ["u_001"]
+}
+```
-**OrganizationRole 이벤트**
+**애플리케이션 추가 (`POST /organizations/:id/applications`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "addedApplicationIds": ["app_xyz"]
+}
+```
+
+**기존 멤버를 다시 추가, 무의미한 `PUT`, 또는 이미 멤버인 초대의 재수락 (실제 변경 없음):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc"
+}
+```
+
+**5000 제한에 도달하는 대량 작업 (조용히 잘림):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "removedUserIds": ["u_0001", "u_0002", "/* … 정확히 5000개의 항목 총계 */"]
+}
+```
+
+정확히 5000개의 항목으로 구성된 배열을 보면 `GET /organizations/:id/users` (또는 `/applications`)를 통해 조정해야 합니다.
+
+#### 조직 역할 이벤트 \{#organization-role-events}
```tsx
type OrganizationRole = {
@@ -198,27 +349,32 @@ type OrganizationScope = {
};
```
-| Event | Field | Type | Optional | Notes |
-| ------------------------------ | ------------------ | ---------------- | -------- | ------------------------------------------------------------------------------ |
-| OrganizationRole.Created | data | OrganizationRole | | 이 이벤트로 생성된 조직 역할 엔티티입니다. |
-| OrganizationRole.Data.Updated | data | OrganizationRole | | 이 이벤트로 업데이트된 조직 역할 엔티티입니다. |
-| OrganizationRole.Deleted | data | null | / | |
-| OrganizationRole.Scope.Updated | data | null | / | |
-| OrganizationRole.Scope.Updated | organizationRoleId | string | ✅ | 스코프가 할당된 역할 ID입니다. (사전 할당된 스코프로 새 역할 생성 시에만 제공) |
+| Event | Field | Type | Optional | Notes |
+| ------------------------------- | ------------------ | ------------------ | -------- | ---------------------------------------------------------------------------------------------------------------------- |
+| OrganizationRole.Created | data | `OrganizationRole` | | 생성된 조직 역할 엔티티입니다. |
+| OrganizationRole.Data.Updated | data | `OrganizationRole` | | 업데이트된 조직 역할 엔티티입니다. |
+| OrganizationRole.Deleted | data | `null` | / | |
+| OrganizationRole.Scopes.Updated | data | `null` | / | |
+| OrganizationRole.Scopes.Updated | organizationRoleId | `string` | ✅ | 스코프가 할당된 역할 ID입니다. (사전 할당된 스코프와 함께 역할을 생성하여 이벤트가 트리거된 경우에만 사용 가능합니다.) |
+
+#### 조직 권한 (스코프) 이벤트 \{#organization-permission-events}
-**조직 권한(OrganizationScope) 이벤트**
+| Event | Field | Type | Optional | Notes |
+| ------------------------------ | ----- | ------------------- | -------- | ------------------------------------ |
+| OrganizationScope.Created | data | `OrganizationScope` | | 생성된 조직 스코프 엔티티입니다. |
+| OrganizationScope.Data.Updated | data | `OrganizationScope` | | 업데이트된 조직 스코프 엔티티입니다. |
+| OrganizationScope.Deleted | data | `null` | / | |
-| Event | Field | Type | Optional | Notes |
-| ------------------------------ | ----- | ----------------- | -------- | ------------------------------------ |
-| OrganizationScope.Created | data | OrganizationScope | | 생성된 조직 스코프 엔티티입니다. |
-| OrganizationScope.Data.Updated | data | OrganizationScope | | 업데이트된 조직 스코프 엔티티입니다. |
-| OrganizationScope.Deleted | data | null | / | |
+## 예외 이벤트 페이로드 \{#exception-event-payloads}
-## 예외 hook 이벤트 요청 본문 \{#exception-hook-events-request-body}
+**이벤트:** `Identifier.Lockout`.
-사용 가능한 이벤트: `Identifier.Lockout`
+보안 사고 시 발생합니다 — 예를 들어, 연속된 인증 실패 시도 후 계정이 잠긴 경우. 이러한 이벤트는 항상 사용자 대면 흐름에서 발생하므로, 본문에는 다음이 포함됩니다:
-요청 본문은 표준 요청 본문 필드와 아래의 추가 필드를 포함하는 JSON 객체입니다:
+- [공통 필드](#common-fields).
+- `ip` 필드 (데이터 변이 이벤트와 동일한 형태).
+- [Experience API 컨텍스트 필드](#experience-api-context-fields).
+- 아래의 예외별 필드.
```tsx
enum SignInIdentifier {
@@ -228,16 +384,7 @@ enum SignInIdentifier {
}
```
-| Field | Type | Optional | Notes |
-| ---------------- | ------------------- | -------- | --------------------------------------------------------- |
-| hookId | `string` | | Logto의 식별자입니다. |
-| event | `string` | | 이 hook을 트리거한 이벤트입니다. |
-| createdAt | `string` | | 페이로드 생성 시간 (ISO 형식)입니다. |
-| userAgent | `string` | ✅ | 요청의 user-agent입니다. |
-| ip | `string` | ✅ | 요청의 IP 주소입니다. |
-| interactionEvent | `string` | ✅ | 이 hook을 트리거한 상호작용 이벤트입니다. |
-| sessionId | `string` | ✅ | 이 이벤트의 세션 ID (Interaction ID 아님), 해당되는 경우. |
-| applicationId | `string` | ✅ | 이 이벤트와 관련된 애플리케이션 ID, 해당되는 경우. |
-| application | `ApplicationEntity` | ✅ | 이 이벤트와 관련된 애플리케이션 정보, 해당되는 경우. |
-| type | `SignInIdentifier` | | 사용자의 식별자 유형 (예: email, phone, username). |
-| value | `string` | | 잠금이 발생한 사용자의 식별자 값입니다. |
+| Field | Type | Optional | Notes |
+| ----- | ------------------ | -------- | ------------------------------------------------------------ |
+| type | `SignInIdentifier` | | 사용자의 식별자 유형, 예: 이메일, 전화번호 또는 사용자 이름. |
+| value | `string` | | 잠금이 발생한 사용자의 식별자 값입니다. |
diff --git a/i18n/pt-BR/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx b/i18n/pt-BR/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx
index 27c543bf25c..055c97539a0 100644
--- a/i18n/pt-BR/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx
+++ b/i18n/pt-BR/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx
@@ -13,9 +13,9 @@ Este guia lista os diferentes eventos de webhook do Logto e explica quando cada
| Tipo de evento | Descrição |
| ----------------- | ----------------------------------------------------------------------------------- |
-| PostRegister | Um usuário cria com sucesso uma nova conta pela interface de usuário. |
-| PostSignIn | Um usuário faz login com sucesso pela interface de usuário. |
-| PostResetPassword | A senha de um usuário é redefinida com sucesso pelo fluxo de "Esqueci minha senha". |
+| PostRegister | Um usuário cria com sucesso uma nova conta através da interface de usuário. |
+| PostSignIn | Um usuário faz login com sucesso através da interface de usuário. |
+| PostResetPassword | A senha de um usuário é redefinida com sucesso através do fluxo "Esqueceu a senha". |
## Eventos de hook de mutação de dados \{#data-mutation-hook-events}
@@ -24,43 +24,43 @@ Este guia lista os diferentes eventos de webhook do Logto e explica quando cada
| Tipo de evento | Descrição |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| User.Created | Uma nova conta de usuário é criada. |
-| User.Deleted | Uma conta de usuário é excluída. |
+| User.Deleted | Uma conta de usuário é deletada. |
| User.Data.Updated | Os dados do perfil do usuário são atualizados, por exemplo, email, avatar, custom.data, identificador social, etc. |
| User.SuspensionStatus.Updated | O status de suspensão do usuário é alterado (suspenso ou reativado). |
-### Papel (Role) \{#role}
+### Papel \{#role}
-| Tipo de evento | Descrição |
-| ------------------- | -------------------------------------------------------------------------------------------- |
-| Role.Created | Um novo papel é criado. |
-| Role.Deleted | Um papel é excluído. |
-| Role.Data.Updated | Os dados de um papel são atualizados, por exemplo, nome do papel, descrição e status padrão. |
-| Role.Scopes.Updated | Permissões atribuídas a um papel são adicionadas ou removidas. |
+| Tipo de evento | Descrição |
+| ------------------- | ----------------------------------------------------------------------------------------------------- |
+| Role.Created | Um novo papel é criado. |
+| Role.Deleted | Um papel é deletado. |
+| Role.Data.Updated | Os dados de um papel são atualizados, por exemplo, nome do papel, descrição e status de papel padrão. |
+| Role.Scopes.Updated | Permissões atribuídas a um papel são adicionadas ou removidas. |
### Permissão (Escopo) \{#permission-scope}
| Tipo de evento | Descrição |
| ------------------ | -------------------------------------------------------------------------------------- |
| Scope.Created | Uma nova permissão de API é criada. |
-| Scope.Deleted | Uma permissão de API é excluída. |
+| Scope.Deleted | Uma permissão de API é deletada. |
| Scope.Data.Updated | Os dados de uma permissão de API são atualizados, por exemplo, descrição da permissão. |
-### Organização (Organization) \{#organization}
+### Organização \{#organization}
-| Tipo de evento | Descrição |
-| ------------------------------- | -------------------------------------------------------------------------------------------- |
-| Organization.Created | Uma nova organização é criada. |
-| Organization.Deleted | Uma organização é excluída. |
-| Organization.Data.Updated | Os dados de uma organização são atualizados, por exemplo, nome, descrição, custom.data, etc. |
-| Organization.Membership.Updated | Membros são adicionados ou removidos de uma organização. |
+| Tipo de evento | Descrição |
+| ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Organization.Created | Uma nova organização é criada. |
+| Organization.Deleted | Uma organização é deletada. |
+| Organization.Data.Updated | Os dados de uma organização são atualizados, por exemplo, nome da organização, descrição, custom.data, etc. |
+| Organization.Membership.Updated | Usuários ou aplicativos são adicionados ou removidos de uma organização. O payload inclui [campos delta de associação](/developers/webhooks/webhooks-request#organizationmembershipupdated-payload). |
-### Papel da organização (Organization role) \{#organization-role}
+### Papel da organização \{#organization-role}
| Tipo de evento | Descrição |
| ------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| OrganizationRole.Created | Um novo papel de organização é criado. |
-| OrganizationRole.Deleted | Um papel de organização é excluído. |
-| OrganizationRole.Data.Updated | Os dados de um papel de organização são atualizados, por exemplo, nome e descrição do papel da organização. |
+| OrganizationRole.Deleted | Um papel de organização é deletado. |
+| OrganizationRole.Data.Updated | Os dados de um papel de organização são atualizados, por exemplo, nome e descrição do papel de organização. |
| OrganizationRole.Scopes.Updated | Permissões atribuídas a um papel de organização são adicionadas ou removidas. |
### Permissão da organização (escopo) \{#organization-permission-scope}
@@ -68,10 +68,10 @@ Este guia lista os diferentes eventos de webhook do Logto e explica quando cada
| Tipo de evento | Descrição |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------- |
| OrganizationScope.Created | Uma nova permissão de organização é criada. |
-| OrganizationScope.Deleted | Uma permissão de organização é excluída. |
-| OrganizationScope.Data.Updated | Os dados de uma permissão de organização são atualizados, por exemplo, descrição da permissão da organização. |
+| OrganizationScope.Deleted | Uma permissão de organização é deletada. |
+| OrganizationScope.Data.Updated | Os dados de uma permissão de organização são atualizados, por exemplo, descrição da permissão de organização. |
-### Eventos disparados pela Management API \{#management-api-triggered-events}
+### Eventos acionados pela Management API \{#management-api-triggered-events}
| Endpoint da API | Evento |
| ---------------------------------------------------------- | ----------------------------------------------------------- |
@@ -96,6 +96,10 @@ Este guia lista os diferentes eventos de webhook do Logto e explica quando cada
| PUT /organizations/:id/users | Organization.Membership.Updated |
| POST /organizations/:id/users | Organization.Membership.Updated |
| DELETE /organizations/:id/users/:userId | Organization.Membership.Updated |
+| PUT /organizations/:id/applications | Organization.Membership.Updated |
+| POST /organizations/:id/applications | Organization.Membership.Updated |
+| DELETE /organizations/:id/applications/:applicationId | Organization.Membership.Updated |
+| PUT /organization-invitations/:id/status (Accepted) | Organization.Membership.Updated |
| POST /organization-roles | OrganizationRole.Created, (OrganizationRole.Scopes.Updated) |
| DELETE /organization-roles/:id | OrganizationRole.Deleted |
| PATCH /organization-roles/:id | OrganizationRole.Data.Updated |
@@ -106,33 +110,34 @@ Este guia lista os diferentes eventos de webhook do Logto e explica quando cada
| POST /organization-roles/:id/scopes | OrganizationRole.Scopes.Updated |
| DELETE /organization-roles/:id/scopes/:organizationScopeId | OrganizationRole.Scopes.Updated |
-### Eventos disparados pela Experience API \{#experience-api-triggered-events}
+### Eventos acionados pela Experience API \{#experience-api-triggered-events}
-| Ação de interação do usuário | Evento |
-| --------------------------------------- | ----------------- |
-| Vinculação de email/telefone do usuário | User.Data.Updated |
-| Vinculação de MFA do usuário | User.Data.Updated |
-| Vinculação social/SSO do usuário | User.Data.Updated |
-| Redefinição de senha do usuário | User.Data.Updated |
-| Registro de usuário | User.Created |
+| Ação de interação do usuário | Evento |
+| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------- |
+| Vinculação de email / telefone do usuário | User.Data.Updated |
+| Vinculação de MFAs do usuário | User.Data.Updated |
+| Vinculação social / SSO do usuário | User.Data.Updated |
+| Redefinição de senha do usuário | User.Data.Updated |
+| Registro de usuário | User.Created |
+| Usuário provisionado automaticamente em uma organização via [provisionamento Just-in-Time](/organizations/just-in-time-provisioning) (correspondência de domínio de email ou conector SSO corporativo) | Organization.Membership.Updated |
## Eventos de hook de exceção \{#exception-hook-events}
### Segurança \{#security}
-| Tipo de evento | Descrição |
-| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| Identifier.Lockout | Uma conta de usuário é bloqueada devido a tentativas consecutivas de verificação de identidade falhadas. Pode ser disparado nos seguintes fluxos:
- Falha na verificação de senha
- Falha na verificação de código
- Falha na verificação de token único
|
+| Tipo de evento | Descrição |
+| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Identifier.Lockout | Uma conta de usuário é bloqueada devido a tentativas consecutivas de verificação de identidade falhadas. Pode ser acionado nos seguintes fluxos:
- Falha na verificação de senha
- Falha na verificação de código
- Falha na verificação de token único
|
-## Perguntas frequentes (FAQs) \{#faqs}
+## FAQs \{#faqs}
-### Qual a diferença entre `PostRegister` e `User.Created`? \{#whats-the-difference-between-postregister-and-usercreated}
+### Qual é a diferença entre `PostRegister` e `User.Created`? \{#whats-the-difference-between-postregister-and-usercreated}
-`PostRegister` é disparado quando um usuário cria com sucesso uma nova conta pelo fluxo de cadastro do usuário; `User.Created` é disparado quando uma nova conta de usuário é criada através da Management API.
+`PostRegister` é acionado quando um usuário cria com sucesso uma nova conta através do fluxo de inscrição do usuário; `User.Created` é acionado quando uma nova conta de usuário é criada através da Management API.
diff --git a/i18n/pt-BR/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx b/i18n/pt-BR/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx
index 611a2caea62..080dbab2d3c 100644
--- a/i18n/pt-BR/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx
+++ b/i18n/pt-BR/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx
@@ -5,25 +5,62 @@ sidebar_label: Requisição de Webhooks
sidebar_position: 4
---
-# Requisição de Webhooks
+# Solicitação de Webhooks
-Uma vez que um evento de hook válido é emitido, o Logto encontrará os webhooks correspondentes e enviará uma requisição POST por configuração de hook.
+Quando um evento de webhook é disparado, o Logto envia uma solicitação `POST` para cada endpoint inscrito nele. O catálogo completo de eventos está em [Eventos de Webhooks](/developers/webhooks/webhooks-events); esta página documenta o **formato da solicitação** que o Logto entrega.
-## Cabeçalhos da requisição \{#request-headers}
+## Cabeçalhos da solicitação \{#request-headers}
-| Chave | Personalizável | Observações |
-| ----------------------- | -------------- | --------------------------------------------------------------------------------------------------------------- |
-| user-agent | ✅ | `Logto (https://logto.io/)` por padrão. |
-| content-type | ✅ | `application/json` por padrão. |
-| logto-signature-sha-256 | | a assinatura do corpo da requisição, consulte [protegendo seus webhooks](/developers/webhooks/secure-webhooks). |
+| Chave | Personalizável | Observações |
+| ----------------------- | -------------- | ---------------------------------------------------------------------------------------------------------- |
+| user-agent | ✅ | `Logto (https://logto.io/)` por padrão. |
+| content-type | ✅ | `application/json` por padrão. |
+| logto-signature-sha-256 | | Assinatura do corpo da solicitação. Veja [protegendo seus webhooks](/developers/webhooks/secure-webhooks). |
-Você pode sobrescrever cabeçalhos personalizáveis [personalizando os cabeçalhos da requisição](/developers/webhooks/configure-webhooks/#secure-webhook) com a mesma chave.
+Cabeçalhos personalizáveis podem ser substituídos através da configuração de [webhook seguro](/developers/webhooks/configure-webhooks/#secure-webhook).
-## Corpo da requisição de eventos de interaction hook \{#interaction-hook-events-request-body}
+## Visão geral do corpo da solicitação \{#request-body-overview}
-Eventos disponíveis: `PostRegister`, `PostSignIn`, `PostResetPassword`
+O corpo é um objeto JSON. Seu formato exato depende de qual família o evento pertence:
-O corpo da requisição é um objeto JSON que contém três tipos de campo de dados:
+| Família | Eventos | Quando é disparado |
+| -------------------- | -------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
+| **Fluxo de usuário** | `PostRegister`, `PostSignIn`, `PostResetPassword` | Um usuário completa um fluxo de cadastro, login ou redefinição de senha tratado pela Experience API. |
+| **Mutação de dados** | `User.*`, `Role.*`, `Scope.*`, `Organization.*`, `OrganizationRole.*`, `OrganizationScope.*` | O modelo de dados subjacente é alterado — por uma chamada da Management API ou por um fluxo de usuário na Experience API. |
+| **Exceção** | `Identifier.Lockout` | Um incidente de segurança — por exemplo, uma conta bloqueada após tentativas consecutivas de verificação falhadas. |
+
+Cada família compartilha um pequeno conjunto de [campos comuns](#common-fields). Cada família então adiciona seus próprios campos de contexto de solicitação, além de uma carga útil específica do evento.
+
+### Campos comuns \{#common-fields}
+
+Presentes em todas as entregas, independentemente da família:
+
+| Campo | Tipo | Opcional | Notas |
+| --------- | -------- | -------- | ------------------------------------------------------- |
+| hookId | `string` | | O identificador de configuração do webhook no Logto. |
+| event | `string` | | O evento que disparou esta entrega. |
+| createdAt | `string` | | O horário de criação da carga útil no formato ISO 8601. |
+| userAgent | `string` | ✅ | O user-agent da solicitação que disparou o evento. |
+
+Cada família também inclui o endereço IP da solicitação que disparou o evento — sob o nome do campo `userIp` para eventos de fluxo de usuário e `ip` para eventos de mutação de dados e exceção. As semânticas são idênticas; a diferença de nome histórica é preservada para compatibilidade retroativa.
+
+## Cargas úteis de eventos de fluxo de usuário \{#user-flow-event-payloads}
+
+**Eventos:** `PostRegister`, `PostSignIn`, `PostResetPassword`.
+
+Disparado quando um usuário completa um fluxo de cadastro, login ou redefinição de senha tratado pela Experience API. Além dos [campos comuns](#common-fields), o corpo contém:
+
+| Campo | Tipo | Opcional | Notas |
+| ---------------- | -------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| interactionEvent | `'SignIn' \| 'Register' \| 'ForgotPassword'` | | O tipo de evento de fluxo de usuário. Mapeia para `PostSignIn` / `PostRegister` / `PostResetPassword` respectivamente. O nome do campo mantém a nomenclatura histórica "interaction". |
+| sessionId | `string` | ✅ | O ID da Sessão (não o ID de Interação) para este evento, se aplicável. |
+| userIp | `string` | ✅ | O endereço IP da solicitação que disparou o evento. |
+| userId | `string` | ✅ | O ID do Usuário associado a este evento, se aplicável. |
+| user | `UserEntity` | ✅ | A entidade de usuário associada a este evento, se aplicável. |
+| applicationId | `string` | ✅ | O ID do Aplicativo associado a este evento, se aplicável. |
+| application | `ApplicationEntity` | ✅ | A entidade de aplicativo associada a este evento, se aplicável. |
+
+#### Formatos de entidade \{#user-flow-entity-shapes}
```tsx
type UserEntity = {
@@ -60,77 +97,64 @@ type ApplicationEntity = {
};
```
-| Campo | Tipo | Opcional | Observações |
-| ---------------- | ------------------- | -------- | ---------------------------------------------------------------------- |
-| hookId | `string` | | O identificador no Logto. |
-| event | `string` | | Qual evento disparou este hook. |
-| createdAt | `string` | | O horário de criação do payload em formato ISO. |
-| interactionEvent | `string` | | O evento de interação que disparou este hook. |
-| sessionId | `string` | ✅ | O ID da sessão (não o ID de interação) para este evento, se aplicável. |
-| userAgent | `string` | ✅ | O user-agent da requisição que disparou este hook. |
-| userIp | `string` | ✅ | O endereço IP da requisição que disparou este hook. |
-| userId | `string` | ✅ | O ID do usuário relacionado a este evento, se aplicável. |
-| user | `UserEntity` | ✅ | A entidade de usuário relacionada a este evento, se aplicável. |
-| applicationId | `string` | ✅ | O ID do aplicativo relacionado a este evento, se aplicável. |
-| application | `ApplicationEntity` | ✅ | As informações do aplicativo relacionado a este evento, se aplicável. |
+Veja [Usuários](/user-management/user-data) e [Aplicativos](/integrate-logto/application-data-structure) para a referência completa dos campos.
-Veja as referências de [Usuários](/user-management/user-data) e [Aplicativos](/integrate-logto/application-data-structure) para explicações detalhadas dos campos.
+## Cargas úteis de eventos de mutação de dados \{#data-mutation-event-payloads}
-## Corpo da requisição de eventos de data mutation hook \{#data-mutation-hook-events-request-body}
+**Eventos:** todos os eventos sob `User.*`, `Role.*`, `Scope.*`, `Organization.*`, `OrganizationRole.*`, `OrganizationScope.*` — veja [Eventos de Webhooks → Eventos de mutação de dados](/developers/webhooks/webhooks-events#data-mutation-hook-events) para o catálogo completo.
-### Campos padrão do corpo da requisição \{#standard-request-body-fields}
+O corpo sempre contém:
-| Campo | Tipo | Opcional | Observações |
-| --------- | -------- | -------- | ----------------------------------------------- |
-| hookId | `string` | | O identificador no Logto. |
-| event | `string` | | Qual evento disparou este hook. |
-| createdAt | `string` | | O horário de criação do payload em formato ISO. |
-| userAgent | `string` | ✅ | O user-agent da requisição. |
-| ip | `string` | ✅ | O endereço IP da requisição. |
+- Os [campos comuns](#common-fields).
+- Um campo `ip` — o endereço IP da solicitação que disparou o evento (opcional, presente quando conhecido).
+- Um **contexto de API** descrevendo como a alteração foi disparada. O contexto é uma de duas variantes, dependendo da fonte do disparo:
+ - [Contexto da Experience API](#experience-api-context-fields) — quando a alteração veio de um fluxo voltado para o usuário.
+ - [Contexto da Management API](#management-api-context-fields) — quando a alteração veio de uma chamada direta da Management API.
+- Uma **carga útil específica do evento** — a entidade afetada em `data` e (para alguns eventos) campos adicionais de nível superior. Veja [cargas úteis de dados específicas do evento](#event-specific-data-payloads).
-### Campos de contexto de Interaction API no corpo \{#interaction-api-context-body-fields}
+### Campos de contexto da Experience API \{#experience-api-context-fields}
-Eventos de data mutation hook disparados por chamadas de API de interação do usuário.
+Presentes quando a alteração foi disparada por um fluxo voltado para o usuário na Experience API — por exemplo, `User.Created` durante o cadastro ou `User.Data.Updated` durante atualizações de perfil.
-Eventos disponíveis: `User.Created`, `User.Data.Updated`
+| Campo | Tipo | Opcional | Notas |
+| ---------------- | -------------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------- |
+| interactionEvent | `'SignIn' \| 'Register' \| 'ForgotPassword'` | ✅ | O tipo de evento de fluxo de usuário que produziu a alteração. O nome do campo mantém a nomenclatura histórica "interaction". |
+| sessionId | `string` | ✅ | O ID da Sessão (não o ID de Interação) para este evento, se aplicável. |
+| applicationId | `string` | ✅ | O ID do Aplicativo, se aplicável. |
+| application | `ApplicationEntity` | ✅ | A entidade de aplicativo, se aplicável. |
-| Campo | Tipo | Opcional | Observações |
-| ---------------- | ------------------- | -------- | ---------------------------------------------------------------------- |
-| interactionEvent | `string` | ✅ | O evento de interação que disparou este hook. |
-| sessionId | `string` | ✅ | O ID da sessão (não o ID de interação) para este evento, se aplicável. |
-| applicationId | `string` | ✅ | O ID do aplicativo relacionado a este evento, se aplicável. |
-| application | `ApplicationEntity` | ✅ | As informações do aplicativo relacionado a este evento, se aplicável. |
+### Campos de contexto da Management API \{#management-api-context-fields}
-### Campos de contexto de Management API no corpo \{#management-api-context-body-fields}
+Presentes quando a alteração foi disparada por uma chamada da Management API.
-Eventos de data mutation hook disparados por chamadas de Management API.
+| Campo | Tipo | Opcional | Notas |
+| ------------ | -------- | -------- | -------------------------------------------------------------------------------------------------------------- |
+| path | `string` | ✅ | O caminho da chamada de API que disparou este hook. |
+| method | `string` | ✅ | O método HTTP da chamada de API. |
+| status | `number` | ✅ | O código de status da resposta da chamada de API. |
+| params | `object` | ✅ | Os parâmetros de caminho koa da chamada de API. |
+| matchedRoute | `string` | ✅ | A rota correspondente koa. O Logto usa este campo para corresponder filtros de eventos de webhook habilitados. |
-| Campo | Tipo | Opcional | Observações |
-| ------------ | -------- | -------- | --------------------------------------------------------------------------------------------------------------------------------- |
-| path | `string` | ✅ | O caminho da chamada de API que disparou este hook. |
-| method | `string` | ✅ | O método da chamada de API que disparou este hook. |
-| status | `number` | ✅ | O código de status da resposta da chamada de API que disparou este hook. |
-| params | `object` | ✅ | Os parâmetros de caminho koa da chamada de API que disparou este hook. |
-| matchedRoute | `string` | ✅ | A rota koa correspondente da chamada de API que disparou este hook. O Logto usa este campo para corresponder eventos habilitados. |
+### Cargas úteis de dados específicas do evento \{#event-specific-data-payloads}
-### Campos de payload de dados no corpo \{#data-payload-body-fields}
+Todo evento de mutação de dados inclui um campo `data` de nível superior que carrega a entidade afetada, ou `null` quando a alteração não pode ser resumida como uma única entidade (eventos de exclusão e associação). Alguns eventos também incluem campos de nível superior específicos do evento além de `data` — `Organization.Membership.Updated` é um desses casos, documentado abaixo.
-**Eventos de usuário**
+#### Eventos de usuário \{#user-events}
-| Evento | Campo | Tipo | Opcional | Observações |
-| ----------------- | ----- | ---------- | -------- | -------------------------------------------------- |
-| User.Created | data | UserEntity | | A entidade de usuário criada para este evento. |
-| User.Data.Updated | data | UserEntity | | A entidade de usuário atualizada para este evento. |
-| User.Deleted | data | null | / | |
+| Evento | Campo | Tipo | Opcional | Notas |
+| ----------------- | ----- | ------------ | -------- | --------------------------------- |
+| User.Created | data | `UserEntity` | | A entidade de usuário criada. |
+| User.Data.Updated | data | `UserEntity` | | A entidade de usuário atualizada. |
+| User.Deleted | data | `null` | / | |
-**Eventos de papel (Role)**
+#### Eventos de papel \{#role-events}
```tsx
type Role = {
id: string;
name: string;
description: string;
- type: 'User' | 'MachineToMachine';
+ type: 'User' \| 'MachineToMachine';
isDefault: boolean;
};
```
@@ -145,23 +169,23 @@ type Scope = {
};
```
-| Evento | Campo | Tipo | Opcional | Observações |
-| ------------------ | ------ | ------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| Role.Created | data | Role | | A entidade de papel criada para este evento. |
-| Role.Data.Updated | data | Role | | A entidade de papel atualizada para este evento. |
-| Role.Deleted | data | null | | |
-| Role.Scope.Updated | data | Scope[] | | Os escopos atualizados atribuídos ao papel. |
-| Role.Scope.Updated | roleId | string | ✅ | O ID do papel ao qual os escopos estão atribuídos. (Disponível apenas quando o evento foi disparado por criação de novo papel com escopos pré-atribuídos) |
+| Evento | Campo | Tipo | Opcional | Notas |
+| ------------------- | ------ | --------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Role.Created | data | `Role` | | A entidade de papel criada. |
+| Role.Data.Updated | data | `Role` | | A entidade de papel atualizada. |
+| Role.Deleted | data | `null` | / | |
+| Role.Scopes.Updated | data | `Scope[]` | | Os escopos atualizados atribuídos ao papel. |
+| Role.Scopes.Updated | roleId | `string` | ✅ | O ID do papel ao qual os escopos são atribuídos. (Disponível apenas quando o evento foi disparado pela criação de um papel com escopos pré-atribuídos.) |
-**Eventos de permissão (Scope)**
+#### Eventos de permissão (escopo) \{#permission-events}
-| Evento | Campo | Tipo | Opcional | Observações |
-| ------------------ | ----- | ----- | -------- | ------------------------------------------------- |
-| Scope.Created | data | Scope | | A entidade de escopo criada para este evento. |
-| Scope.Data.Updated | data | Scope | | A entidade de escopo atualizada para este evento. |
-| Scope.Deleted | data | null | / | |
+| Evento | Campo | Tipo | Opcional | Notas |
+| ------------------ | ----- | ------- | -------- | -------------------------------- |
+| Scope.Created | data | `Scope` | | A entidade de escopo criada. |
+| Scope.Data.Updated | data | `Scope` | | A entidade de escopo atualizada. |
+| Scope.Deleted | data | `null` | / | |
-**Eventos de organização (Organization)**
+#### Eventos de organização \{#organization-events}
```tsx
type Organization = {
@@ -173,14 +197,139 @@ type Organization = {
};
```
-| Evento | Campo | Tipo | Opcional | Observações |
-| ------------------------------- | ----- | ------------ | -------- | ------------------------------------------------------ |
-| Organization.Created | data | Organization | | A entidade de organização criada para este evento. |
-| Organization.Data.Updated | data | Organization | | A entidade de organização atualizada para este evento. |
-| Organization.Deleted | data | null | / | |
-| Organization.Membership.Updated | data | null | / | |
+| Evento | Campo | Tipo | Opcional | Notas |
+| ------------------------------- | ----- | -------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Organization.Created | data | `Organization` | | A entidade de organização criada. |
+| Organization.Data.Updated | data | `Organization` | | A entidade de organização atualizada. |
+| Organization.Deleted | data | `null` | / | |
+| Organization.Membership.Updated | data | `null` | / | A alteração é descrita por matrizes delta opcionais de nível superior. Veja [carga útil de Organization.Membership.Updated](#organizationmembershipupdated-payload) abaixo. |
+
+##### Carga útil de Organization.Membership.Updated \{#organizationmembershipupdated-payload}
+
+Além dos [campos comuns](#common-fields) e dos campos de contexto de API correspondentes à origem do gatilho ([contexto da Management API](#management-api-context-fields) para rotas da Management API, [contexto da Experience API](#experience-api-context-fields) para o provisionamento just-in-time), o evento `Organization.Membership.Updated` carrega um `organizationId` mais matrizes delta opcionais no nível superior da carga útil (ao lado de `event`, `createdAt`, etc.; **não** dentro de `data`, que é sempre `null` para este evento).
+
+| Campo | Tipo | Opcional | Notas |
+| --------------------- | ---------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| organizationId | `string` | | A organização cuja associação foi alterada. |
+| addedUserIds | `string[]` | ✅ | IDs de usuários recém-adicionados por este disparo. Omitido quando nenhum usuário foi adicionado, ou quando o disparo não afeta a associação de usuários. |
+| removedUserIds | `string[]` | ✅ | IDs de usuários removidos por este disparo. Omitido quando nenhum usuário foi removido. |
+| addedApplicationIds | `string[]` | ✅ | IDs de aplicativos recém-adicionados. Omitido quando nenhum aplicativo foi adicionado, ou quando o disparo não afeta a associação de aplicativos. |
+| removedApplicationIds | `string[]` | ✅ | IDs de aplicativos removidos. Omitido quando nenhum aplicativo foi removido. |
+
+As quatro matrizes delta são **opcionais e aditivas** — elas não alteram o formato da carga útil existente para consumidores que não as esperam, e o campo legado `data: null` ainda é emitido inalterado.
+
+###### Disparos e quais campos delta eles podem emitir \{#membership-triggers}
+
+| Disparo | Campos delta possíveis |
+| -------------------------------------------------------------------------- | ---------------------------------------------- |
+| `POST /organizations/:id/users` | `addedUserIds` |
+| `PUT /organizations/:id/users` | `addedUserIds`, `removedUserIds` |
+| `DELETE /organizations/:id/users/:userId` | `removedUserIds` |
+| `POST /organizations/:id/applications` | `addedApplicationIds` |
+| `PUT /organizations/:id/applications` | `addedApplicationIds`, `removedApplicationIds` |
+| `DELETE /organizations/:id/applications/:applicationId` | `removedApplicationIds` |
+| `PUT /organization-invitations/:id/status` (`Accepted`) | `addedUserIds` |
+| Provisionamento just-in-time ao adicionar o usuário a uma nova organização | `addedUserIds` |
+
+###### Deltas vazios são omitidos — ausente ≠ alteração vazia \{#empty-deltas-are-omitted}
+
+Matrizes delta vazias são **omitidas inteiramente** da carga útil. Por exemplo, um `PUT /organizations/:id/users` que substitui o conjunto de associação pelo conjunto existente não produz nenhuma alteração real, e a carga útil se reduz apenas a `{ organizationId }` com todos os quatro campos delta ausentes. O mesmo se aplica a uma re-adição de um membro existente, uma re-aceitação de um convite por um usuário que já é membro que já é membro.
+
+**Os consumidores devem tratar um campo ausente como "nenhuma alteração desse lado", não como "uma alteração vazia".**
+
+###### Limite por matriz (truncamento silencioso) \{#membership-delta-cap}
+
+Cada matriz delta é limitada a **5000 entradas**. Quando uma única chamada da Management API adiciona ou remove mais de 5000 usuários (ou aplicativos) em uma operação, a matriz delta correspondente é truncada silenciosamente para suas primeiras 5000 entradas — **não há marcador na carga útil** indicando que um limite foi atingido.
+
+Se sua aplicação realiza operações administrativas em massa que podem afetar plausivelmente mais de 5000 membros em uma chamada, trate uma matriz de exatamente 5000 entradas como um sinal para reconciliar a associação autoritativa via Management API:
+
+- `GET /organizations/:id/users` — associação completa de usuários.
+- `GET /organizations/:id/applications` — associação completa de aplicativos.
+
+Isso segue o mesmo padrão do evento `push` do GitHub, que limita `commits` a 20 entradas e aponta os consumidores para a API de comparação para a lista completa.
+
+###### Ignorando eventos sem operação \{#skipping-no-op-events}
+
+Cada `PUT` contra as rotas de associação emite um evento independentemente de algo realmente ter mudado — para que qualquer chamada de substituição de estado tenha pelo menos uma entrega de webhook para fins de auditoria. Para ignorar entregas sem operação no lado do consumidor, filtre pela presença de matriz delta:
+
+```ts
+if (
+ payload.addedUserIds?.length ||
+ payload.removedUserIds?.length ||
+ payload.addedApplicationIds?.length ||
+ payload.removedApplicationIds?.length
+) {
+ // alteração real de associação — lide com isso
+}
+```
-**Eventos de OrganizationRole**
+`?.length` é falso tanto para `undefined` quanto para `[]`, então o mesmo predicado é robusto, seja o campo ausente ou (em algum futuro hipotético) emitido como uma matriz vazia.
+
+###### Exemplos de cargas úteis \{#membership-example-payloads}
+
+**Adicionar um usuário (`POST /organizations/:id/users`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "addedUserIds": ["u_001"]
+}
+```
+
+**Substituir o conjunto de associação de usuários (`PUT /organizations/:id/users`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "addedUserIds": ["u_002"],
+ "removedUserIds": ["u_001"]
+}
+```
+
+**Remover um usuário (`DELETE /organizations/:id/users/:userId`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "removedUserIds": ["u_001"]
+}
+```
+
+**Adicionar um aplicativo (`POST /organizations/:id/applications`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "addedApplicationIds": ["app_xyz"]
+}
+```
+
+**Re-adicionar um membro existente, operação sem efeito `PUT`, ou re-aceitação de um convite já membro (sem alteração real):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc"
+}
+```
+
+**Operação em massa que atinge o limite de 5000 (truncado silenciosamente):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "removedUserIds": ["u_0001", "u_0002", "/* … exatamente 5000 entradas no total */"]
+}
+```
+
+Ver uma matriz de exatamente 5000 entradas deve acionar uma reconciliação `GET /organizations/:id/users` (ou `/applications`).
+
+#### Eventos de papel de organização \{#organization-role-events}
```tsx
type OrganizationRole = {
@@ -198,27 +347,32 @@ type OrganizationScope = {
};
```
-| Evento | Campo | Tipo | Opcional | Observações |
-| ------------------------------ | ------------------ | ---------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| OrganizationRole.Created | data | OrganizationRole | | A entidade de papel de organização criada para este evento. |
-| OrganizationRole.Data.Updated | data | OrganizationRole | | A entidade de papel de organização atualizada para este evento. |
-| OrganizationRole.Deleted | data | null | / | |
-| OrganizationRole.Scope.Updated | data | null | / | |
-| OrganizationRole.Scope.Updated | organizationRoleId | string | ✅ | O ID do papel ao qual os escopos estão atribuídos. (Disponível apenas quando o evento foi disparado por criação de novo papel com escopos pré-atribuídos) |
+| Evento | Campo | Tipo | Opcional | Notas |
+| ------------------------------- | ------------------ | ------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| OrganizationRole.Created | data | `OrganizationRole` | | A entidade de papel de organização criada. |
+| OrganizationRole.Data.Updated | data | `OrganizationRole` | | A entidade de papel de organização atualizada. |
+| OrganizationRole.Deleted | data | `null` | / | |
+| OrganizationRole.Scopes.Updated | data | `null` | / | |
+| OrganizationRole.Scopes.Updated | organizationRoleId | `string` | ✅ | O ID do papel ao qual os escopos são atribuídos. (Disponível apenas quando o evento foi disparado pela criação de um papel com escopos pré-atribuídos.) |
+
+#### Eventos de permissão de organização (escopo) \{#organization-permission-events}
-**Eventos de permissão de organização (OrganizationScope)**
+| Evento | Campo | Tipo | Opcional | Notas |
+| ------------------------------ | ----- | ------------------- | -------- | ----------------------------------------------- |
+| OrganizationScope.Created | data | `OrganizationScope` | | A entidade de escopo de organização criada. |
+| OrganizationScope.Data.Updated | data | `OrganizationScope` | | A entidade de escopo de organização atualizada. |
+| OrganizationScope.Deleted | data | `null` | / | |
-| Evento | Campo | Tipo | Opcional | Observações |
-| ------------------------------ | ----- | ----------------- | -------- | ----------------------------------------------- |
-| OrganizationScope.Created | data | OrganizationScope | | A entidade de escopo de organização criada. |
-| OrganizationScope.Data.Updated | data | OrganizationScope | | A entidade de escopo de organização atualizada. |
-| OrganizationScope.Deleted | data | null | / | |
+## Cargas úteis de eventos de exceção \{#exception-event-payloads}
-## Corpo da requisição de eventos de exception hook \{#exception-hook-events-request-body}
+**Eventos:** `Identifier.Lockout`.
-Eventos disponíveis: `Identifier.Lockout`
+Disparado em incidentes de segurança — por exemplo, uma conta bloqueada após tentativas consecutivas de verificação falhadas. Esses eventos sempre se originam de um fluxo voltado para o usuário, então o corpo contém:
-O corpo da requisição é um objeto JSON que contém os campos padrão do corpo da requisição e campos adicionais conforme abaixo:
+- Os [campos comuns](#common-fields).
+- O campo `ip` (mesmo formato que eventos de mutação de dados).
+- Os [campos de contexto da Experience API](#experience-api-context-fields).
+- Os campos específicos da exceção abaixo.
```tsx
enum SignInIdentifier {
@@ -228,16 +382,7 @@ enum SignInIdentifier {
}
```
-| Campo | Tipo | Opcional | Observações |
-| ---------------- | ------------------- | -------- | ------------------------------------------------------------------------------------ |
-| hookId | `string` | | O identificador no Logto. |
-| event | `string` | | Qual evento disparou este hook. |
-| createdAt | `string` | | O horário de criação do payload em formato ISO. |
-| userAgent | `string` | ✅ | O user-agent da requisição. |
-| ip | `string` | ✅ | O endereço IP da requisição. |
-| interactionEvent | `string` | ✅ | O evento de interação que disparou este hook. |
-| sessionId | `string` | ✅ | O ID da sessão (não o ID de interação) para este evento, se aplicável. |
-| applicationId | `string` | ✅ | O ID do aplicativo relacionado a este evento, se aplicável. |
-| application | `ApplicationEntity` | ✅ | As informações do aplicativo relacionado a este evento, se aplicável. |
-| type | `SignInIdentifier` | | O tipo de identificador do usuário, por exemplo, email, telefone ou nome de usuário. |
-| value | `string` | | O valor do identificador do usuário que disparou o bloqueio. |
+| Campo | Tipo | Opcional | Notas |
+| ----- | ------------------ | -------- | ------------------------------------------------------------------------------------ |
+| type | `SignInIdentifier` | | O tipo de identificador do usuário, por exemplo, email, telefone ou nome de usuário. |
+| value | `string` | | O valor do identificador do usuário que disparou o bloqueio. |
diff --git a/i18n/th/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx b/i18n/th/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx
index 1dfe1bc24c1..836667ce584 100644
--- a/i18n/th/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx
+++ b/i18n/th/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx
@@ -5,70 +5,70 @@ sidebar_label: เหตุการณ์ Webhook
sidebar_position: 3
---
-# เหตุการณ์ Webhook
+# เหตุการณ์ Webhooks
-คู่มือนี้จะแสดงรายการเหตุการณ์ webhook ของ Logto ที่แตกต่างกันและอธิบายว่าแต่ละเหตุการณ์เกิดขึ้นเมื่อใด
+คู่มือนี้แสดงรายการเหตุการณ์ Webhook ของ Logto ที่แตกต่างกันและอธิบายว่าแต่ละเหตุการณ์เกิดขึ้นเมื่อใด
-## เหตุการณ์ hook จากการโต้ตอบของผู้ใช้ \{#user-interaction-hook-events}
+## เหตุการณ์การโต้ตอบของผู้ใช้ \{#user-interaction-hook-events}
-| ประเภทเหตุการณ์ | คำอธิบาย |
-| ----------------- | --------------------------------------------------------- |
-| PostRegister | ผู้ใช้สร้างบัญชีใหม่สำเร็จผ่านอินเทอร์เฟซ UI |
-| PostSignIn | ผู้ใช้ลงชื่อเข้าใช้สำเร็จผ่านอินเทอร์เฟซ UI |
-| PostResetPassword | รหัสผ่านของผู้ใช้ถูกรีเซ็ตสำเร็จผ่านขั้นตอน "ลืมรหัสผ่าน" |
+| ประเภทเหตุการณ์ | คำอธิบาย |
+| ----------------- | ----------------------------------------------------------- |
+| PostRegister | ผู้ใช้สร้างบัญชีใหม่สำเร็จผ่านอินเทอร์เฟซ UI |
+| PostSignIn | ผู้ใช้ลงชื่อเข้าใช้สำเร็จผ่านอินเทอร์เฟซ UI |
+| PostResetPassword | รหัสผ่านของผู้ใช้ถูกรีเซ็ตสำเร็จผ่านกระบวนการ "ลืมรหัสผ่าน" |
-## เหตุการณ์ hook จากการเปลี่ยนแปลงข้อมูล \{#data-mutation-hook-events}
+## เหตุการณ์การเปลี่ยนแปลงข้อมูล \{#data-mutation-hook-events}
### ผู้ใช้ \{#user}
-| ประเภทเหตุการณ์ | คำอธิบาย |
-| ----------------------------- | --------------------------------------------------------------------------------- |
-| User.Created | มีการสร้างบัญชีผู้ใช้ใหม่ |
-| User.Deleted | มีการลบบัญชีผู้ใช้ออก |
-| User.Data.Updated | ข้อมูลโปรไฟล์ผู้ใช้ถูกอัปเดต เช่น อีเมล, อวาตาร์, custom.data, ตัวระบุโซเชียล ฯลฯ |
-| User.SuspensionStatus.Updated | สถานะการระงับบัญชีผู้ใช้ถูกเปลี่ยน (ระงับหรือเปิดใช้งานใหม่) |
+| ประเภทเหตุการณ์ | คำอธิบาย |
+| ----------------------------- | ------------------------------------------------------------------------------------- |
+| User.Created | สร้างบัญชีผู้ใช้ใหม่ |
+| User.Deleted | ลบบัญชีผู้ใช้ |
+| User.Data.Updated | ข้อมูลโปรไฟล์ผู้ใช้ถูกอัปเดต เช่น อีเมล, อวาตาร์, custom.data, ตัวระบุโซเชียล เป็นต้น |
+| User.SuspensionStatus.Updated | สถานะการระงับผู้ใช้ถูกเปลี่ยน (ถูกระงับหรือเปิดใช้งานใหม่) |
-### บทบาท (Role) \{#role}
+### บทบาท \{#role}
-| ประเภทเหตุการณ์ | คำอธิบาย |
-| ------------------- | -------------------------------------------------------------------- |
-| Role.Created | มีการสร้างบทบาทใหม่ |
-| Role.Deleted | มีการลบบทบาทออก |
-| Role.Data.Updated | ข้อมูลของบทบาทถูกอัปเดต เช่น ชื่อบทบาท, คำอธิบาย, สถานะบทบาทเริ่มต้น |
-| Role.Scopes.Updated | มีการเพิ่มหรือลบสิทธิ์ (permissions) ที่กำหนดให้กับบทบาท |
+| ประเภทเหตุการณ์ | คำอธิบาย |
+| ------------------- | ----------------------------------------------------------------------- |
+| Role.Created | สร้างบทบาทใหม่ |
+| Role.Deleted | ลบบทบาท |
+| Role.Data.Updated | ข้อมูลของบทบาทถูกอัปเดต เช่น ชื่อบทบาท, คำอธิบาย, และสถานะบทบาทเริ่มต้น |
+| Role.Scopes.Updated | สิทธิ์ที่กำหนดให้กับบทบาทถูกเพิ่มหรือลบ |
-### สิทธิ์ (ขอบเขต; Permission / Scope) \{#permission-scope}
+### สิทธิ์ (ขอบเขต) \{#permission-scope}
| ประเภทเหตุการณ์ | คำอธิบาย |
| ------------------ | ------------------------------------------------- |
-| Scope.Created | มีการสร้างสิทธิ์ API ใหม่ |
-| Scope.Deleted | มีการลบสิทธิ์ API ออก |
+| Scope.Created | สร้างสิทธิ์ API ใหม่ |
+| Scope.Deleted | ลบสิทธิ์ API |
| Scope.Data.Updated | ข้อมูลของสิทธิ์ API ถูกอัปเดต เช่น คำอธิบายสิทธิ์ |
-### องค์กร (Organization) \{#organization}
+### องค์กร \{#organization}
-| ประเภทเหตุการณ์ | คำอธิบาย |
-| ------------------------------- | ------------------------------------------------------------------- |
-| Organization.Created | มีการสร้างองค์กรใหม่ |
-| Organization.Deleted | มีการลบองค์กรออก |
-| Organization.Data.Updated | ข้อมูลขององค์กรถูกอัปเดต เช่น ชื่อองค์กร, คำอธิบาย, custom.data ฯลฯ |
-| Organization.Membership.Updated | มีการเพิ่มหรือลบสมาชิกในองค์กร |
+| ประเภทเหตุการณ์ | คำอธิบาย |
+| ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Organization.Created | สร้างองค์กรใหม่ |
+| Organization.Deleted | ลบองค์กร |
+| Organization.Data.Updated | ข้อมูลขององค์กรถูกอัปเดต เช่น ชื่อองค์กร, คำอธิบาย, custom.data เป็นต้น |
+| Organization.Membership.Updated | ผู้ใช้หรือแอปพลิเคชันถูกเพิ่มหรือลบออกจากองค์กร ข้อมูลที่ส่งมารวมถึง [ฟิลด์การเปลี่ยนแปลงสมาชิก](/developers/webhooks/webhooks-request#organizationmembershipupdated-payload) |
-### บทบาทขององค์กร (Organization role) \{#organization-role}
+### บทบาทขององค์กร \{#organization-role}
-| ประเภทเหตุการณ์ | คำอธิบาย |
-| ------------------------------- | ------------------------------------------------------------- |
-| OrganizationRole.Created | มีการสร้างบทบาทขององค์กรใหม่ |
-| OrganizationRole.Deleted | มีการลบบทบาทขององค์กรออก |
-| OrganizationRole.Data.Updated | ข้อมูลของบทบาทองค์กรถูกอัปเดต เช่น ชื่อบทบาทองค์กรและคำอธิบาย |
-| OrganizationRole.Scopes.Updated | มีการเพิ่มหรือลบสิทธิ์ที่กำหนดให้กับบทบาทขององค์กร |
+| ประเภทเหตุการณ์ | คำอธิบาย |
+| ------------------------------- | ------------------------------------------------------------------- |
+| OrganizationRole.Created | สร้างบทบาทขององค์กรใหม่ |
+| OrganizationRole.Deleted | ลบบทบาทขององค์กร |
+| OrganizationRole.Data.Updated | ข้อมูลของบทบาทขององค์กรถูกอัปเดต เช่น ชื่อบทบาทขององค์กรและคำอธิบาย |
+| OrganizationRole.Scopes.Updated | สิทธิ์ที่กำหนดให้กับบทบาทขององค์กรถูกเพิ่มหรือลบ |
-### สิทธิ์ขององค์กร (ขอบเขต; Organization permission / scope) \{#organization-permission-scope}
+### สิทธิ์ขององค์กร (ขอบเขต) \{#organization-permission-scope}
| ประเภทเหตุการณ์ | คำอธิบาย |
| ------------------------------ | -------------------------------------------------------------- |
-| OrganizationScope.Created | มีการสร้างสิทธิ์ขององค์กรใหม่ |
-| OrganizationScope.Deleted | มีการลบสิทธิ์ขององค์กรออก |
+| OrganizationScope.Created | สร้างสิทธิ์ขององค์กรใหม่ |
+| OrganizationScope.Deleted | ลบสิทธิ์ขององค์กร |
| OrganizationScope.Data.Updated | ข้อมูลของสิทธิ์ขององค์กรถูกอัปเดต เช่น คำอธิบายสิทธิ์ขององค์กร |
### เหตุการณ์ที่ถูกกระตุ้นโดย Management API \{#management-api-triggered-events}
@@ -96,6 +96,10 @@ sidebar_position: 3
| PUT /organizations/:id/users | Organization.Membership.Updated |
| POST /organizations/:id/users | Organization.Membership.Updated |
| DELETE /organizations/:id/users/:userId | Organization.Membership.Updated |
+| PUT /organizations/:id/applications | Organization.Membership.Updated |
+| POST /organizations/:id/applications | Organization.Membership.Updated |
+| DELETE /organizations/:id/applications/:applicationId | Organization.Membership.Updated |
+| PUT /organization-invitations/:id/status (Accepted) | Organization.Membership.Updated |
| POST /organization-roles | OrganizationRole.Created, (OrganizationRole.Scopes.Updated) |
| DELETE /organization-roles/:id | OrganizationRole.Deleted |
| PATCH /organization-roles/:id | OrganizationRole.Data.Updated |
@@ -108,31 +112,32 @@ sidebar_position: 3
### เหตุการณ์ที่ถูกกระตุ้นโดย Experience API \{#experience-api-triggered-events}
-| การกระทำของผู้ใช้ | เหตุการณ์ |
-| --------------------------------- | ----------------- |
-| การเชื่อมโยงอีเมล/โทรศัพท์ผู้ใช้ | User.Data.Updated |
-| การเชื่อมโยง MFA ของผู้ใช้ | User.Data.Updated |
-| การเชื่อมโยงโซเชียล/SSO ของผู้ใช้ | User.Data.Updated |
-| การรีเซ็ตรหัสผ่านผู้ใช้ | User.Data.Updated |
-| การลงทะเบียนผู้ใช้ | User.Created |
+| การกระทำการโต้ตอบของผู้ใช้ | เหตุการณ์ |
+| -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- |
+| การเชื่อมโยงอีเมล / โทรศัพท์ของผู้ใช้ | User.Data.Updated |
+| การเชื่อมโยง MFA ของผู้ใช้ | User.Data.Updated |
+| การเชื่อมโยงโซเชียล / SSO ของผู้ใช้ | User.Data.Updated |
+| การรีเซ็ตรหัสผ่านของผู้ใช้ | User.Data.Updated |
+| การลงทะเบียนของผู้ใช้ | User.Created |
+| ผู้ใช้ถูกจัดเตรียมอัตโนมัติในองค์กรผ่าน [การจัดเตรียมแบบ Just-in-Time](/organizations/just-in-time-provisioning) (การจับคู่โดเมนอีเมลหรือผู้ให้บริการ SSO ขององค์กร) | Organization.Membership.Updated |
-## เหตุการณ์ hook ข้อยกเว้น \{#exception-hook-events}
+## เหตุการณ์ข้อยกเว้น \{#exception-hook-events}
### ความปลอดภัย \{#security}
-| ประเภทเหตุการณ์ | คำอธิบาย |
-| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| Identifier.Lockout | บัญชีผู้ใช้ถูกล็อกเนื่องจากพยายามยืนยันตัวตนล้มเหลวติดต่อกัน สามารถถูกกระตุ้นในขั้นตอนต่อไปนี้:
- การตรวจสอบรหัสผ่านล้มเหลว
- การตรวจสอบรหัสยืนยันล้มเหลว
- การตรวจสอบโทเค็นแบบครั้งเดียวล้มเหลว
|
+| ประเภทเหตุการณ์ | คำอธิบาย |
+| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| Identifier.Lockout | บัญชีผู้ใช้ถูกล็อกเนื่องจากความพยายามยืนยันตัวตนที่ล้มเหลวติดต่อกัน สามารถถูกกระตุ้นในกระบวนการต่อไปนี้:
- การยืนยันรหัสผ่านล้มเหลว
- การยืนยันรหัสล้มเหลว
- การยืนยันโทเค็นครั้งเดียวล้มเหลว
|
## คำถามที่พบบ่อย \{#faqs}
-### ความแตกต่างระหว่าง `PostRegister` กับ `User.Created` คืออะไร? \{#whats-the-difference-between-postregister-and-usercreated}
+### ความแตกต่างระหว่าง `PostRegister` และ `User.Created` คืออะไร? \{#whats-the-difference-between-postregister-and-usercreated}
-`PostRegister` จะถูกกระตุ้นเมื่อผู้ใช้สร้างบัญชีใหม่สำเร็จผ่านขั้นตอนการสมัครของผู้ใช้; `User.Created` จะถูกกระตุ้นเมื่อมีการสร้างบัญชีผู้ใช้ใหม่ผ่าน Management API
+`PostRegister` ถูกกระตุ้นเมื่อผู้ใช้สร้างบัญชีใหม่สำเร็จผ่านกระบวนการลงทะเบียนของผู้ใช้; `User.Created` ถูกกระตุ้นเมื่อมีการสร้างบัญชีผู้ใช้ใหม่ผ่าน Management API
diff --git a/i18n/th/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx b/i18n/th/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx
index 1848cf3aa04..4d210efc80a 100644
--- a/i18n/th/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx
+++ b/i18n/th/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx
@@ -7,23 +7,60 @@ sidebar_position: 4
# คำขอ Webhooks
-เมื่อมีการปล่อยเหตุการณ์ hook ที่ถูกต้อง Logto จะค้นหา webhooks ที่เกี่ยวข้องและส่งคำขอ POST ต่อ hook config แต่ละรายการ
+เมื่อเหตุการณ์ webhook ถูกเรียกใช้ Logto จะส่งคำขอ `POST` ไปยังทุก endpoint ที่สมัครรับข้อมูลไว้ แคตตาล็อกเหตุการณ์ทั้งหมดอยู่ใน [Webhooks events](/developers/webhooks/webhooks-events); หน้านี้เอกสาร **รูปแบบของคำขอ** ที่ Logto ส่ง
## ส่วนหัวของคำขอ \{#request-headers}
-| Key | ปรับแต่งได้ | หมายเหตุ |
-| ----------------------- | ----------- | ---------------------------------------------------------------------------------------------------------- |
-| user-agent | ✅ | ค่าเริ่มต้นคือ `Logto (https://logto.io/)` |
-| content-type | ✅ | ค่าเริ่มต้นคือ `application/json` |
-| logto-signature-sha-256 | | ลายเซ็นของเนื้อหา request ดูที่ [การรักษาความปลอดภัย webhook ของคุณ](/developers/webhooks/secure-webhooks) |
+| Key | ปรับแต่งได้ | หมายเหตุ |
+| ----------------------- | ----------- | ---------------------------------------------------------------------------------------- |
+| user-agent | ✅ | `Logto (https://logto.io/)` โดยค่าเริ่มต้น. |
+| content-type | ✅ | `application/json` โดยค่าเริ่มต้น. |
+| logto-signature-sha-256 | | ลายเซ็นของเนื้อหาคำขอ ดู [securing your webhooks](/developers/webhooks/secure-webhooks). |
-คุณสามารถเขียนทับ header ที่ปรับแต่งได้โดย [ปรับแต่ง request](/developers/webhooks/configure-webhooks/#secure-webhook) header ด้วย key เดียวกัน
+ส่วนหัวที่สามารถปรับแต่งได้สามารถถูกแทนที่ผ่านการตั้งค่า [secure webhook](/developers/webhooks/configure-webhooks/#secure-webhook).
-## เนื้อหาคำขอของเหตุการณ์ interaction hook \{#interaction-hook-events-request-body}
+## ภาพรวมของเนื้อหาคำขอ \{#request-body-overview}
-เหตุการณ์ที่ใช้ได้: `PostRegister`, `PostSignIn`, `PostResetPassword`
+เนื้อหาเป็นวัตถุ JSON รูปแบบที่แน่นอนขึ้นอยู่กับว่ามันเป็นของครอบครัวเหตุการณ์ใด:
-เนื้อหาคำขอเป็นอ็อบเจกต์ JSON ที่มีข้อมูล 3 ประเภทดังนี้:
+| Family | Events | When it fires |
+| ----------------- | -------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
+| **User flow** | `PostRegister`, `PostSignIn`, `PostResetPassword` | เมื่อผู้ใช้ทำกระบวนการลงทะเบียน ลงชื่อเข้าใช้ หรือรีเซ็ตรหัสผ่านที่จัดการโดย Experience API เสร็จสิ้น. |
+| **Data mutation** | `User.*`, `Role.*`, `Scope.*`, `Organization.*`, `OrganizationRole.*`, `OrganizationScope.*` | เมื่อโมเดลข้อมูลพื้นฐานถูกเปลี่ยนแปลง — โดยการเรียก Management API หรือโดยกระบวนการผู้ใช้บน Experience API. |
+| **Exception** | `Identifier.Lockout` | เหตุการณ์ด้านความปลอดภัย — เช่น บัญชีถูกล็อกหลังจากพยายามยืนยันตัวตนล้มเหลวติดต่อกัน. |
+
+ทุกครอบครัวมีชุด [common fields](#common-fields) ร่วมกัน จากนั้นแต่ละครอบครัวจะเพิ่มฟิลด์บริบทคำขอของตัวเองพร้อมกับ payload เฉพาะเหตุการณ์
+
+### ฟิลด์ทั่วไป \{#common-fields}
+
+มีอยู่ในทุกการส่งไม่ว่าจะเป็นครอบครัวใด:
+
+| Field | Type | Optional | Notes |
+| --------- | -------- | -------- | ------------------------------------ |
+| hookId | `string` | | ตัวระบุการตั้งค่า webhook ใน Logto. |
+| event | `string` | | เหตุการณ์ที่กระตุ้นการส่งนี้. |
+| createdAt | `string` | | เวลาสร้าง payload ในรูปแบบ ISO 8601. |
+| userAgent | `string` | ✅ | ตัวแทนผู้ใช้ของคำขอที่กระตุ้น. |
+
+แต่ละครอบครัวยังรวมถึงที่อยู่ IP ของคำขอที่กระตุ้น — ภายใต้ชื่อฟิลด์ `userIp` สำหรับเหตุการณ์ user-flow และ `ip` สำหรับเหตุการณ์ data-mutation และ exception ความหมายเหมือนกัน; ชื่อที่แตกต่างกันทางประวัติศาสตร์ถูกเก็บรักษาไว้เพื่อความเข้ากันได้ย้อนหลัง
+
+## Payload ของเหตุการณ์ User flow \{#user-flow-event-payloads}
+
+**Events:** `PostRegister`, `PostSignIn`, `PostResetPassword`.
+
+ถูกเรียกใช้เมื่อผู้ใช้ทำกระบวนการลงทะเบียน ลงชื่อเข้าใช้ หรือรีเซ็ตรหัสผ่านที่จัดการโดย Experience API เสร็จสิ้น นอกจาก [common fields](#common-fields) แล้ว เนื้อหายังมี:
+
+| Field | Type | Optional | Notes |
+| ---------------- | -------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| interactionEvent | `'SignIn' \| 'Register' \| 'ForgotPassword'` | | ประเภทเหตุการณ์ user-flow. แผนที่ไปยัง `PostSignIn` / `PostRegister` / `PostResetPassword` ตามลำดับ ชื่อฟิลด์ยังคงชื่อ "interaction" ทางประวัติศาสตร์. |
+| sessionId | `string` | ✅ | Session ID (ไม่ใช่ Interaction ID) สำหรับเหตุการณ์นี้ ถ้ามี. |
+| userIp | `string` | ✅ | ที่อยู่ IP ของคำขอที่กระตุ้น. |
+| userId | `string` | ✅ | User ID ที่เกี่ยวข้องกับเหตุการณ์นี้ ถ้ามี. |
+| user | `UserEntity` | ✅ | เอนทิตีผู้ใช้ที่เกี่ยวข้องกับเหตุการณ์นี้ ถ้ามี. |
+| applicationId | `string` | ✅ | Application ID ที่เกี่ยวข้องกับเหตุการณ์นี้ ถ้ามี. |
+| application | `ApplicationEntity` | ✅ | เอนทิตีแอปพลิเคชันที่เกี่ยวข้องกับเหตุการณ์นี้ ถ้ามี. |
+
+#### รูปแบบเอนทิตี \{#user-flow-entity-shapes}
```tsx
type UserEntity = {
@@ -60,70 +97,57 @@ type ApplicationEntity = {
};
```
-| Field | Type | Optional | หมายเหตุ |
-| ---------------- | ------------------- | -------- | ------------------------------------------------------------- |
-| hookId | `string` | | ตัวระบุใน Logto |
-| event | `string` | | เหตุการณ์ที่เรียกใช้ hook นี้ |
-| createdAt | `string` | | เวลาสร้าง payload ในรูปแบบ ISO |
-| interactionEvent | `string` | | เหตุการณ์ interaction ที่เรียกใช้ hook นี้ |
-| sessionId | `string` | ✅ | Session ID (ไม่ใช่ Interaction ID) สำหรับเหตุการณ์นี้ (ถ้ามี) |
-| userAgent | `string` | ✅ | user-agent ของคำขอที่เรียกใช้ hook นี้ |
-| userIp | `string` | ✅ | ที่อยู่ IP ของคำขอที่เรียกใช้ hook นี้ |
-| userId | `string` | ✅ | User ID ที่เกี่ยวข้องกับเหตุการณ์นี้ (ถ้ามี) |
-| user | `UserEntity` | ✅ | user entity ที่เกี่ยวข้องกับเหตุการณ์นี้ (ถ้ามี) |
-| applicationId | `string` | ✅ | Application ID ที่เกี่ยวข้องกับเหตุการณ์นี้ (ถ้ามี) |
-| application | `ApplicationEntity` | ✅ | ข้อมูลแอปพลิเคชันที่เกี่ยวข้องกับเหตุการณ์นี้ (ถ้ามี) |
+ดู [Users](/user-management/user-data) และ [Applications](/integrate-logto/application-data-structure) สำหรับการอ้างอิงฟิลด์ทั้งหมด
-ดูข้อมูลอ้างอิง [ผู้ใช้](/user-management/user-data) และ [แอปพลิเคชัน](/integrate-logto/application-data-structure) สำหรับคำอธิบาย field โดยละเอียด
+## Payload ของเหตุการณ์ Data mutation \{#data-mutation-event-payloads}
-## เนื้อหาคำขอของเหตุการณ์ data mutation hook \{#data-mutation-hook-events-request-body}
+**Events:** ทุกเหตุการณ์ภายใต้ `User.*`, `Role.*`, `Scope.*`, `Organization.*`, `OrganizationRole.*`, `OrganizationScope.*` — ดู [Webhooks events → Data mutation hook events](/developers/webhooks/webhooks-events#data-mutation-hook-events) สำหรับแคตตาล็อกทั้งหมด
-### ฟิลด์มาตรฐานของเนื้อหาคำขอ \{#standard-request-body-fields}
+เนื้อหามักจะมี:
-| Field | Type | Optional | หมายเหตุ |
-| --------- | -------- | -------- | ------------------------------ |
-| hookId | `string` | | ตัวระบุใน Logto |
-| event | `string` | | เหตุการณ์ที่เรียกใช้ hook นี้ |
-| createdAt | `string` | | เวลาสร้าง payload ในรูปแบบ ISO |
-| userAgent | `string` | ✅ | user-agent ของคำขอ |
-| ip | `string` | ✅ | ที่อยู่ IP ของคำขอ |
+- [common fields](#common-fields).
+- ฟิลด์ `ip` — ที่อยู่ IP ของคำขอที่กระตุ้น (ไม่บังคับ, มีเมื่อทราบ).
+- **บริบท API** ที่อธิบายว่าการเปลี่ยนแปลงถูกกระตุ้นอย่างไร บริบทเป็นหนึ่งในสองรูปแบบขึ้นอยู่กับแหล่งที่มาของการกระตุ้น:
+ - [บริบท Experience API](#experience-api-context-fields) — เมื่อการเปลี่ยนแปลงมาจากกระบวนการที่ผู้ใช้เผชิญหน้า.
+ - [บริบท Management API](#management-api-context-fields) — เมื่อการเปลี่ยนแปลงมาจากการเรียก Management API โดยตรง.
+- **payload เฉพาะเหตุการณ์** — เอนทิตีที่ได้รับผลกระทบใน `data` และ (สำหรับบางเหตุการณ์) ฟิลด์ระดับบนเพิ่มเติม ดู [payload ข้อมูลเฉพาะเหตุการณ์](#event-specific-data-payloads).
-### ฟิลด์ context ของ Interaction API \{#interaction-api-context-body-fields}
+### ฟิลด์บริบท Experience API \{#experience-api-context-fields}
-เหตุการณ์ data mutation hook ที่ถูกเรียกโดยการเรียก API interaction ของผู้ใช้
+มีเมื่อการเปลี่ยนแปลงถูกกระตุ้นโดยกระบวนการที่ผู้ใช้เผชิญหน้าบน Experience API — ตัวอย่างเช่น, `User.Created` ระหว่างการลงทะเบียนหรือ `User.Data.Updated` ระหว่างการอัปเดตโปรไฟล์
-เหตุการณ์ที่ใช้ได้: `User.Created`, `User.Data.Updated`
+| Field | Type | Optional | Notes |
+| ---------------- | -------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------- |
+| interactionEvent | `'SignIn' \| 'Register' \| 'ForgotPassword'` | ✅ | ประเภทเหตุการณ์ user-flow ที่ทำให้เกิดการเปลี่ยนแปลง ชื่อฟิลด์ยังคงชื่อ "interaction" ทางประวัติศาสตร์. |
+| sessionId | `string` | ✅ | Session ID (ไม่ใช่ Interaction ID) สำหรับเหตุการณ์นี้ ถ้ามี. |
+| applicationId | `string` | ✅ | Application ID, ถ้ามี. |
+| application | `ApplicationEntity` | ✅ | เอนทิตีแอปพลิเคชัน, ถ้ามี. |
-| Field | Type | Optional | หมายเหตุ |
-| ---------------- | ------------------- | -------- | ------------------------------------------------------------- |
-| interactionEvent | `string` | ✅ | เหตุการณ์ interaction ที่เรียกใช้ hook นี้ |
-| sessionId | `string` | ✅ | Session ID (ไม่ใช่ Interaction ID) สำหรับเหตุการณ์นี้ (ถ้ามี) |
-| applicationId | `string` | ✅ | Application ID ที่เกี่ยวข้องกับเหตุการณ์นี้ (ถ้ามี) |
-| application | `ApplicationEntity` | ✅ | ข้อมูลแอปพลิเคชันที่เกี่ยวข้องกับเหตุการณ์นี้ (ถ้ามี) |
+### ฟิลด์บริบท Management API \{#management-api-context-fields}
-### ฟิลด์ context ของ Management API \{#management-api-context-body-fields}
+มีเมื่อการเปลี่ยนแปลงถูกกระตุ้นโดยการเรียก Management API
-เหตุการณ์ data mutation hook ที่ถูกเรียกโดยการเรียก Management API
+| Field | Type | Optional | Notes |
+| ------------ | -------- | -------- | ------------------------------------------------------------------------------------------- |
+| path | `string` | ✅ | เส้นทางของการเรียก API ที่กระตุ้น webhook นี้. |
+| method | `string` | ✅ | วิธี HTTP ของการเรียก API. |
+| status | `number` | ✅ | รหัสสถานะการตอบสนองของการเรียก API. |
+| params | `object` | ✅ | พารามิเตอร์เส้นทาง koa ของการเรียก API. |
+| matchedRoute | `string` | ✅ | เส้นทางที่ตรงกันของ koa Logto ใช้ฟิลด์นี้เพื่อจับคู่ตัวกรองเหตุการณ์ webhook ที่เปิดใช้งาน. |
-| Field | Type | Optional | หมายเหตุ |
-| ------------ | -------- | -------- | --------------------------------------------------------------------------------------------------------------- |
-| path | `string` | ✅ | path ของ API call ที่เรียกใช้ hook นี้ |
-| method | `string` | ✅ | method ของ API call ที่เรียกใช้ hook นี้ |
-| status | `number` | ✅ | รหัสสถานะตอบกลับของ API call ที่เรียกใช้ hook นี้ |
-| params | `object` | ✅ | koa path params ของ API call ที่เรียกใช้ hook นี้ |
-| matchedRoute | `string` | ✅ | koa matched route ของ API call ที่เรียกใช้ hook นี้ Logto ใช้ field นี้เพื่อจับคู่กับ hook events ที่เปิดใช้งาน |
+### Payload ข้อมูลเฉพาะเหตุการณ์ \{#event-specific-data-payloads}
-### ฟิลด์เนื้อหาข้อมูล (Data payload body fields) \{#data-payload-body-fields}
+ทุกเหตุการณ์ data-mutation รวมถึงฟิลด์ `data` ระดับบนที่มีเอนทิตีที่ได้รับผลกระทบ หรือ `null` เมื่อการเปลี่ยนแปลงไม่สามารถสรุปเป็นเอนทิตีเดียวได้ (เหตุการณ์ลบและสมาชิก) บางเหตุการณ์ยังรวมถึงฟิลด์ระดับบนเฉพาะเหตุการณ์นอกเหนือจาก `data` — `Organization.Membership.Updated` เป็นกรณีหนึ่งที่มีการบันทึกไว้ด้านล่าง
-**เหตุการณ์ผู้ใช้**
+#### เหตุการณ์ผู้ใช้ \{#user-events}
-| Event | Field | Type | Optional | หมายเหตุ |
-| ----------------- | ----- | ---------- | -------- | ------------------------------------------ |
-| User.Created | data | UserEntity | | user entity ที่ถูกสร้างสำหรับเหตุการณ์นี้ |
-| User.Data.Updated | data | UserEntity | | user entity ที่ถูกอัปเดตสำหรับเหตุการณ์นี้ |
-| User.Deleted | data | null | / | |
+| Event | Field | Type | Optional | Notes |
+| ----------------- | ----- | ------------ | -------- | -------------------------- |
+| User.Created | data | `UserEntity` | | เอนทิตีผู้ใช้ที่สร้างขึ้น. |
+| User.Data.Updated | data | `UserEntity` | | เอนทิตีผู้ใช้ที่อัปเดต. |
+| User.Deleted | data | `null` | / | |
-**เหตุการณ์บทบาท (Role events)**
+#### เหตุการณ์บทบาท \{#role-events}
```tsx
type Role = {
@@ -145,23 +169,23 @@ type Scope = {
};
```
-| Event | Field | Type | Optional | หมายเหตุ |
-| ------------------ | ------ | ------- | -------- | ------------------------------------------------------------------------------------------------------------- |
-| Role.Created | data | Role | | role entity ที่ถูกสร้างสำหรับเหตุการณ์นี้ |
-| Role.Data.Updated | data | Role | | role entity ที่ถูกอัปเดตสำหรับเหตุการณ์นี้ |
-| Role.Deleted | data | null | | |
-| Role.Scope.Updated | data | Scope[] | | scopes ที่ถูกอัปเดตและกำหนดให้กับ role |
-| Role.Scope.Updated | roleId | string | ✅ | role ID ที่ scopes ถูกกำหนดให้ (มีเฉพาะเมื่อเหตุการณ์ถูกเรียกโดยการสร้าง role ใหม่พร้อมกำหนด scopes ล่วงหน้า) |
+| Event | Field | Type | Optional | Notes |
+| ------------------- | ------ | --------- | -------- | ---------------------------------------------------------------------------------------------------------- |
+| Role.Created | data | `Role` | | เอนทิตีบทบาทที่สร้างขึ้น. |
+| Role.Data.Updated | data | `Role` | | เอนทิตีบทบาทที่อัปเดต. |
+| Role.Deleted | data | `null` | / | |
+| Role.Scopes.Updated | data | `Scope[]` | | ขอบเขตที่อัปเดตที่กำหนดให้กับบทบาท. |
+| Role.Scopes.Updated | roleId | `string` | ✅ | ID บทบาทที่ขอบเขตถูกกำหนดให้ (มีเฉพาะเมื่อเหตุการณ์ถูกกระตุ้นโดยการสร้างบทบาทที่มีขอบเขตที่กำหนดล่วงหน้า). |
-**เหตุการณ์สิทธิ์ (Permission / Scope events)**
+#### เหตุการณ์สิทธิ์ (Scope) \{#permission-events}
-| Event | Field | Type | Optional | หมายเหตุ |
-| ------------------ | ----- | ----- | -------- | ------------------------------------------- |
-| Scope.Created | data | Scope | | scope entity ที่ถูกสร้างสำหรับเหตุการณ์นี้ |
-| Scope.Data.Updated | data | Scope | | scope entity ที่ถูกอัปเดตสำหรับเหตุการณ์นี้ |
-| Scope.Deleted | data | null | / | |
+| Event | Field | Type | Optional | Notes |
+| ------------------ | ----- | ------- | -------- | -------------------------- |
+| Scope.Created | data | `Scope` | | เอนทิตีขอบเขตที่สร้างขึ้น. |
+| Scope.Data.Updated | data | `Scope` | | เอนทิตีขอบเขตที่อัปเดต. |
+| Scope.Deleted | data | `null` | / | |
-**เหตุการณ์องค์กร (Organization events)**
+#### เหตุการณ์องค์กร \{#organization-events}
```tsx
type Organization = {
@@ -173,14 +197,139 @@ type Organization = {
};
```
-| Event | Field | Type | Optional | หมายเหตุ |
-| ------------------------------- | ----- | ------------ | -------- | -------------------------------------------------- |
-| Organization.Created | data | Organization | | organization entity ที่ถูกสร้างสำหรับเหตุการณ์นี้ |
-| Organization.Data.Updated | data | Organization | | organization entity ที่ถูกอัปเดตสำหรับเหตุการณ์นี้ |
-| Organization.Deleted | data | null | / | |
-| Organization.Membership.Updated | data | null | / | |
+| Event | Field | Type | Optional | Notes |
+| ------------------------------- | ----- | -------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Organization.Created | data | `Organization` | | เอนทิตีองค์กรที่สร้างขึ้น. |
+| Organization.Data.Updated | data | `Organization` | | เอนทิตีองค์กรที่อัปเดต. |
+| Organization.Deleted | data | `null` | / | |
+| Organization.Membership.Updated | data | `null` | / | การเปลี่ยนแปลงถูกอธิบายโดยอาร์เรย์ delta ระดับบนที่เป็นทางเลือก ดู [Organization.Membership.Updated payload](#organizationmembershipupdated-payload) ด้านล่าง. |
+
+##### Payload ของ Organization.Membership.Updated \{#organizationmembershipupdated-payload}
+
+นอกจาก[ฟิลด์ทั่วไป](#common-fields)และฟิลด์บริบท API ที่เหมาะสมตามแหล่งที่มาของทริกเกอร์ ([บริบท Management API](#management-api-context-fields) สำหรับเส้นทาง Management API, [บริบท Experience API](#experience-api-context-fields) สำหรับการจัดเตรียมแบบทันเวลา) แล้ว เหตุการณ์ `Organization.Membership.Updated` ยังมี `organizationId` พร้อมอาร์เรย์ delta ที่เป็นทางเลือกที่ระดับบนของ payload (ถัดจาก `event`, `createdAt`, ฯลฯ, **ไม่ใช่** ภายใน `data`, ซึ่งเป็น `null` เสมอสำหรับเหตุการณ์นี้)
+
+| Field | Type | Optional | Notes |
+| --------------------- | ---------- | -------- | ------------------------------------------------------------------------------------------------------------------------------ |
+| organizationId | `string` | | องค์กรที่การเป็นสมาชิกเปลี่ยนแปลง. |
+| addedUserIds | `string[]` | ✅ | User IDs ที่เพิ่มใหม่โดยการกระตุ้นนี้ ถูกละเว้นเมื่อไม่มีผู้ใช้ถูกเพิ่ม หรือเมื่อการกระตุ้นไม่ส่งผลต่อการเป็นสมาชิกของผู้ใช้. |
+| removedUserIds | `string[]` | ✅ | User IDs ที่ถูกลบโดยการกระตุ้นนี้ ถูกละเว้นเมื่อไม่มีผู้ใช้ถูกลบ. |
+| addedApplicationIds | `string[]` | ✅ | Application IDs ที่เพิ่มใหม่ ถูกละเว้นเมื่อไม่มีแอปพลิเคชันถูกเพิ่ม หรือเมื่อการกระตุ้นไม่ส่งผลต่อการเป็นสมาชิกของแอปพลิเคชัน. |
+| removedApplicationIds | `string[]` | ✅ | Application IDs ที่ถูกลบ ถูกละเว้นเมื่อไม่มีแอปพลิเคชันถูกลบ. |
+
+อาร์เรย์ delta ทั้งสี่เป็น **ทางเลือกและเพิ่มเข้าไป** — พวกมันไม่เปลี่ยนรูปแบบ payload ที่มีอยู่สำหรับผู้บริโภคที่ไม่คาดหวังพวกมัน และฟิลด์ `data: null` แบบดั้งเดิมยังคงถูกส่งออกโดยไม่เปลี่ยนแปลง
+
+###### การกระตุ้นและฟิลด์ delta ที่พวกมันอาจส่งออก \{#membership-triggers}
+
+| Trigger | Possible delta fields |
+| --------------------------------------------------------------------- | ---------------------------------------------- |
+| `POST /organizations/:id/users` | `addedUserIds` |
+| `PUT /organizations/:id/users` | `addedUserIds`, `removedUserIds` |
+| `DELETE /organizations/:id/users/:userId` | `removedUserIds` |
+| `POST /organizations/:id/applications` | `addedApplicationIds` |
+| `PUT /organizations/:id/applications` | `addedApplicationIds`, `removedApplicationIds` |
+| `DELETE /organizations/:id/applications/:applicationId` | `removedApplicationIds` |
+| `PUT /organization-invitations/:id/status` (`Accepted`) | `addedUserIds` |
+| การจัดเตรียมแบบทันทีทันใด (Just-in-time) เมื่อเพิ่มผู้ใช้ในองค์กรใหม่ | `addedUserIds` |
+
+###### Delta ที่ว่างเปล่าถูกละเว้น — การไม่มี ≠ การเปลี่ยนแปลงที่ว่างเปล่า \{#empty-deltas-are-omitted}
+
+อาร์เรย์ delta ที่ว่างเปล่า **ถูกละเว้นทั้งหมด** จาก payload ตัวอย่างเช่น, `PUT /organizations/:id/users` ที่แทนที่ชุดสมาชิกด้วยชุดที่มีอยู่แล้วไม่ก่อให้เกิดการเปลี่ยนแปลงจริง และ payload ลดลงเหลือเพียง `{ organizationId }` โดยไม่มีฟิลด์ delta ทั้งสี่ การเดียวกันนี้ใช้กับการเพิ่มสมาชิกที่มีอยู่แล้ว การยอมรับคำเชิญซ้ำโดยผู้ใช้ที่เป็นสมาชิกอยู่แล้ว
+
+**ผู้บริโภคต้องถือว่าฟิลด์ที่หายไปหมายถึง "ไม่มีการเปลี่ยนแปลงในด้านนั้น" ไม่ใช่ "การเปลี่ยนแปลงที่ว่างเปล่า"**
+
+###### ขีดจำกัดต่ออาร์เรย์ (การตัดทอนอย่างเงียบ ๆ) \{#membership-delta-cap}
+
+แต่ละอาร์เรย์ delta ถูกจำกัดที่ **5000 รายการ** เมื่อการเรียก Management API เดียวเพิ่มหรือลบผู้ใช้ (หรือแอปพลิเคชัน) มากกว่า 5000 รายการในการดำเนินการเดียว อาร์เรย์ delta ที่สอดคล้องกันจะถูกตัดทอนอย่างเงียบ ๆ ไปยัง 5000 รายการแรกของมัน — **ไม่มีตัวบ่งชี้ใน payload** ว่าขีดจำกัดถูกเรียกใช้
+
+หากแอปพลิเคชันของคุณดำเนินการบริหารจัดการแบบกลุ่มที่สามารถส่งผลกระทบต่อสมาชิกมากกว่า 5000 คนในการเรียกเดียว ให้ถือว่าอาร์เรย์ที่มี 5000 รายการพอดีเป็นสัญญาณให้กระทบยอดการเป็นสมาชิกที่มีอำนาจผ่าน Management API:
+
+- `GET /organizations/:id/users` — การเป็นสมาชิกผู้ใช้ทั้งหมด
+- `GET /organizations/:id/applications` — การเป็นสมาชิกแอปพลิเคชันทั้งหมด
+
+สิ่งนี้เป็นไปตามรูปแบบเดียวกับเหตุการณ์ `push` ของ GitHub ซึ่งจำกัด `commits` ที่ 20 รายการและชี้ผู้บริโภคไปที่ API เปรียบเทียบสำหรับรายการทั้งหมด
+
+###### ข้ามเหตุการณ์ที่ไม่มีการดำเนินการ \{#skipping-no-op-events}
+
+ทุก `PUT` ต่อเส้นทางการเป็นสมาชิกจะส่งเหตุการณ์ไม่ว่าจะมีการเปลี่ยนแปลงอะไรจริงหรือไม่ — เพื่อให้การเรียกแทนที่สถานะใด ๆ มีการส่ง webhook อย่างน้อยหนึ่งครั้งเพื่อวัตถุประสงค์ในการตรวจสอบ เพื่อข้ามการส่งที่ไม่มีการดำเนินการในฝั่งผู้บริโภค ให้กรองตามการมีอยู่ของอาร์เรย์ delta:
+
+```ts
+if (
+ payload.addedUserIds?.length ||
+ payload.removedUserIds?.length ||
+ payload.addedApplicationIds?.length ||
+ payload.removedApplicationIds?.length
+) {
+ // การเปลี่ยนแปลงการเป็นสมาชิกจริง — จัดการมัน
+}
+```
-**เหตุการณ์ OrganizationRole**
+`?.length` เป็นค่าเท็จสำหรับทั้ง `undefined` และ `[]`, ดังนั้นคำทำนายเดียวกันนี้มีความทนทานไม่ว่าจะฟิลด์หายไปหรือ (ในอนาคตที่สมมุติ) ถูกส่งออกเป็นอาร์เรย์ว่างเปล่า
+
+###### ตัวอย่าง payload \{#membership-example-payloads}
+
+**เพิ่มผู้ใช้ (`POST /organizations/:id/users`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "addedUserIds": ["u_001"]
+}
+```
+
+**แทนที่ชุดสมาชิกผู้ใช้ (`PUT /organizations/:id/users`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "addedUserIds": ["u_002"],
+ "removedUserIds": ["u_001"]
+}
+```
+
+**ลบผู้ใช้ (`DELETE /organizations/:id/users/:userId`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "removedUserIds": ["u_001"]
+}
+```
+
+**เพิ่มแอปพลิเคชัน (`POST /organizations/:id/applications`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "addedApplicationIds": ["app_xyz"]
+}
+```
+
+**เพิ่มสมาชิกที่มีอยู่แล้ว, no-op `PUT`, หรือการยอมรับคำเชิญซ้ำของสมาชิกที่มีอยู่แล้ว (ไม่มีการเปลี่ยนแปลงจริง):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc"
+}
+```
+
+**การดำเนินการแบบกลุ่มที่ถึงขีดจำกัด 5000 (ตัดทอนอย่างเงียบ ๆ):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "removedUserIds": ["u_0001", "u_0002", "/* … exactly 5000 entries total */"]
+}
+```
+
+การเห็นอาร์เรย์ที่มี 5000 รายการพอดีควรกระตุ้นการกระทบยอด `GET /organizations/:id/users` (หรือ `/applications`).
+
+#### เหตุการณ์บทบาทองค์กร \{#organization-role-events}
```tsx
type OrganizationRole = {
@@ -198,27 +347,32 @@ type OrganizationScope = {
};
```
-| Event | Field | Type | Optional | หมายเหตุ |
-| ------------------------------ | ------------------ | ---------------- | -------- | ------------------------------------------------------------------------------------------------------------- |
-| OrganizationRole.Created | data | OrganizationRole | | organization role entity ที่ถูกสร้างสำหรับเหตุการณ์นี้ |
-| OrganizationRole.Data.Updated | data | OrganizationRole | | organization role entity ที่ถูกอัปเดตสำหรับเหตุการณ์นี้ |
-| OrganizationRole.Deleted | data | null | / | |
-| OrganizationRole.Scope.Updated | data | null | / | |
-| OrganizationRole.Scope.Updated | organizationRoleId | string | ✅ | role ID ที่ scopes ถูกกำหนดให้ (มีเฉพาะเมื่อเหตุการณ์ถูกเรียกโดยการสร้าง role ใหม่พร้อมกำหนด scopes ล่วงหน้า) |
+| Event | Field | Type | Optional | Notes |
+| ------------------------------- | ------------------ | ------------------ | -------- | ---------------------------------------------------------------------------------------------------------- |
+| OrganizationRole.Created | data | `OrganizationRole` | | เอนทิตีบทบาทองค์กรที่สร้างขึ้น. |
+| OrganizationRole.Data.Updated | data | `OrganizationRole` | | เอนทิตีบทบาทองค์กรที่อัปเดต. |
+| OrganizationRole.Deleted | data | `null` | / | |
+| OrganizationRole.Scopes.Updated | data | `null` | / | |
+| OrganizationRole.Scopes.Updated | organizationRoleId | `string` | ✅ | ID บทบาทที่ขอบเขตถูกกำหนดให้ (มีเฉพาะเมื่อเหตุการณ์ถูกกระตุ้นโดยการสร้างบทบาทที่มีขอบเขตที่กำหนดล่วงหน้า). |
+
+#### เหตุการณ์สิทธิ์องค์กร (scope) \{#organization-permission-events}
-**เหตุการณ์สิทธิ์ขององค์กร (Organization permission / OrganizationScope events)**
+| Event | Field | Type | Optional | Notes |
+| ------------------------------ | ----- | ------------------- | -------- | -------------------------------- |
+| OrganizationScope.Created | data | `OrganizationScope` | | เอนทิตีขอบเขตองค์กรที่สร้างขึ้น. |
+| OrganizationScope.Data.Updated | data | `OrganizationScope` | | เอนทิตีขอบเขตองค์กรที่อัปเดต. |
+| OrganizationScope.Deleted | data | `null` | / | |
-| Event | Field | Type | Optional | หมายเหตุ |
-| ------------------------------ | ----- | ----------------- | -------- | -------------------------------------- |
-| OrganizationScope.Created | data | OrganizationScope | | organization scope entity ที่ถูกสร้าง |
-| OrganizationScope.Data.Updated | data | OrganizationScope | | organization scope entity ที่ถูกอัปเดต |
-| OrganizationScope.Deleted | data | null | / | |
+## Payload ของเหตุการณ์ Exception \{#exception-event-payloads}
-## เนื้อหาคำขอของเหตุการณ์ exception hook \{#exception-hook-events-request-body}
+**Events:** `Identifier.Lockout`.
-เหตุการณ์ที่ใช้ได้: `Identifier.Lockout`
+ถูกเรียกใช้เมื่อเกิดเหตุการณ์ด้านความปลอดภัย — เช่น บัญชีถูกล็อกหลังจากพยายามยืนยันตัวตนล้มเหลวติดต่อกัน เหตุการณ์เหล่านี้มักมาจากกระบวนการที่ผู้ใช้เผชิญหน้า ดังนั้นเนื้อหาจึงมี:
-เนื้อหาคำขอเป็นอ็อบเจกต์ JSON ที่มีฟิลด์มาตรฐานของเนื้อหาคำขอและฟิลด์เพิ่มเติมดังนี้:
+- [common fields](#common-fields).
+- ฟิลด์ `ip` (รูปแบบเดียวกับเหตุการณ์ data-mutation).
+- [ฟิลด์บริบท Experience API](#experience-api-context-fields).
+- ฟิลด์เฉพาะ exception ด้านล่าง
```tsx
enum SignInIdentifier {
@@ -228,16 +382,7 @@ enum SignInIdentifier {
}
```
-| Field | Type | Optional | หมายเหตุ |
-| ---------------- | ------------------- | -------- | ------------------------------------------------------------- |
-| hookId | `string` | | ตัวระบุใน Logto |
-| event | `string` | | เหตุการณ์ที่เรียกใช้ hook นี้ |
-| createdAt | `string` | | เวลาสร้าง payload ในรูปแบบ ISO |
-| userAgent | `string` | ✅ | user-agent ของคำขอ |
-| ip | `string` | ✅ | ที่อยู่ IP ของคำขอ |
-| interactionEvent | `string` | ✅ | เหตุการณ์ interaction ที่เรียกใช้ hook นี้ |
-| sessionId | `string` | ✅ | Session ID (ไม่ใช่ Interaction ID) สำหรับเหตุการณ์นี้ (ถ้ามี) |
-| applicationId | `string` | ✅ | Application ID ที่เกี่ยวข้องกับเหตุการณ์นี้ (ถ้ามี) |
-| application | `ApplicationEntity` | ✅ | ข้อมูลแอปพลิเคชันที่เกี่ยวข้องกับเหตุการณ์นี้ (ถ้ามี) |
-| type | `SignInIdentifier` | | ประเภท identifier ของผู้ใช้ เช่น email, phone หรือ username |
-| value | `string` | | ค่า identifier ของผู้ใช้ที่ทำให้เกิด lockout |
+| Field | Type | Optional | Notes |
+| ----- | ------------------ | -------- | ---------------------------------------------------------- |
+| type | `SignInIdentifier` | | ประเภทตัวระบุของผู้ใช้ เช่น อีเมล โทรศัพท์ หรือชื่อผู้ใช้. |
+| value | `string` | | ค่าตัวระบุของผู้ใช้ที่กระตุ้นการล็อกเอาต์. |
diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx b/i18n/zh-CN/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx
index 14606a5e4f8..cadab678f3c 100644
--- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx
+++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx
@@ -5,9 +5,9 @@ sidebar_label: Webhook 事件
sidebar_position: 3
---
-# Webhook 事件
+# Webhooks 事件
-本指南列出了不同的 Logto Webhook 事件,并解释了每个事件发生的时机。
+本指南列出了不同的 Logto webhook 事件,并解释了每个事件发生的时间。
## 用户交互钩子事件 \{#user-interaction-hook-events}
@@ -21,59 +21,59 @@ sidebar_position: 3
### 用户 \{#user}
-| 事件类型 | 描述 |
-| ----------------------------- | ------------------------------------------------------------- |
-| User.Created | 创建了一个新用户账户。 |
-| User.Deleted | 删除了一个用户账户。 |
-| User.Data.Updated | 用户资料数据被更新,例如邮箱、头像、custom.data、社交标识等。 |
-| User.SuspensionStatus.Updated | 用户的封禁状态发生变化(被封禁或重新激活)。 |
+| 事件类型 | 描述 |
+| ----------------------------- | --------------------------------------------------------------------- |
+| User.Created | 创建了一个新的用户账户。 |
+| User.Deleted | 删除了一个用户账户。 |
+| User.Data.Updated | 用户资料数据被更新,例如,电子邮件、头像、custom.data、社交标识符等。 |
+| User.SuspensionStatus.Updated | 用户的暂停状态被更改(暂停或重新激活)。 |
-### 角色 (Role) \{#role}
+### 角色 \{#role}
-| 事件类型 | 描述 |
-| ------------------- | ------------------------------------------------------------ |
-| Role.Created | 创建了一个新角色 (Role)。 |
-| Role.Deleted | 删除了一个角色 (Role)。 |
-| Role.Data.Updated | 角色 (Role) 的数据被更新,例如角色名称、描述和默认角色状态。 |
-| Role.Scopes.Updated | 分配给角色 (Role) 的权限 (Permissions) 被添加或移除。 |
+| 事件类型 | 描述 |
+| ------------------- | ------------------------------------------------------ |
+| Role.Created | 创建了一个新的角色。 |
+| Role.Deleted | 删除了一个角色。 |
+| Role.Data.Updated | 角色的数据被更新,例如,角色名称、描述和默认角色状态。 |
+| Role.Scopes.Updated | 分配给角色的权限被添加或移除。 |
-### 权限 (Permission)(Scope)\{#permission-scope}
+### 权限 (Scope) \{#permission-scope}
-| 事件类型 | 描述 |
-| ------------------ | -------------------------------------------------- |
-| Scope.Created | 创建了一个新的 API 权限 (Permission)。 |
-| Scope.Deleted | 删除了一个 API 权限 (Permission)。 |
-| Scope.Data.Updated | API 权限 (Permission) 的数据被更新,例如权限描述。 |
+| 事件类型 | 描述 |
+| ------------------ | -------------------------------------- |
+| Scope.Created | 创建了一个新的 API 权限。 |
+| Scope.Deleted | 删除了一个 API 权限。 |
+| Scope.Data.Updated | API 权限的数据被更新,例如,权限描述。 |
### 组织 (Organization) \{#organization}
-| 事件类型 | 描述 |
-| ------------------------------- | ---------------------------------------------------------------------- |
-| Organization.Created | 创建了一个新组织 (Organization)。 |
-| Organization.Deleted | 删除了一个组织 (Organization)。 |
-| Organization.Data.Updated | 组织 (Organization) 的数据被更新,例如组织名称、描述、custom.data 等。 |
-| Organization.Membership.Updated | 组织 (Organization) 的成员被添加或移除。 |
+| 事件类型 | 描述 |
+| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Organization.Created | 创建了一个新的组织。 |
+| Organization.Deleted | 删除了一个组织。 |
+| Organization.Data.Updated | 组织的数据被更新,例如,组织名称、描述、custom.data 等。 |
+| Organization.Membership.Updated | 用户或应用程序被添加到或从组织中移除。负载包括 [membership delta fields](/developers/webhooks/webhooks-request#organizationmembershipupdated-payload)。 |
-### 组织角色 (Organization role) \{#organization-role}
+### 组织角色 \{#organization-role}
-| 事件类型 | 描述 |
-| ------------------------------- | ---------------------------------------------------------------------- |
-| OrganizationRole.Created | 创建了一个新的组织角色 (Organization role)。 |
-| OrganizationRole.Deleted | 删除了一个组织角色 (Organization role)。 |
-| OrganizationRole.Data.Updated | 组织角色 (Organization role) 的数据被更新,例如组织角色名称和描述。 |
-| OrganizationRole.Scopes.Updated | 分配给组织角色 (Organization role) 的权限 (Permissions) 被添加或移除。 |
+| 事件类型 | 描述 |
+| ------------------------------- | ------------------------------------------------ |
+| OrganizationRole.Created | 创建了一个新的组织角色。 |
+| OrganizationRole.Deleted | 删除了一个组织角色。 |
+| OrganizationRole.Data.Updated | 组织角色的数据被更新,例如,组织角色名称和描述。 |
+| OrganizationRole.Scopes.Updated | 分配给组织角色的权限被添加或移除。 |
-### 组织权限 (Organization permission)(scope)\{#organization-permission-scope}
+### 组织权限 (Scope) \{#organization-permission-scope}
-| 事件类型 | 描述 |
-| ------------------------------ | ------------------------------------------------------------------- |
-| OrganizationScope.Created | 创建了一个新的组织权限 (Organization permission)。 |
-| OrganizationScope.Deleted | 删除了一个组织权限 (Organization permission)。 |
-| OrganizationScope.Data.Updated | 组织权限 (Organization permission) 的数据被更新,例如组织权限描述。 |
+| 事件类型 | 描述 |
+| ------------------------------ | ------------------------------------------ |
+| OrganizationScope.Created | 创建了一个新的组织权限。 |
+| OrganizationScope.Deleted | 删除了一个组织权限。 |
+| OrganizationScope.Data.Updated | 组织权限的数据被更新,例如,组织权限描述。 |
### Management API 触发的事件 \{#management-api-triggered-events}
-| API endpoint | 事件 |
+| API 端点 | 事件 |
| ---------------------------------------------------------- | ----------------------------------------------------------- |
| POST /users | User.Created |
| DELETE /users/:userId | User.Deleted |
@@ -96,6 +96,10 @@ sidebar_position: 3
| PUT /organizations/:id/users | Organization.Membership.Updated |
| POST /organizations/:id/users | Organization.Membership.Updated |
| DELETE /organizations/:id/users/:userId | Organization.Membership.Updated |
+| PUT /organizations/:id/applications | Organization.Membership.Updated |
+| POST /organizations/:id/applications | Organization.Membership.Updated |
+| DELETE /organizations/:id/applications/:applicationId | Organization.Membership.Updated |
+| PUT /organization-invitations/:id/status (Accepted) | Organization.Membership.Updated |
| POST /organization-roles | OrganizationRole.Created, (OrganizationRole.Scopes.Updated) |
| DELETE /organization-roles/:id | OrganizationRole.Deleted |
| PATCH /organization-roles/:id | OrganizationRole.Data.Updated |
@@ -108,13 +112,14 @@ sidebar_position: 3
### Experience API 触发的事件 \{#experience-api-triggered-events}
-| 用户交互操作 | 事件 |
-| --------------------- | ----------------- |
-| 用户邮箱 / 手机号绑定 | User.Data.Updated |
-| 用户 MFA 绑定 | User.Data.Updated |
-| 用户社交 / SSO 绑定 | User.Data.Updated |
-| 用户密码重置 | User.Data.Updated |
-| 用户注册 | User.Created |
+| 用户交互操作 | 事件 |
+| ---------------------------------------------------------------------------------------------------------------- | ------------------------------- |
+| 用户电子邮件/电话关联 | User.Data.Updated |
+| 用户 MFA 关联 | User.Data.Updated |
+| 用户社交/SSO 关联 | User.Data.Updated |
+| 用户密码重置 | User.Data.Updated |
+| 用户注册 | User.Created |
+| 用户通过 [即时供应](/organizations/just-in-time-provisioning)(匹配电子邮件域或企业 SSO 连接器)自动供应到组织中 | Organization.Membership.Updated |
## 异常钩子事件 \{#exception-hook-events}
@@ -122,14 +127,14 @@ sidebar_position: 3
| 事件类型 | 描述 |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------ |
-| Identifier.Lockout | 由于连续身份验证失败,用户账户被锁定。可在以下流程中触发:
|
+| Identifier.Lockout | 由于连续身份验证失败,用户账户被锁定。可以在以下流程中触发:
|
## 常见问题 \{#faqs}
-### `PostRegister` 和 `User.Created` 有什么区别?\{#whats-the-difference-between-postregister-and-usercreated}
+### `PostRegister` 和 `User.Created` 之间有什么区别? \{#whats-the-difference-between-postregister-and-usercreated}
diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx b/i18n/zh-CN/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx
index 17695e64de8..8cd0a8a5bfe 100644
--- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx
+++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx
@@ -5,25 +5,62 @@ sidebar_label: Webhook 请求
sidebar_position: 4
---
-# Webhook 请求
+# Webhooks 请求
-当一个有效的 hook 事件被触发后,Logto 会查找对应的 webhook,并根据每个 hook 配置发送一个 POST 请求。
+当一个 webhook 事件触发时,Logto 会向每个订阅了该事件的端点发送一个 `POST` 请求。完整的事件目录在 [Webhooks 事件](/developers/webhooks/webhooks-events)中;本页面记录了 Logto 发送的请求的**结构**。
## 请求头 \{#request-headers}
-| Key | 可自定义 | 说明 |
-| ----------------------- | -------- | ---------------------------------------------------------------------------- |
-| user-agent | ✅ | 默认值为 `Logto (https://logto.io/)`。 |
-| content-type | ✅ | 默认值为 `application/json`。 |
-| logto-signature-sha-256 | | 请求体的签名,详见[保护你的 webhook](/developers/webhooks/secure-webhooks)。 |
+| Key | 可自定义 | 说明 |
+| ----------------------- | -------- | ------------------------------------------------------------------------------ |
+| user-agent | ✅ | 默认是 `Logto (https://logto.io/)`。 |
+| content-type | ✅ | 默认是 `application/json`。 |
+| logto-signature-sha-256 | | 请求体的签名。参见 [保护你的 webhooks](/developers/webhooks/secure-webhooks)。 |
-你可以通过[自定义请求](/developers/webhooks/configure-webhooks/#secure-webhook)头部并使用相同的 key 来覆盖可自定义的请求头。
+可定制的头可以通过 [secure webhook](/developers/webhooks/configure-webhooks/#secure-webhook) 配置进行覆盖。
-## 交互 hook 事件请求体 \{#interaction-hook-events-request-body}
+## 请求体概述 \{#request-body-overview}
-可用事件:`PostRegister`、`PostSignIn`、`PostResetPassword`
+请求体是一个 JSON 对象。其具体结构取决于事件所属的类别:
-请求体是一个包含三类数据字段的 JSON 对象:
+| Family | Events | When it fires |
+| ------------ | -------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
+| **用户流程** | `PostRegister`, `PostSignIn`, `PostResetPassword` | 用户完成由 Experience API 处理的注册、登录或重置密码流程时触发。 |
+| **数据变更** | `User.*`, `Role.*`, `Scope.*`, `Organization.*`, `OrganizationRole.*`, `OrganizationScope.*` | 底层数据模型发生变更时触发——通过 Management API 调用或 Experience API 上的用户流程。 |
+| **异常** | `Identifier.Lockout` | 安全事件——例如,连续验证失败后账户被锁定。 |
+
+每个类别共享一小组[公共字段](#common-fields)。然后,每个类别在其自身的请求上下文字段和特定事件的有效负载上进行扩展。
+
+### 公共字段 \{#common-fields}
+
+无论类别如何,每次传递中都存在:
+
+| Field | Type | Optional | Notes |
+| --------- | -------- | -------- | --------------------------------- |
+| hookId | `string` | | Logto 中的 webhook 配置标识符。 |
+| event | `string` | | 触发此次传递的事件。 |
+| createdAt | `string` | | 有效负载创建时间,ISO 8601 格式。 |
+| userAgent | `string` | ✅ | 触发请求的用户代理。 |
+
+每个类别还包括触发请求的 IP 地址——在用户流程事件中字段名为 `userIp`,在数据变更和异常事件中为 `ip`。语义相同;历史名称差异是为了向后兼容。
+
+## 用户流程事件有效负载 \{#user-flow-event-payloads}
+
+**事件:** `PostRegister`, `PostSignIn`, `PostResetPassword`。
+
+当用户完成由 Experience API 处理的注册、登录或重置密码流程时触发。除了[公共字段](#common-fields),请求体还包含:
+
+| Field | Type | Optional | Notes |
+| ---------------- | -------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------- |
+| interactionEvent | `'SignIn' \| 'Register' \| 'ForgotPassword'` | | 用户流程事件类型。分别映射到 `PostSignIn` / `PostRegister` / `PostResetPassword`。字段名称保留历史“交互”命名。 |
+| sessionId | `string` | ✅ | 此事件的会话 ID(不是交互 ID),如果适用。 |
+| userIp | `string` | ✅ | 触发请求的 IP 地址。 |
+| userId | `string` | ✅ | 与此事件相关的用户 ID,如果适用。 |
+| user | `UserEntity` | ✅ | 与此事件相关的用户实体,如果适用。 |
+| applicationId | `string` | ✅ | 与此事件相关的应用程序 ID,如果适用。 |
+| application | `ApplicationEntity` | ✅ | 与此事件相关的应用程序实体,如果适用。 |
+
+#### 实体结构 \{#user-flow-entity-shapes}
```tsx
type UserEntity = {
@@ -60,70 +97,57 @@ type ApplicationEntity = {
};
```
-| 字段 | 类型 | 可选 | 说明 |
-| ---------------- | ------------------- | ---- | ---------------------------------------------------- |
-| hookId | `string` | | Logto 中的标识符。 |
-| event | `string` | | 触发此 hook 的事件。 |
-| createdAt | `string` | | 负载的创建时间,ISO 格式。 |
-| interactionEvent | `string` | | 触发此 hook 的交互事件。 |
-| sessionId | `string` | ✅ | 此事件的 Session ID(不是 Interaction ID),如适用。 |
-| userAgent | `string` | ✅ | 触发此 hook 的请求的 user-agent。 |
-| userIp | `string` | ✅ | 触发此 hook 的请求的 IP 地址。 |
-| userId | `string` | ✅ | 此事件相关的用户 ID,如适用。 |
-| user | `UserEntity` | ✅ | 此事件相关的用户实体,如适用。 |
-| applicationId | `string` | ✅ | 此事件相关的应用 ID,如适用。 |
-| application | `ApplicationEntity` | ✅ | 此事件相关的应用信息,如适用。 |
+参见 [用户](/user-management/user-data) 和 [应用程序](/integrate-logto/application-data-structure) 以获取完整字段参考。
-详细字段说明请参见 [用户](/user-management/user-data) 和 [应用](/integrate-logto/application-data-structure) 参考文档。
+## 数据变更事件有效负载 \{#data-mutation-event-payloads}
-## 数据变更 hook 事件请求体 \{#data-mutation-hook-events-request-body}
+**事件:** `User.*`, `Role.*`, `Scope.*`, `Organization.*`, `OrganizationRole.*`, `OrganizationScope.*` 下的每个事件——参见 [Webhooks 事件 → 数据变更 hook 事件](/developers/webhooks/webhooks-events#data-mutation-hook-events) 以获取完整目录。
-### 标准请求体字段 \{#standard-request-body-fields}
+请求体始终包含:
-| 字段 | 类型 | 可选 | 说明 |
-| --------- | -------- | ---- | -------------------------- |
-| hookId | `string` | | Logto 中的标识符。 |
-| event | `string` | | 触发此 hook 的事件。 |
-| createdAt | `string` | | 负载的创建时间,ISO 格式。 |
-| userAgent | `string` | ✅ | 请求的 user-agent。 |
-| ip | `string` | ✅ | 请求的 IP 地址。 |
+- [公共字段](#common-fields)。
+- 一个 `ip` 字段——触发请求的 IP 地址(可选,已知时存在)。
+- 描述变更如何触发的**API 上下文**。上下文根据触发源有两种变体之一:
+ - [Experience API 上下文](#experience-api-context-fields)——当变更来自用户界面流程时。
+ - [Management API 上下文](#management-api-context-fields)——当变更来自直接的 Management API 调用时。
+- **事件特定的有效负载**——在 `data` 中的受影响实体和(对于某些事件)额外的顶级字段。参见[事件特定数据有效负载](#event-specific-data-payloads)。
-### 交互 API 上下文体字段 \{#interaction-api-context-body-fields}
+### Experience API 上下文字段 \{#experience-api-context-fields}
-由用户交互 API 调用触发的数据变更 hook 事件。
+当变更由 Experience API 上的用户界面流程触发时存在——例如,注册期间的 `User.Created` 或个人资料更新期间的 `User.Data.Updated`。
-可用事件:`User.Created`、`User.Data.Updated`
+| Field | Type | Optional | Notes |
+| ---------------- | -------------------------------------------- | -------- | -------------------------------------------------------- |
+| interactionEvent | `'SignIn' \| 'Register' \| 'ForgotPassword'` | ✅ | 产生变更的用户流程事件类型。字段名称保留历史“交互”命名。 |
+| sessionId | `string` | ✅ | 此事件的会话 ID(不是交互 ID),如果适用。 |
+| applicationId | `string` | ✅ | 应用程序 ID,如果适用。 |
+| application | `ApplicationEntity` | ✅ | 应用程序实体,如果适用。 |
-| 字段 | 类型 | 可选 | 说明 |
-| ---------------- | ------------------- | ---- | ---------------------------------------------------- |
-| interactionEvent | `string` | ✅ | 触发此 hook 的交互事件。 |
-| sessionId | `string` | ✅ | 此事件的 Session ID(不是 Interaction ID),如适用。 |
-| applicationId | `string` | ✅ | 此事件相关的应用 ID,如适用。 |
-| application | `ApplicationEntity` | ✅ | 此事件相关的应用信息,如适用。 |
+### Management API 上下文字段 \{#management-api-context-fields}
-### Management API 上下文体字段 \{#management-api-context-body-fields}
+当变更由 Management API 调用触发时存在。
-由 Management API 调用触发的数据变更 hook 事件。
+| Field | Type | Optional | Notes |
+| ------------ | -------- | -------- | --------------------------------------------------------------- |
+| path | `string` | ✅ | 触发此 hook 的 API 调用路径。 |
+| method | `string` | ✅ | API 调用的 HTTP 方法。 |
+| status | `number` | ✅ | API 调用的响应状态码。 |
+| params | `object` | ✅ | API 调用的 koa 路径参数。 |
+| matchedRoute | `string` | ✅ | koa 匹配的路由。Logto 使用此字段匹配启用的 webhook 事件过滤器。 |
-| 字段 | 类型 | 可选 | 说明 |
-| ------------ | -------- | ---- | -------------------------------------------------------------------------------- |
-| path | `string` | ✅ | 触发此 hook 的 API 调用路径。 |
-| method | `string` | ✅ | 触发此 hook 的 API 调用方法。 |
-| status | `number` | ✅ | 触发此 hook 的 API 调用响应状态码。 |
-| params | `object` | ✅ | 触发此 hook 的 API 调用的 koa 路径参数。 |
-| matchedRoute | `string` | ✅ | 触发此 hook 的 API 调用的 koa 匹配路由。Logto 使用此字段匹配已启用的 hook 事件。 |
+### 事件特定数据有效负载 \{#event-specific-data-payloads}
-### 数据负载体字段 \{#data-payload-body-fields}
+每个数据变更事件都包含一个顶级 `data` 字段,携带受影响的实体,或在变更无法总结为单个实体时为 `null`(删除和成员事件)。某些事件还包括 `data` 之外的事件特定顶级字段——`Organization.Membership.Updated` 就是这样一个例子,下面有详细说明。
-**用户事件**
+#### 用户事件 \{#user-events}
-| 事件 | 字段 | 类型 | 可选 | 说明 |
-| ----------------- | ---- | ---------- | ---- | ---------------------- |
-| User.Created | data | UserEntity | | 此事件创建的用户实体。 |
-| User.Data.Updated | data | UserEntity | | 此事件更新的用户实体。 |
-| User.Deleted | data | null | / | |
+| Event | Field | Type | Optional | Notes |
+| ----------------- | ----- | ------------ | -------- | ---------------- |
+| User.Created | data | `UserEntity` | | 创建的用户实体。 |
+| User.Data.Updated | data | `UserEntity` | | 更新的用户实体。 |
+| User.Deleted | data | `null` | / | |
-**角色 (Role) 事件**
+#### 角色事件 \{#role-events}
```tsx
type Role = {
@@ -145,23 +169,23 @@ type Scope = {
};
```
-| 事件 | 字段 | 类型 | 可选 | 说明 |
-| ------------------ | ------ | ------- | ---- | ------------------------------------------------------------------------------------- |
-| Role.Created | data | Role | | 此事件创建的角色 (Role) 实体。 |
-| Role.Data.Updated | data | Role | | 此事件更新的角色 (Role) 实体。 |
-| Role.Deleted | data | null | | |
-| Role.Scope.Updated | data | Scope[] | | 分配给角色 (Role) 的已更新权限 (Scope)。 |
-| Role.Scope.Updated | roleId | string | ✅ | 分配权限 (Scope) 的角色 (Role) ID。(仅当事件由创建带有预分配权限的新角色触发时可用) |
+| Event | Field | Type | Optional | Notes |
+| ------------------- | ------ | --------- | -------- | --------------------------------------------------------------------- |
+| Role.Created | data | `Role` | | 创建的角色实体。 |
+| Role.Data.Updated | data | `Role` | | 更新的角色实体。 |
+| Role.Deleted | data | `null` | / | |
+| Role.Scopes.Updated | data | `Scope[]` | | 分配给角色的更新权限。 |
+| Role.Scopes.Updated | roleId | `string` | ✅ | 分配权限的角色 ID。(仅在事件由创建具有预分配权限的角色触发时可用。) |
-**权限 (Scope) 事件**
+#### 权限 (Scope) 事件 \{#permission-events}
-| 事件 | 字段 | 类型 | 可选 | 说明 |
-| ------------------ | ---- | ----- | ---- | ------------------------------- |
-| Scope.Created | data | Scope | | 此事件创建的权限 (Scope) 实体。 |
-| Scope.Data.Updated | data | Scope | | 此事件更新的权限 (Scope) 实体。 |
-| Scope.Deleted | data | null | / | |
+| Event | Field | Type | Optional | Notes |
+| ------------------ | ----- | ------- | -------- | ---------------- |
+| Scope.Created | data | `Scope` | | 创建的权限实体。 |
+| Scope.Data.Updated | data | `Scope` | | 更新的权限实体。 |
+| Scope.Deleted | data | `null` | / | |
-**组织 (Organization) 事件**
+#### 组织事件 \{#organization-events}
```tsx
type Organization = {
@@ -173,14 +197,139 @@ type Organization = {
};
```
-| 事件 | 字段 | 类型 | 可选 | 说明 |
-| ------------------------------- | ---- | ------------ | ---- | -------------------------------------- |
-| Organization.Created | data | Organization | | 此事件创建的组织 (Organization) 实体。 |
-| Organization.Data.Updated | data | Organization | | 此事件更新的组织 (Organization) 实体。 |
-| Organization.Deleted | data | null | / | |
-| Organization.Membership.Updated | data | null | / | |
+| Event | Field | Type | Optional | Notes |
+| ------------------------------- | ----- | -------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------- |
+| Organization.Created | data | `Organization` | | 创建的组织实体。 |
+| Organization.Data.Updated | data | `Organization` | | 更新的组织实体。 |
+| Organization.Deleted | data | `null` | / | |
+| Organization.Membership.Updated | data | `null` | / | 变更由可选的顶级增量数组描述。参见下面的 [Organization.Membership.Updated 有效负载](#organizationmembershipupdated-payload)。 |
+
+##### Organization.Membership.Updated 有效负载 \{#organizationmembershipupdated-payload}
+
+除了[通用字段](#common-fields)以及依触发源而定的 API 上下文字段(Management API 路由对应 [Management API 上下文](#management-api-context-fields),即时 (JIT) 配置对应 [Experience API 上下文](#experience-api-context-fields))之外,`Organization.Membership.Updated` 事件还携带一个 `organizationId`,以及有效负载顶级的可选增量数组(在 `event`、`createdAt` 等旁边,**不在** `data` 内,对于此事件始终为 `null`)。
+
+| Field | Type | Optional | Notes |
+| --------------------- | ---------- | -------- | --------------------------------------------------------------------------- |
+| organizationId | `string` | | 成员变更的组织。 |
+| addedUserIds | `string[]` | ✅ | 此触发器新增的用户 ID。当没有用户被添加,或触发器不影响用户成员时省略。 |
+| removedUserIds | `string[]` | ✅ | 此触发器移除的用户 ID。当没有用户被移除时省略。 |
+| addedApplicationIds | `string[]` | ✅ | 新增的应用程序 ID。当没有应用程序被添加,或触发器不影响应用程序成员时省略。 |
+| removedApplicationIds | `string[]` | ✅ | 移除的应用程序 ID。当没有应用程序被移除时省略。 |
+
+四个增量数组是**可选且附加的**——它们不会改变不期望它们的消费者的现有有效负载结构,且遗留的 `data: null` 字段仍然不变地发出。
+
+###### 触发器及其可能发出的增量字段 \{#membership-triggers}
+
+| Trigger | Possible delta fields |
+| ------------------------------------------------------- | ---------------------------------------------- |
+| `POST /organizations/:id/users` | `addedUserIds` |
+| `PUT /organizations/:id/users` | `addedUserIds`, `removedUserIds` |
+| `DELETE /organizations/:id/users/:userId` | `removedUserIds` |
+| `POST /organizations/:id/applications` | `addedApplicationIds` |
+| `PUT /organizations/:id/applications` | `addedApplicationIds`, `removedApplicationIds` |
+| `DELETE /organizations/:id/applications/:applicationId` | `removedApplicationIds` |
+| `PUT /organization-invitations/:id/status` (`Accepted`) | `addedUserIds` |
+| 将用户添加到新组织时的即时 (JIT) 供应 | `addedUserIds` |
+
+###### 空增量被省略——缺席 ≠ 空变更 \{#empty-deltas-are-omitted}
+
+空增量数组**完全省略**在有效负载中。例如,一个用现有集合替换成员集的 `PUT /organizations/:id/users` 不会产生实际变更,有效负载仅简化为 `{ organizationId }`,所有四个增量字段缺失。同样适用于重新添加现有成员、已是成员的用户重新接受邀请。
+
+**消费者必须将缺失字段视为“该方面没有变更”,而不是“空变更”。**
+
+###### 每个数组的上限(静默截断) \{#membership-delta-cap}
+
+每个增量数组的上限为**5000 个条目**。当单个 Management API 调用在一次操作中添加或移除超过 5000 个用户(或应用程序)时,相应的增量数组会被静默截断为其前 5000 个条目——**没有在有效负载中标记**上限触发。
+
+如果你的应用程序执行可能在一次调用中影响超过 5000 个成员的管理批量操作,请将正好 5000 个条目的数组视为通过 Management API 调和权威成员的信号:
+
+- `GET /organizations/:id/users`——完整的用户成员。
+- `GET /organizations/:id/applications`——完整的应用程序成员。
+
+这遵循与 GitHub 的 `push` 事件相同的模式,该事件将 `commits` 限制为 20 个条目,并指向消费者使用比较 API 获取完整列表。
+
+###### 跳过无操作事件 \{#skipping-no-op-events}
+
+每次针对成员路由的 `PUT` 都会发出一个事件,无论是否实际发生了变更——以便任何状态替换调用至少有一个 webhook 传递用于审计目的。要在消费者端跳过无操作传递,请过滤增量数组的存在:
+
+```ts
+if (
+ payload.addedUserIds?.length ||
+ payload.removedUserIds?.length ||
+ payload.addedApplicationIds?.length ||
+ payload.removedApplicationIds?.length
+) {
+ // 实际成员变更——处理它
+}
+```
-**组织角色 (OrganizationRole) 事件**
+`?.length` 对于 `undefined` 和 `[]` 都是假的,因此无论字段是缺失还是(在某个假设的未来)作为空数组发出,相同的谓词都是稳健的。
+
+###### 示例有效负载 \{#membership-example-payloads}
+
+**添加用户 (`POST /organizations/:id/users`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "addedUserIds": ["u_001"]
+}
+```
+
+**替换用户成员集 (`PUT /organizations/:id/users`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "addedUserIds": ["u_002"],
+ "removedUserIds": ["u_001"]
+}
+```
+
+**移除用户 (`DELETE /organizations/:id/users/:userId`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "removedUserIds": ["u_001"]
+}
+```
+
+**添加应用程序 (`POST /organizations/:id/applications`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "addedApplicationIds": ["app_xyz"]
+}
+```
+
+**重新添加现有成员、无操作 `PUT` 或已是成员的邀请重新接受(无实际变更):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc"
+}
+```
+
+**达到 5000 上限的批量操作(静默截断):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "removedUserIds": ["u_0001", "u_0002", "/* … 总共正好 5000 个条目 */"]
+}
+```
+
+看到一个正好 5000 个条目的数组应该提示进行调和 `GET /organizations/:id/users`(或 `/applications`)。
+
+#### 组织角色事件 \{#organization-role-events}
```tsx
type OrganizationRole = {
@@ -198,27 +347,32 @@ type OrganizationScope = {
};
```
-| 事件 | 字段 | 类型 | 可选 | 说明 |
-| ------------------------------ | ------------------ | ---------------- | ---- | ----------------------------------------------------------------------------------------------------- |
-| OrganizationRole.Created | data | OrganizationRole | | 此事件创建的组织角色 (OrganizationRole) 实体。 |
-| OrganizationRole.Data.Updated | data | OrganizationRole | | 此事件更新的组织角色 (OrganizationRole) 实体。 |
-| OrganizationRole.Deleted | data | null | / | |
-| OrganizationRole.Scope.Updated | data | null | / | |
-| OrganizationRole.Scope.Updated | organizationRoleId | string | ✅ | 分配权限 (Scope) 的组织角色 (OrganizationRole) ID。(仅当事件由创建带有预分配权限的新角色触发时可用) |
+| Event | Field | Type | Optional | Notes |
+| ------------------------------- | ------------------ | ------------------ | -------- | --------------------------------------------------------------------- |
+| OrganizationRole.Created | data | `OrganizationRole` | | 创建的组织角色实体。 |
+| OrganizationRole.Data.Updated | data | `OrganizationRole` | | 更新的组织角色实体。 |
+| OrganizationRole.Deleted | data | `null` | / | |
+| OrganizationRole.Scopes.Updated | data | `null` | / | |
+| OrganizationRole.Scopes.Updated | organizationRoleId | `string` | ✅ | 分配权限的角色 ID。(仅在事件由创建具有预分配权限的角色触发时可用。) |
+
+#### 组织权限 (Scope) 事件 \{#organization-permission-events}
-**组织权限 (OrganizationScope) 事件**
+| Event | Field | Type | Optional | Notes |
+| ------------------------------ | ----- | ------------------- | -------- | -------------------- |
+| OrganizationScope.Created | data | `OrganizationScope` | | 创建的组织权限实体。 |
+| OrganizationScope.Data.Updated | data | `OrganizationScope` | | 更新的组织权限实体。 |
+| OrganizationScope.Deleted | data | `null` | / | |
-| 事件 | 字段 | 类型 | 可选 | 说明 |
-| ------------------------------ | ---- | ----------------- | ---- | ----------------------------------------- |
-| OrganizationScope.Created | data | OrganizationScope | | 创建的组织权限 (OrganizationScope) 实体。 |
-| OrganizationScope.Data.Updated | data | OrganizationScope | | 更新的组织权限 (OrganizationScope) 实体。 |
-| OrganizationScope.Deleted | data | null | / | |
+## 异常事件有效负载 \{#exception-event-payloads}
-## 异常 hook 事件请求体 \{#exception-hook-events-request-body}
+**事件:** `Identifier.Lockout`。
-可用事件:`Identifier.Lockout`
+在安全事件中触发——例如,连续验证失败后账户被锁定。这些事件始终源自用户界面流程,因此请求体包含:
-请求体是一个包含标准请求体字段和如下附加字段的 JSON 对象:
+- [公共字段](#common-fields)。
+- `ip` 字段(与数据变更事件的形状相同)。
+- [Experience API 上下文字段](#experience-api-context-fields)。
+- 以下异常特定字段。
```tsx
enum SignInIdentifier {
@@ -228,16 +382,7 @@ enum SignInIdentifier {
}
```
-| 字段 | 类型 | 可选 | 说明 |
-| ---------------- | ------------------- | ---- | ---------------------------------------------------- |
-| hookId | `string` | | Logto 中的标识符。 |
-| event | `string` | | 触发此 hook 的事件。 |
-| createdAt | `string` | | 负载的创建时间,ISO 格式。 |
-| userAgent | `string` | ✅ | 请求的 user-agent。 |
-| ip | `string` | ✅ | 请求的 IP 地址。 |
-| interactionEvent | `string` | ✅ | 触发此 hook 的交互事件。 |
-| sessionId | `string` | ✅ | 此事件的 Session ID(不是 Interaction ID),如适用。 |
-| applicationId | `string` | ✅ | 此事件相关的应用 ID,如适用。 |
-| application | `ApplicationEntity` | ✅ | 此事件相关的应用信息,如适用。 |
-| type | `SignInIdentifier` | | 用户的标识符类型,例如 email、phone 或 username。 |
-| value | `string` | | 触发锁定的用户标识符值。 |
+| Field | Type | Optional | Notes |
+| ----- | ------------------ | -------- | ------------------------------------------------ |
+| type | `SignInIdentifier` | | 用户的标识符类型,例如,电子邮件、电话或用户名。 |
+| value | `string` | | 触发锁定的用户标识符值。 |
diff --git a/i18n/zh-TW/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx b/i18n/zh-TW/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx
index 2cf5f1aaf4f..f19f0bd5742 100644
--- a/i18n/zh-TW/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx
+++ b/i18n/zh-TW/docusaurus-plugin-content-docs/current/developers/webhooks/events.mdx
@@ -7,73 +7,73 @@ sidebar_position: 3
# Webhooks 事件
-本指南列出各種 Logto Webhook 事件,並說明每個事件發生的時機。
+本指南列出不同的 Logto webhook 事件,並解釋每個事件發生的時機。
-## 使用者互動 Hook 事件 \{#user-interaction-hook-events}
+## 使用者互動 hook 事件 \{#user-interaction-hook-events}
-| 事件類型 | 說明 |
-| ----------------- | ---------------------------------------- |
-| PostRegister | 使用者透過 UI 介面成功建立新帳號。 |
-| PostSignIn | 使用者透過 UI 介面成功登入。 |
-| PostResetPassword | 使用者透過「忘記密碼」流程成功重設密碼。 |
+| 事件類型 | 描述 |
+| ----------------- | ------------------------------------------ |
+| PostRegister | 使用者透過 UI 介面成功創建新帳戶。 |
+| PostSignIn | 使用者透過 UI 介面成功登入。 |
+| PostResetPassword | 使用者的密碼透過「忘記密碼」流程成功重設。 |
-## 資料變更 Hook 事件 \{#data-mutation-hook-events}
+## 資料變更 hook 事件 \{#data-mutation-hook-events}
### 使用者 \{#user}
-| 事件類型 | 說明 |
-| ----------------------------- | ------------------------------------------------------------------- |
-| User.Created | 建立新使用者帳號。 |
-| User.Deleted | 刪除使用者帳號。 |
-| User.Data.Updated | 更新使用者個人資料,例如電子郵件、頭像、custom.data、社交識別碼等。 |
-| User.SuspensionStatus.Updated | 使用者停權狀態變更(停權或重新啟用)。 |
+| 事件類型 | 描述 |
+| ----------------------------- | --------------------------------------------------------------- |
+| User.Created | 創建新使用者帳戶。 |
+| User.Deleted | 刪除使用者帳戶。 |
+| User.Data.Updated | 更新使用者資料,例如電子郵件、頭像、custom.data、社交識別符等。 |
+| User.SuspensionStatus.Updated | 使用者的停權狀態改變(停權或重新啟用)。 |
-### 角色 (Role) \{#role}
+### 角色 \{#role}
-| 事件類型 | 說明 |
-| ------------------- | -------------------------------------------------------- |
-| Role.Created | 建立新角色 (Role)。 |
-| Role.Deleted | 刪除角色 (Role)。 |
-| Role.Data.Updated | 更新角色 (Role) 資料,例如角色名稱、描述、預設角色狀態。 |
-| Role.Scopes.Updated | 指派給角色 (Role) 的權限 (Permissions) 被新增或移除。 |
+| 事件類型 | 描述 |
+| ------------------- | ------------------------------------------------ |
+| Role.Created | 創建新角色。 |
+| Role.Deleted | 刪除角色。 |
+| Role.Data.Updated | 更新角色資料,例如角色名稱、描述和預設角色狀態。 |
+| Role.Scopes.Updated | 為角色分配的權限被新增或移除。 |
-### 權限 (Permission, Scope) \{#permission-scope}
+### 權限(Scope)\{#permission-scope}
-| 事件類型 | 說明 |
-| ------------------ | ----------------------------------------------- |
-| Scope.Created | 建立新的 API 權限 (Permission)。 |
-| Scope.Deleted | 刪除 API 權限 (Permission)。 |
-| Scope.Data.Updated | 更新 API 權限 (Permission) 資料,例如權限描述。 |
+| 事件類型 | 描述 |
+| ------------------ | ----------------------------------- |
+| Scope.Created | 創建新的 API 權限。 |
+| Scope.Deleted | 刪除 API 權限。 |
+| Scope.Data.Updated | 更新 API 權限的資料,例如權限描述。 |
-### 組織 (Organization) \{#organization}
+### 組織 \{#organization}
-| 事件類型 | 說明 |
-| ------------------------------- | ------------------------------------------------------------------ |
-| Organization.Created | 建立新組織 (Organization)。 |
-| Organization.Deleted | 刪除組織 (Organization)。 |
-| Organization.Data.Updated | 更新組織 (Organization) 資料,例如組織名稱、描述、custom.data 等。 |
-| Organization.Membership.Updated | 組織 (Organization) 成員被新增或移除。 |
+| 事件類型 | 描述 |
+| ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Organization.Created | 創建新組織。 |
+| Organization.Deleted | 刪除組織。 |
+| Organization.Data.Updated | 更新組織資料,例如組織名稱、描述、custom.data 等。 |
+| Organization.Membership.Updated | 使用者或應用程式被新增或移除出組織。負載包含 [membership delta fields](/developers/webhooks/webhooks-request#organizationmembershipupdated-payload)。 |
-### 組織角色 (Organization role) \{#organization-role}
+### 組織角色 \{#organization-role}
-| 事件類型 | 說明 |
-| ------------------------------- | ---------------------------------------------------------------------- |
-| OrganizationRole.Created | 建立新組織角色 (Organization role)。 |
-| OrganizationRole.Deleted | 刪除組織角色 (Organization role)。 |
-| OrganizationRole.Data.Updated | 更新組織角色 (Organization role) 資料,例如名稱與描述。 |
-| OrganizationRole.Scopes.Updated | 指派給組織角色 (Organization role) 的權限 (Permissions) 被新增或移除。 |
+| 事件類型 | 描述 |
+| ------------------------------- | ------------------------------------------ |
+| OrganizationRole.Created | 創建新組織角色。 |
+| OrganizationRole.Deleted | 刪除組織角色。 |
+| OrganizationRole.Data.Updated | 更新組織角色資料,例如組織角色名稱和描述。 |
+| OrganizationRole.Scopes.Updated | 為組織角色分配的權限被新增或移除。 |
-### 組織權限 (Organization permission, scope) \{#organization-permission-scope}
+### 組織權限(Scope)\{#organization-permission-scope}
-| 事件類型 | 說明 |
-| ------------------------------ | ------------------------------------------------------- |
-| OrganizationScope.Created | 建立新組織權限 (Organization permission)。 |
-| OrganizationScope.Deleted | 刪除組織權限 (Organization permission)。 |
-| OrganizationScope.Data.Updated | 更新組織權限 (Organization permission) 資料,例如描述。 |
+| 事件類型 | 描述 |
+| ------------------------------ | -------------------------------------- |
+| OrganizationScope.Created | 創建新的組織權限。 |
+| OrganizationScope.Deleted | 刪除組織權限。 |
+| OrganizationScope.Data.Updated | 更新組織權限的資料,例如組織權限描述。 |
-### Management API 觸發事件 \{#management-api-triggered-events}
+### Management API 觸發的事件 \{#management-api-triggered-events}
-| API endpoint | 事件 |
+| API 端點 | 事件 |
| ---------------------------------------------------------- | ----------------------------------------------------------- |
| POST /users | User.Created |
| DELETE /users/:userId | User.Deleted |
@@ -96,6 +96,10 @@ sidebar_position: 3
| PUT /organizations/:id/users | Organization.Membership.Updated |
| POST /organizations/:id/users | Organization.Membership.Updated |
| DELETE /organizations/:id/users/:userId | Organization.Membership.Updated |
+| PUT /organizations/:id/applications | Organization.Membership.Updated |
+| POST /organizations/:id/applications | Organization.Membership.Updated |
+| DELETE /organizations/:id/applications/:applicationId | Organization.Membership.Updated |
+| PUT /organization-invitations/:id/status (Accepted) | Organization.Membership.Updated |
| POST /organization-roles | OrganizationRole.Created, (OrganizationRole.Scopes.Updated) |
| DELETE /organization-roles/:id | OrganizationRole.Deleted |
| PATCH /organization-roles/:id | OrganizationRole.Data.Updated |
@@ -106,33 +110,34 @@ sidebar_position: 3
| POST /organization-roles/:id/scopes | OrganizationRole.Scopes.Updated |
| DELETE /organization-roles/:id/scopes/:organizationScopeId | OrganizationRole.Scopes.Updated |
-### Experience API 觸發事件 \{#experience-api-triggered-events}
+### Experience API 觸發的事件 \{#experience-api-triggered-events}
-| 使用者互動行為 | 事件 |
-| ------------------------- | ----------------- |
-| 使用者綁定電子郵件 / 電話 | User.Data.Updated |
-| 使用者綁定 MFA | User.Data.Updated |
-| 使用者綁定社交 / SSO | User.Data.Updated |
-| 使用者重設密碼 | User.Data.Updated |
-| 使用者註冊 | User.Created |
+| 使用者互動操作 | 事件 |
+| ---------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- |
+| 使用者電子郵件/電話連結 | User.Data.Updated |
+| 使用者 MFA 連結 | User.Data.Updated |
+| 使用者社交/SSO 連結 | User.Data.Updated |
+| 使用者密碼重設 | User.Data.Updated |
+| 使用者註冊 | User.Created |
+| 使用者透過 [即時佈建 (JIT, Just-in-Time provisioning)](/organizations/just-in-time-provisioning) 自動佈建到組織(匹配電子郵件域或企業級 SSO 連接器) | Organization.Membership.Updated |
-## 例外 Hook 事件 \{#exception-hook-events}
+## 異常 hook 事件 \{#exception-hook-events}
-### 安全性 (Security) \{#security}
+### 安全性 \{#security}
-| 事件類型 | 說明 |
-| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------- |
-| Identifier.Lockout | 由於連續身分驗證失敗,使用者帳號被鎖定。可在以下流程中觸發:
|
+| 事件類型 | 描述 |
+| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------ |
+| Identifier.Lockout | 使用者帳戶因連續身份驗證失敗而被鎖定。可能在以下流程中觸發:
|
## 常見問題 \{#faqs}
-### `PostRegister` 與 `User.Created` 有什麼不同? \{#whats-the-difference-between-postregister-and-usercreated}
+### `PostRegister` 和 `User.Created` 有什麼區別?\{#whats-the-difference-between-postregister-and-usercreated}
-`PostRegister` 於使用者透過註冊流程成功建立新帳號時觸發;`User.Created` 則於透過 Management API 建立新使用者帳號時觸發。
+`PostRegister` 在使用者透過使用者註冊流程成功創建新帳戶時觸發;`User.Created` 在透過 Management API 創建新使用者帳戶時觸發。
diff --git a/i18n/zh-TW/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx b/i18n/zh-TW/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx
index 861012c0358..3c0145cc473 100644
--- a/i18n/zh-TW/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx
+++ b/i18n/zh-TW/docusaurus-plugin-content-docs/current/developers/webhooks/request.mdx
@@ -5,25 +5,62 @@ sidebar_label: Webhooks 請求 (Webhooks request)
sidebar_position: 4
---
-# Webhooks 請求 (Webhooks request)
+# Webhooks 請求
-當有效的 hook 事件被觸發時,Logto 會尋找對應的 webhook,並依每個 hook 設定發送一個 POST 請求。
+當 webhook 事件觸發時,Logto 會向每個訂閱的端點發送一個 `POST` 請求。完整的事件目錄位於 [Webhooks 事件](/developers/webhooks/webhooks-events);本頁記錄了 Logto 傳送的請求**結構**。
## 請求標頭 \{#request-headers}
-| Key | 可自訂 | 說明 |
-| ----------------------- | ------ | ------------------------------------------------------------------------------ |
-| user-agent | ✅ | 預設為 `Logto (https://logto.io/)`。 |
-| content-type | ✅ | 預設為 `application/json`。 |
-| logto-signature-sha-256 | | 請求主體的簽章,詳見[保護你的 webhook](/developers/webhooks/secure-webhooks)。 |
+| Key | 可自訂 | 說明 |
+| ----------------------- | ------ | ---------------------------------------------------------------------------------- |
+| user-agent | ✅ | 預設為 `Logto (https://logto.io/)`。 |
+| content-type | ✅ | 預設為 `application/json`。 |
+| logto-signature-sha-256 | | 請求主體的簽名。請參閱 [保護你的 webhooks](/developers/webhooks/secure-webhooks)。 |
-你可以透過[自訂請求標頭](/developers/webhooks/configure-webhooks/#secure-webhook)(key 相同時)覆寫可自訂的標頭。
+可自訂的標頭可以透過 [secure webhook](/developers/webhooks/configure-webhooks/#secure-webhook) 配置覆蓋。
-## 互動 hook 事件請求主體 \{#interaction-hook-events-request-body}
+## 請求主體概述 \{#request-body-overview}
-可用事件:`PostRegister`、`PostSignIn`、`PostResetPassword`
+主體是一個 JSON 物件。其具體結構取決於事件所屬的類別:
-請求主體是一個 JSON 物件,包含三種類型的資料欄位:
+| 類別 | 事件 | 觸發時機 |
+| -------------- | -------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
+| **使用者流程** | `PostRegister`、`PostSignIn`、`PostResetPassword` | 使用者完成由 Experience API 處理的註冊、登入或重設密碼流程。 |
+| **資料變更** | `User.*`、`Role.*`、`Scope.*`、`Organization.*`、`OrganizationRole.*`、`OrganizationScope.*` | 基礎資料模型被變更 — 透過 Management API 呼叫或 Experience API 上的使用者流程。 |
+| **例外** | `Identifier.Lockout` | 安全事件 — 例如,帳戶在連續驗證失敗後被鎖定。 |
+
+每個類別共享一小組[通用欄位](#common-fields)。然後每個類別會添加其自己的請求上下文欄位以及特定事件的負載。
+
+### 通用欄位 \{#common-fields}
+
+無論類別如何,每次傳送都會包含:
+
+| 欄位 | 類型 | 可選 | 備註 |
+| --------- | -------- | ---- | ------------------------------- |
+| hookId | `string` | | Logto 中的 webhook 配置識別符。 |
+| event | `string` | | 觸發此傳送的事件。 |
+| createdAt | `string` | | 負載創建時間,格式為 ISO 8601。 |
+| userAgent | `string` | ✅ | 觸發請求的 user-agent。 |
+
+每個類別還包括觸發請求的 IP 地址 — 在使用者流程事件中為 `userIp` 欄位,在資料變更和例外事件中為 `ip` 欄位。語義相同;歷史名稱差異是為了向後相容。
+
+## 使用者流程事件負載 \{#user-flow-event-payloads}
+
+**事件:** `PostRegister`、`PostSignIn`、`PostResetPassword`。
+
+當使用者完成由 Experience API 處理的註冊、登入或重設密碼流程時觸發。除了[通用欄位](#common-fields)外,主體還包含:
+
+| 欄位 | 類型 | 可選 | 備註 |
+| ---------------- | -------------------------------------------- | ---- | --------------------------------------------------------------------------------------------------------------------------- |
+| interactionEvent | `'SignIn' \| 'Register' \| 'ForgotPassword'` | | 使用者流程事件類型。分別對應 `PostSignIn` / `PostRegister` / `PostResetPassword`。欄位名稱保留歷史上的「interaction」命名。 |
+| sessionId | `string` | ✅ | 此事件的 Session ID(非 Interaction ID),如果適用。 |
+| userIp | `string` | ✅ | 觸發請求的 IP 地址。 |
+| userId | `string` | ✅ | 與此事件相關的使用者 ID,如果適用。 |
+| user | `UserEntity` | ✅ | 與此事件相關的使用者實體,如果適用。 |
+| applicationId | `string` | ✅ | 與此事件相關的應用程式 ID,如果適用。 |
+| application | `ApplicationEntity` | ✅ | 與此事件相關的應用程式實體,如果適用。 |
+
+#### 實體結構 \{#user-flow-entity-shapes}
```tsx
type UserEntity = {
@@ -60,70 +97,57 @@ type ApplicationEntity = {
};
```
-| 欄位 | 型別 | 選填 | 說明 |
-| ---------------- | ------------------- | ---- | -------------------------------------------------- |
-| hookId | `string` | | Logto 中的識別碼。 |
-| event | `string` | | 觸發此 hook 的事件。 |
-| createdAt | `string` | | 負載建立時間(ISO 格式)。 |
-| interactionEvent | `string` | | 觸發此 hook 的互動事件。 |
-| sessionId | `string` | ✅ | 此事件的 Session ID(非 Interaction ID),如適用。 |
-| userAgent | `string` | ✅ | 觸發此 hook 請求的 user-agent。 |
-| userIp | `string` | ✅ | 觸發此 hook 請求的 IP 位址。 |
-| userId | `string` | ✅ | 此事件相關的 User ID,如適用。 |
-| user | `UserEntity` | ✅ | 此事件相關的使用者實體,如適用。 |
-| applicationId | `string` | ✅ | 此事件相關的 Application ID,如適用。 |
-| application | `ApplicationEntity` | ✅ | 此事件相關的應用程式資訊,如適用。 |
+請參閱 [使用者](/user-management/user-data) 和 [應用程式](/integrate-logto/application-data-structure) 以獲取完整的欄位參考。
-詳細欄位說明請參閱 [使用者](/user-management/user-data)與[應用程式](/integrate-logto/application-data-structure)參考文件。
+## 資料變更事件負載 \{#data-mutation-event-payloads}
-## 資料變更 hook 事件請求主體 \{#data-mutation-hook-events-request-body}
+**事件:** `User.*`、`Role.*`、`Scope.*`、`Organization.*`、`OrganizationRole.*`、`OrganizationScope.*` 下的每個事件 — 請參閱 [Webhooks 事件 → 資料變更 hook 事件](/developers/webhooks/webhooks-events#data-mutation-hook-events) 以獲取完整目錄。
-### 標準請求主體欄位 \{#standard-request-body-fields}
+主體始終包含:
-| 欄位 | 型別 | 選填 | 說明 |
-| --------- | -------- | ---- | -------------------------- |
-| hookId | `string` | | Logto 中的識別碼。 |
-| event | `string` | | 觸發此 hook 的事件。 |
-| createdAt | `string` | | 負載建立時間(ISO 格式)。 |
-| userAgent | `string` | ✅ | 請求的 user-agent。 |
-| ip | `string` | ✅ | 請求的 IP 位址。 |
+- [通用欄位](#common-fields)。
+- 一個 `ip` 欄位 — 觸發請求的 IP 地址(可選,已知時存在)。
+- 描述變更如何觸發的 **API 上下文**。根據觸發來源,上下文有兩種變體之一:
+ - [Experience API 上下文](#experience-api-context-fields) — 當變更來自使用者面向的流程時。
+ - [Management API 上下文](#management-api-context-fields) — 當變更來自直接的 Management API 呼叫時。
+- **事件特定負載** — 在 `data` 中的受影響實體,以及(對於某些事件)其他頂層欄位。請參閱 [事件特定資料負載](#event-specific-data-payloads)。
-### 互動 API context 主體欄位 \{#interaction-api-context-body-fields}
+### Experience API 上下文欄位 \{#experience-api-context-fields}
-由使用者互動 API 呼叫觸發的資料變更 hook 事件。
+當變更由 Experience API 上的使用者面向流程觸發時存在 — 例如,註冊期間的 `User.Created` 或個人資料更新期間的 `User.Data.Updated`。
-可用事件:`User.Created`、`User.Data.Updated`
+| 欄位 | 類型 | 可選 | 備註 |
+| ---------------- | -------------------------------------------- | ---- | ----------------------------------------------------------------------- |
+| interactionEvent | `'SignIn' \| 'Register' \| 'ForgotPassword'` | ✅ | 產生變更的使用者流程事件類型。欄位名稱保留歷史上的「interaction」命名。 |
+| sessionId | `string` | ✅ | 此事件的 Session ID(非 Interaction ID),如果適用。 |
+| applicationId | `string` | ✅ | 應用程式 ID,如果適用。 |
+| application | `ApplicationEntity` | ✅ | 應用程式實體,如果適用。 |
-| 欄位 | 型別 | 選填 | 說明 |
-| ---------------- | ------------------- | ---- | -------------------------------------------------- |
-| interactionEvent | `string` | ✅ | 觸發此 hook 的互動事件。 |
-| sessionId | `string` | ✅ | 此事件的 Session ID(非 Interaction ID),如適用。 |
-| applicationId | `string` | ✅ | 此事件相關的 Application ID,如適用。 |
-| application | `ApplicationEntity` | ✅ | 此事件相關的應用程式資訊,如適用。 |
+### Management API 上下文欄位 \{#management-api-context-fields}
-### Management API context 主體欄位 \{#management-api-context-body-fields}
+當變更由 Management API 呼叫觸發時存在。
-由 Management API 呼叫觸發的資料變更 hook 事件。
+| 欄位 | 類型 | 可選 | 備註 |
+| ------------ | -------- | ---- | ----------------------------------------------------------------- |
+| path | `string` | ✅ | 觸發此 hook 的 API 呼叫路徑。 |
+| method | `string` | ✅ | API 呼叫的 HTTP 方法。 |
+| status | `number` | ✅ | API 呼叫的回應狀態碼。 |
+| params | `object` | ✅ | API 呼叫的 koa 路徑參數。 |
+| matchedRoute | `string` | ✅ | koa 匹配的路由。Logto 使用此欄位來匹配啟用的 webhook 事件過濾器。 |
-| 欄位 | 型別 | 選填 | 說明 |
-| ------------ | -------- | ---- | ------------------------------------------------------------------------------ |
-| path | `string` | ✅ | 觸發此 hook 的 API 呼叫路徑。 |
-| method | `string` | ✅ | 觸發此 hook 的 API 呼叫方法。 |
-| status | `number` | ✅ | 觸發此 hook 的 API 呼叫回應狀態碼。 |
-| params | `object` | ✅ | 觸發此 hook 的 API 請求 koa 路徑參數。 |
-| matchedRoute | `string` | ✅ | 觸發此 hook 的 API 呼叫 koa 匹配路由。Logto 會用此欄位比對已啟用的 hook 事件。 |
+### 事件特定資料負載 \{#event-specific-data-payloads}
-### 資料負載主體欄位 \{#data-payload-body-fields}
+每個資料變更事件都包含一個頂層的 `data` 欄位,攜帶受影響的實體,或在變更無法總結為單一實體時(刪除和成員事件)為 `null`。某些事件還包括 `data` 之外的事件特定頂層欄位 — `Organization.Membership.Updated` 就是這樣一個例子,詳見下文。
-**使用者事件**
+#### 使用者事件 \{#user-events}
-| 事件 | 欄位 | 型別 | 選填 | 說明 |
-| ----------------- | ---- | ---------- | ---- | ------------------------ |
-| User.Created | data | UserEntity | | 此事件建立的使用者實體。 |
-| User.Data.Updated | data | UserEntity | | 此事件更新的使用者實體。 |
-| User.Deleted | data | null | / | |
+| 事件 | 欄位 | 類型 | 可選 | 備註 |
+| ----------------- | ---- | ------------ | ---- | ------------------ |
+| User.Created | data | `UserEntity` | | 創建的使用者實體。 |
+| User.Data.Updated | data | `UserEntity` | | 更新的使用者實體。 |
+| User.Deleted | data | `null` | / | |
-**角色事件**
+#### 角色事件 \{#role-events}
```tsx
type Role = {
@@ -145,23 +169,23 @@ type Scope = {
};
```
-| 事件 | 欄位 | 型別 | 選填 | 說明 |
-| ------------------ | ------ | ------- | ---- | ------------------------------------------------------------------------------------ |
-| Role.Created | data | Role | | 此事件建立的角色 (Role) 實體。 |
-| Role.Data.Updated | data | Role | | 此事件更新的角色 (Role) 實體。 |
-| Role.Deleted | data | null | | |
-| Role.Scope.Updated | data | Scope[] | | 指派給角色 (Role) 的最新權限範圍 (Scopes)。 |
-| Role.Scope.Updated | roleId | string | ✅ | 權限範圍 (Scopes) 指派到的角色 (Role) ID。(僅於建立新角色並預先指派權限範圍時提供) |
+| 事件 | 欄位 | 類型 | 可選 | 備註 |
+| ------------------- | ------ | --------- | ---- | ------------------------------------------------------------------------------- |
+| Role.Created | data | `Role` | | 創建的角色實體。 |
+| Role.Data.Updated | data | `Role` | | 更新的角色實體。 |
+| Role.Deleted | data | `null` | / | |
+| Role.Scopes.Updated | data | `Scope[]` | | 分配給角色的更新權限範圍。 |
+| Role.Scopes.Updated | roleId | `string` | ✅ | 分配權限範圍的角色 ID。(僅在事件由創建具有預先分配權限範圍的角色觸發時可用。) |
-**權限(Scope)事件**
+#### 權限(範圍)事件 \{#permission-events}
-| 事件 | 欄位 | 型別 | 選填 | 說明 |
-| ------------------ | ---- | ----- | ---- | ----------------------------------- |
-| Scope.Created | data | Scope | | 此事件建立的權限範圍 (Scope) 實體。 |
-| Scope.Data.Updated | data | Scope | | 此事件更新的權限範圍 (Scope) 實體。 |
-| Scope.Deleted | data | null | / | |
+| 事件 | 欄位 | 類型 | 可選 | 備註 |
+| ------------------ | ---- | ------- | ---- | -------------------- |
+| Scope.Created | data | `Scope` | | 創建的權限範圍實體。 |
+| Scope.Data.Updated | data | `Scope` | | 更新的權限範圍實體。 |
+| Scope.Deleted | data | `null` | / | |
-**組織 (Organization) 事件**
+#### 組織事件 \{#organization-events}
```tsx
type Organization = {
@@ -173,14 +197,139 @@ type Organization = {
};
```
-| 事件 | 欄位 | 型別 | 選填 | 說明 |
-| ------------------------------- | ---- | ------------ | ---- | -------------------------------------- |
-| Organization.Created | data | Organization | | 此事件建立的組織 (Organization) 實體。 |
-| Organization.Data.Updated | data | Organization | | 此事件更新的組織 (Organization) 實體。 |
-| Organization.Deleted | data | null | / | |
-| Organization.Membership.Updated | data | null | / | |
+| 事件 | 欄位 | 類型 | 可選 | 備註 |
+| ------------------------------- | ---- | -------------- | ---- | --------------------------------------------------------------------------------------------------------------------------- |
+| Organization.Created | data | `Organization` | | 創建的組織實體。 |
+| Organization.Data.Updated | data | `Organization` | | 更新的組織實體。 |
+| Organization.Deleted | data | `null` | / | |
+| Organization.Membership.Updated | data | `null` | / | 變更由可選的頂層增量陣列描述。請參閱下文的 [Organization.Membership.Updated 負載](#organizationmembershipupdated-payload)。 |
+
+##### Organization.Membership.Updated 負載 \{#organizationmembershipupdated-payload}
+
+除了[共用欄位](#common-fields)以及依觸發來源而定的 API 上下文欄位(Management API 路由對應 [Management API 上下文](#management-api-context-fields),即時 (JIT) 佈建對應 [Experience API 上下文](#experience-api-context-fields))之外,`Organization.Membership.Updated` 事件還攜帶一個 `organizationId`,以及在負載頂層的可選增量陣列(與 `event`、`createdAt` 等並列,**不在** `data` 中,對於此事件始終為 `null`)。
+
+| 欄位 | 類型 | 可選 | 備註 |
+| --------------------- | ---------- | ---- | ------------------------------------------------------------------- |
+| organizationId | `string` | | 成員變更的組織。 |
+| addedUserIds | `string[]` | ✅ | 此觸發新增的使用者 ID。當未新增使用者或觸發不影響使用者成員時省略。 |
+| removedUserIds | `string[]` | ✅ | 此觸發移除的使用者 ID。當未移除使用者時省略。 |
+| addedApplicationIds | `string[]` | ✅ | 新增的應用程式 ID。當未新增應用程式或觸發不影響應用程式成員時省略。 |
+| removedApplicationIds | `string[]` | ✅ | 移除的應用程式 ID。當未移除應用程式時省略。 |
+
+四個增量陣列是**可選且附加的** — 它們不會改變對不期望它們的消費者的現有負載結構,並且遺留的 `data: null` 欄位仍然不變地發出。
+
+###### 觸發器及其可能發出的增量欄位 \{#membership-triggers}
+
+| 觸發器 | 可能的增量欄位 |
+| ------------------------------------------------------- | ---------------------------------------------- |
+| `POST /organizations/:id/users` | `addedUserIds` |
+| `PUT /organizations/:id/users` | `addedUserIds`、`removedUserIds` |
+| `DELETE /organizations/:id/users/:userId` | `removedUserIds` |
+| `POST /organizations/:id/applications` | `addedApplicationIds` |
+| `PUT /organizations/:id/applications` | `addedApplicationIds`、`removedApplicationIds` |
+| `DELETE /organizations/:id/applications/:applicationId` | `removedApplicationIds` |
+| `PUT /organization-invitations/:id/status` (`Accepted`) | `addedUserIds` |
+| 將使用者新增至新組織時的即時 (JIT) 佈建 | `addedUserIds` |
+
+###### 空增量被省略 — 缺席 ≠ 空變更 \{#empty-deltas-are-omitted}
+
+空增量陣列會從負載中**完全省略**。例如,將成員集替換為現有集的 `PUT /organizations/:id/users` 不會產生實際變更,負載僅簡化為 `{ organizationId }`,所有四個增量欄位均缺席。同樣適用於重新添加現有成員、已是成員的使用者重新接受邀請。
+
+**消費者必須將缺失欄位視為「該方面無變更」,而不是「空變更」。**
+
+###### 每個陣列的上限(靜默截斷) \{#membership-delta-cap}
+
+每個增量陣列的上限為 **5000 個條目**。當單個 Management API 呼叫在一次操作中新增或移除超過 5000 個使用者(或應用程式)時,對應的增量陣列會靜默截斷為其前 5000 個條目 — **負載中沒有標記**表示上限已觸發。
+
+如果你的應用程式執行的管理批量操作可能在一次呼叫中影響超過 5000 個成員,請將正好 5000 個條目的陣列視為信號,通過 Management API 協調權威成員:
+
+- `GET /organizations/:id/users` — 完整的使用者成員。
+- `GET /organizations/:id/applications` — 完整的應用程式成員。
+
+這遵循 GitHub 的 `push` 事件的相同模式,該事件將 `commits` 限制為 20 個條目,並指示消費者使用比較 API 獲取完整列表。
+
+###### 跳過無操作事件 \{#skipping-no-op-events}
+
+每次針對成員路由的 `PUT` 都會發出事件,無論是否實際改變 — 以便任何狀態替換呼叫至少有一個 webhook 傳送以供審計。要在消費者端跳過無操作傳送,請過濾增量陣列的存在:
+
+```ts
+if (
+ payload.addedUserIds?.length ||
+ payload.removedUserIds?.length ||
+ payload.addedApplicationIds?.length ||
+ payload.removedApplicationIds?.length
+) {
+ // 實際成員變更 — 處理它
+}
+```
-**組織角色 (OrganizationRole) 事件**
+`?.length` 對於 `undefined` 和 `[]` 都是偽值,因此無論欄位是缺席還是(在某個假設的未來)作為空陣列發出,相同的謂詞都是穩健的。
+
+###### 範例負載 \{#membership-example-payloads}
+
+**新增使用者(`POST /organizations/:id/users`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "addedUserIds": ["u_001"]
+}
+```
+
+**替換使用者成員集(`PUT /organizations/:id/users`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "addedUserIds": ["u_002"],
+ "removedUserIds": ["u_001"]
+}
+```
+
+**移除使用者(`DELETE /organizations/:id/users/:userId`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "removedUserIds": ["u_001"]
+}
+```
+
+**新增應用程式(`POST /organizations/:id/applications`):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "addedApplicationIds": ["app_xyz"]
+}
+```
+
+**重新添加現有成員、無操作 `PUT` 或已是成員的邀請重新接受(無實際變更):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc"
+}
+```
+
+**達到 5000 上限的批量操作(靜默截斷):**
+
+```json
+{
+ "event": "Organization.Membership.Updated",
+ "organizationId": "org_abc",
+ "removedUserIds": ["u_0001", "u_0002", "/* … 總共正好 5000 個條目 */"]
+}
+```
+
+看到正好 5000 個條目的陣列應提示協調 `GET /organizations/:id/users`(或 `/applications`)。
+
+#### 組織角色事件 \{#organization-role-events}
```tsx
type OrganizationRole = {
@@ -198,27 +347,32 @@ type OrganizationScope = {
};
```
-| 事件 | 欄位 | 型別 | 選填 | 說明 |
-| ------------------------------ | ------------------ | ---------------- | ---- | ---------------------------------------------------------------------------------------------------- |
-| OrganizationRole.Created | data | OrganizationRole | | 此事件建立的組織角色 (OrganizationRole) 實體。 |
-| OrganizationRole.Data.Updated | data | OrganizationRole | | 此事件更新的組織角色 (OrganizationRole) 實體。 |
-| OrganizationRole.Deleted | data | null | / | |
-| OrganizationRole.Scope.Updated | data | null | / | |
-| OrganizationRole.Scope.Updated | organizationRoleId | string | ✅ | 權限範圍 (Scopes) 指派到的組織角色 (OrganizationRole) ID。(僅於建立新角色並預先指派權限範圍時提供) |
+| 事件 | 欄位 | 類型 | 可選 | 備註 |
+| ------------------------------- | ------------------ | ------------------ | ---- | ------------------------------------------------------------------------------- |
+| OrganizationRole.Created | data | `OrganizationRole` | | 創建的組織角色實體。 |
+| OrganizationRole.Data.Updated | data | `OrganizationRole` | | 更新的組織角色實體。 |
+| OrganizationRole.Deleted | data | `null` | / | |
+| OrganizationRole.Scopes.Updated | data | `null` | / | |
+| OrganizationRole.Scopes.Updated | organizationRoleId | `string` | ✅ | 分配權限範圍的角色 ID。(僅在事件由創建具有預先分配權限範圍的角色觸發時可用。) |
+
+#### 組織權限(範圍)事件 \{#organization-permission-events}
-**組織權限(OrganizationScope)事件**
+| 事件 | 欄位 | 類型 | 可選 | 備註 |
+| ------------------------------ | ---- | ------------------- | ---- | ------------------------ |
+| OrganizationScope.Created | data | `OrganizationScope` | | 創建的組織權限範圍實體。 |
+| OrganizationScope.Data.Updated | data | `OrganizationScope` | | 更新的組織權限範圍實體。 |
+| OrganizationScope.Deleted | data | `null` | / | |
-| 事件 | 欄位 | 型別 | 選填 | 說明 |
-| ------------------------------ | ---- | ----------------- | ---- | --------------------------------------------------- |
-| OrganizationScope.Created | data | OrganizationScope | | 此事件建立的組織權限範圍 (OrganizationScope) 實體。 |
-| OrganizationScope.Data.Updated | data | OrganizationScope | | 此事件更新的組織權限範圍 (OrganizationScope) 實體。 |
-| OrganizationScope.Deleted | data | null | / | |
+## 例外事件負載 \{#exception-event-payloads}
-## 例外 hook 事件請求主體 \{#exception-hook-events-request-body}
+**事件:** `Identifier.Lockout`。
-可用事件:`Identifier.Lockout`
+在安全事件中觸發 — 例如,帳戶在連續驗證失敗後被鎖定。這些事件始終源自使用者面向的流程,因此主體攜帶:
-請求主體是一個 JSON 物件,包含標準請求主體欄位與下列額外欄位:
+- [通用欄位](#common-fields)。
+- `ip` 欄位(與資料變更事件的形狀相同)。
+- [Experience API 上下文欄位](#experience-api-context-fields)。
+- 下列例外特定欄位。
```tsx
enum SignInIdentifier {
@@ -228,16 +382,7 @@ enum SignInIdentifier {
}
```
-| 欄位 | 型別 | 選填 | 說明 |
-| ---------------- | ------------------- | ---- | -------------------------------------------------- |
-| hookId | `string` | | Logto 中的識別碼。 |
-| event | `string` | | 觸發此 hook 的事件。 |
-| createdAt | `string` | | 負載建立時間(ISO 格式)。 |
-| userAgent | `string` | ✅ | 請求的 user-agent。 |
-| ip | `string` | ✅ | 請求的 IP 位址。 |
-| interactionEvent | `string` | ✅ | 觸發此 hook 的互動事件。 |
-| sessionId | `string` | ✅ | 此事件的 Session ID(非 Interaction ID),如適用。 |
-| applicationId | `string` | ✅ | 此事件相關的 Application ID,如適用。 |
-| application | `ApplicationEntity` | ✅ | 此事件相關的應用程式資訊,如適用。 |
-| type | `SignInIdentifier` | | 使用者的識別類型,例如 email、phone 或 username。 |
-| value | `string` | | 觸發鎖定的使用者識別值。 |
+| 欄位 | 類型 | 可選 | 備註 |
+| ----- | ------------------ | ---- | ---------------------------------------------------- |
+| type | `SignInIdentifier` | | 使用者的識別符類型,例如電子郵件、電話或使用者名稱。 |
+| value | `string` | | 觸發鎖定的使用者識別符值。 |