Zum Hauptinhalt springen

Webhooks-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; diese Seite dokumentiert die Struktur der Anfrage, die Logto liefert.

Anfrage-Header

KeyAnpassbarHinweise
user-agentStandardmäßig Logto (https://logto.io/).
content-typeStandardmäßig application/json.
logto-signature-sha-256Signatur des Anfragetextes. Siehe Sicherung deiner Webhooks.

Anpassbare Header können über die sichere Webhook-Konfiguration überschrieben werden.

Überblick über den Anfragetext

Der Text ist ein JSON-Objekt. Seine genaue Struktur hängt davon ab, zu welcher Familie das Ereignis gehört:

FamilieEreignisseWann es ausgelöst wird
BenutzerflussPostRegister, PostSignIn, PostResetPasswordEin Benutzer schließt einen Anmelde-, Anmelde- oder Passwortzurücksetzungsfluss ab, der von der Experience API behandelt wird.
DatenmutationUser.*, 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.
AusnahmeIdentifier.LockoutEin Sicherheitsvorfall — zum Beispiel ein Konto, das nach aufeinanderfolgenden fehlgeschlagenen Verifizierungsversuchen gesperrt wurde.

Jede Familie teilt einen kleinen Satz von gemeinsamen Feldern. Jede Familie fügt dann ihre eigenen Anfragekontextfelder sowie eine ereignisspezifische Nutzlast hinzu.

Gemeinsame Felder

In jeder Lieferung unabhängig von der Familie vorhanden:

FeldTypOptionalAnmerkungen
hookIdstringDie Webhook-Konfigurationskennung in Logto.
eventstringDas Ereignis, das diese Lieferung ausgelöst hat.
createdAtstringDie Erstellungszeit der Nutzlast im ISO 8601-Format.
userAgentstringDer 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

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 enthält der Text:

FeldTypOptionalAnmerkungen
interactionEvent'SignIn' | 'Register' | 'ForgotPassword'Der Benutzerfluss-Ereignistyp. Entspricht PostSignIn / PostRegister / PostResetPassword. Der Feldname behält die historische "Interaktions"-Benennung bei.
sessionIdstringDie Sitzungs-ID (nicht Interaktions-ID) für dieses Ereignis, falls zutreffend.
userIpstringDie IP-Adresse der auslösenden Anfrage.
userIdstringDie Benutzer-ID, die mit diesem Ereignis verknüpft ist, falls zutreffend.
userUserEntityDie Benutzerentität, die mit diesem Ereignis verknüpft ist, falls zutreffend.
applicationIdstringDie Anwendungs-ID, die mit diesem Ereignis verknüpft ist, falls zutreffend.
applicationApplicationEntityDie Anwendungsentität, die mit diesem Ereignis verknüpft ist, falls zutreffend.

Entitätsstrukturen

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

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

Siehe Benutzer und Anwendungen für die vollständige Feldreferenz.

Nutzlasten von Datenmutationsereignissen

Ereignisse: jedes Ereignis unter User.*, Role.*, Scope.*, Organization.*, OrganizationRole.*, OrganizationScope.* — siehe Webhooks-Ereignisse → Datenmutations-Hook-Ereignisse für den vollständigen Katalog.

Der Text enthält immer:

  • Die gemeinsamen Felder.
  • 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:
  • Eine ereignisspezifische Nutzlast — die betroffene Entität in data und (für einige Ereignisse) zusätzliche Felder auf oberster Ebene. Siehe ereignisspezifische Daten-Nutzlasten.

Experience API-Kontextfelder

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.

FeldTypOptionalAnmerkungen
interactionEvent'SignIn' | 'Register' | 'ForgotPassword'Der Benutzerfluss-Ereignistyp, der die Änderung hervorgebracht hat. Der Feldname behält die historische "Interaktions"-Benennung bei.
sessionIdstringDie Sitzungs-ID (nicht Interaktions-ID) für dieses Ereignis, falls zutreffend.
applicationIdstringDie Anwendungs-ID, falls zutreffend.
applicationApplicationEntityDie Anwendungsentität, falls zutreffend.

Management API-Kontextfelder

Vorhanden, wenn die Änderung durch einen Management API-Aufruf ausgelöst wurde.

FeldTypOptionalAnmerkungen
pathstringDer Pfad des API-Aufrufs, der diesen Hook ausgelöst hat.
methodstringDie HTTP-Methode des API-Aufrufs.
statusnumberDer Antwortstatuscode des API-Aufrufs.
paramsobjectDie koa-Pfadparameter des API-Aufrufs.
matchedRoutestringDie koa-übereinstimmende Route. Logto verwendet dieses Feld, um aktivierte Webhook-Ereignisfilter abzugleichen.

Ereignisspezifische Daten-Nutzlasten

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.

Benutzerereignisse

EreignisFeldTypOptionalAnmerkungen
User.CreateddataUserEntityDie erstellte Benutzerentität.
User.Data.UpdateddataUserEntityDie aktualisierte Benutzerentität.
User.Deleteddatanull/

Rollenereignisse

type Role = {
id: string;
name: string;
description: string;
type: 'User' | 'MachineToMachine';
isDefault: boolean;
};
type Scope = {
id: string;
name: string;
description: string;
resourceId: string;
createdAt: number;
};
EreignisFeldTypOptionalAnmerkungen
Role.CreateddataRoleDie erstellte Rollenentität.
Role.Data.UpdateddataRoleDie aktualisierte Rollenentität.
Role.Deleteddatanull/
Role.Scopes.UpdateddataScope[]Die aktualisierten Berechtigungen, die der Rolle zugewiesen sind.
Role.Scopes.UpdatedroleIdstringDie Rollen-ID, der Berechtigungen zugewiesen sind. (Nur verfügbar, wenn das Ereignis durch das Erstellen einer Rolle mit vorab zugewiesenen Berechtigungen ausgelöst wurde.)

Berechtigung (Scope) Ereignisse

EreignisFeldTypOptionalAnmerkungen
Scope.CreateddataScopeDie erstellte Berechtigungsentität.
Scope.Data.UpdateddataScopeDie aktualisierte Berechtigungsentität.
Scope.Deleteddatanull/

Organisationsevents

type Organization = {
id: string;
name: string;
description?: string;
customData: object;
createdAt: number;
};
EreignisFeldTypOptionalAnmerkungen
Organization.CreateddataOrganizationDie erstellte Organisationsentität.
Organization.Data.UpdateddataOrganizationDie aktualisierte Organisationsentität.
Organization.Deleteddatanull/
Organization.Membership.Updateddatanull/Die Änderung wird durch optionale Delta-Arrays auf oberster Ebene beschrieben. Siehe Organization.Membership.Updated Nutzlast unten.
Organization.Membership.Updated Nutzlast

Zusätzlich zu den gemeinsamen Feldern und den API-Kontextfeldern, die für die Triggerquelle gelten (Management API-Kontext für Management API-Routen, Experience API-Kontext 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).

FeldTypOptionalAnmerkungen
organizationIdstringDie Organisation, deren Mitgliedschaft sich geändert hat.
addedUserIdsstring[]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.
removedUserIdsstring[]Benutzer-IDs, die durch diesen Auslöser entfernt wurden. Weggelassen, wenn keine Benutzer entfernt wurden.
addedApplicationIdsstring[]Anwendungs-IDs, die neu hinzugefügt wurden. Weggelassen, wenn keine Anwendungen hinzugefügt wurden oder wenn der Auslöser die Anwendungszugehörigkeit nicht beeinflusst.
removedApplicationIdsstring[]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
AuslöserMögliche Delta-Felder
POST /organizations/:id/usersaddedUserIds
PUT /organizations/:id/usersaddedUserIds, removedUserIds
DELETE /organizations/:id/users/:userIdremovedUserIds
POST /organizations/:id/applicationsaddedApplicationIds
PUT /organizations/:id/applicationsaddedApplicationIds, removedApplicationIds
DELETE /organizations/:id/applications/:applicationIdremovedApplicationIds
PUT /organization-invitations/:id/status (Accepted)addedUserIds
Just-in-time Bereitstellung beim Hinzufügen des Benutzers zu einer neuen OrganisationaddedUserIds

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

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)

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

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:

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

Einen Benutzer hinzufügen (POST /organizations/:id/users):

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

Die Benutzerzugehörigkeitsmenge ersetzen (PUT /organizations/:id/users):

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

Einen Benutzer entfernen (DELETE /organizations/:id/users/:userId):

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

Eine Anwendung hinzufügen (POST /organizations/:id/applications):

{
"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):

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

Massenoperation, die das 5000-Limit erreicht (still gekürzt):

{
"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

type OrganizationRole = {
id: string;
name: string;
description?: string;
};
type OrganizationScope = {
id: string;
name: string;
description?: string;
};
EreignisFeldTypOptionalAnmerkungen
OrganizationRole.CreateddataOrganizationRoleDie erstellte Organisationsrollenentität.
OrganizationRole.Data.UpdateddataOrganizationRoleDie aktualisierte Organisationsrollenentität.
OrganizationRole.Deleteddatanull/
OrganizationRole.Scopes.Updateddatanull/
OrganizationRole.Scopes.UpdatedorganizationRoleIdstringDie 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

EreignisFeldTypOptionalAnmerkungen
OrganizationScope.CreateddataOrganizationScopeDie erstellte Organisationsberechtigungsentität.
OrganizationScope.Data.UpdateddataOrganizationScopeDie aktualisierte Organisationsberechtigungsentität.
OrganizationScope.Deleteddatanull/

Ausnahmeereignis-Nutzlasten

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:

enum SignInIdentifier {
Email = 'email',
Phone = 'phone',
Username = 'username',
}
FeldTypOptionalAnmerkungen
typeSignInIdentifierDer Identifikatortyp des Benutzers, z. B. E-Mail, Telefon oder Benutzername.
valuestringDer Identifikatorwert des Benutzers, der die Sperrung ausgelöst hat.