Group webhooks, group reads, and pause for Directory Sync
- Category
- SSO
- Published
Directory Sync sends webhooks for group and membership changes, the Backend API reads a group and its members, and a directory can be paused without removing anyone's access.
Directory Sync has three new capabilities: webhooks for group changes, Backend API reads for a group and its members, and a pause switch for directories. Group pushes from the identity provider also produce fewer events than before.
Group webhooks
Directory Sync keeps Organization memberships and Roles in step with your identity provider, but until now the groups themselves were hard to observe. That matters most when your application maps identity provider groups onto its own objects, such as teams or projects, rather than onto Clerk Organizations alone. The only signal was the user.updated event Directory Sync fires for each member it touches. Your webhook handler fetched the user, read their current groups, and worked out what changed. When an IT admin deleted a group in the identity provider, that produced the same events as every member leaving at once, and nothing in them told the two apart.
Six webhook events now report group changes directly:
directoryGroup.created: the identity provider created a group.directoryGroup.updated: the identity provider renamed a group. The payload carries the newdisplay_name.directoryGroup.deleted: the identity provider deleted a group, or it stopped appearing in a pull sync. The payload carries the last known name.directoryGroup.synced: the identity provider pushed a group in full, whether or not anything changed. Okta sends that push on Push now and on its periodic re-push of unchanged groups, so the event fires once per group per push. It isn't sent for pull-synced directories such as Google Workspace.directoryGroupMembership.created: a user was added to a group.directoryGroupMembership.deleted: a user was removed from a group.causesays why:member_removedwhen the provider took the user out,group_deletedwhen the whole group went away.
Every payload names the directory_id and the group's id and display_name. Membership payloads also carry the member's directory_user_id and the user_id of the Clerk user they're linked to, which is null until that user has been provisioned.
Webhooks can arrive out of order. When two events describe the same group or membership, keep the one with the later updated_at, which is when the directory recorded the change.
Read a group and its members
Two reads join the Directories endpoints:
GET /v1/directories/{directory_id}/groups/{group_id}returns one group as the identity provider reported it, and404once the provider has deleted it.GET /v1/directories/{directory_id}/groups/{group_id}/memberslists the group's members with cursor pagination, up to 500 per page. Each member carries theuser_idof its Clerk user, ornullif that user hasn't been provisioned yet.
A webhook handler that receives a directoryGroup.* event can fetch the group's current state with these reads instead of keeping its own copy of the directory.
Fewer user.updated events on group pushes
Since October 20, a group push from the identity provider records only the members who joined or left. The per-user events a push produces, such as directoryGroupMembership.created and user.updated, cover those users alone. The group-level events don't depend on who changed: a rename sends directoryGroup.updated, and every push sends directoryGroup.synced, so a push with nothing changed sends that one event and nothing else. Before, every push rewrote the whole group, so every member counted as changed on every push, and large groups that Okta re-pushes every few minutes timed out.
If you relied on that fan-out to replay a group, for example by asking a customer to Push now in Okta so your application could rebuild its memberships, listen for directoryGroup.synced instead and page through the group with the members endpoint. That's one event per group per push, however many members the group has.
Pause a directory
A directory can now be paused, from its page in the Clerk Dashboard or by sending paused to PATCH /v1/directories/{directory_id}. Directory responses include the flag. A paused directory rejects provisioning requests and skips scheduled syncs, but keeps the memberships it granted. After you resume a SCIM directory, trigger a resync from the identity provider so it pushes its current state. Requests it sent while the directory was paused were rejected, not queued. A pull-synced directory catches up on its next sync. Disabling a directory withdraws the access it granted instead, so pause when you want changes to stop landing for a while without touching anyone's access.