Team members & invitations
Every tenant starts with one person: the owner who signed up. This guide covers the invitation flow that brings the rest of the team in, and the member-management API that governs them afterwards. (If your organization provisions users from an identity provider, see SCIM provisioning — the two coexist, and SCIM-managed members are the IdP's to change, not the console's.)
Getting
403on everything here, in a brand-new organization? If your organization was opened for you by an AI agent, it stays quarantined until you approve the setup on the verification page — invitations, roles and member domains are all refused until then, with that reason in the message. Approving lifts it immediately. See Agent-driven onboarding.
Inviting a teammate
POST /api/v1/members/invites (requires the members:manage permission):
{ "email": "teammate@example.com", "role": "admin" }
The teammate receives an email with a single-use acceptance link, valid for 7 days. The invitation carries the role you chose — any system role except two:
ownercan never be granted by invitation. Ownership transfer is a separate, deliberate operation (not yet available).customeris the end-user population's role, never a workforce grant.
Re-inviting the same email re-issues the invitation: the previous link stops working, the expiry restarts, and the role is updated to whatever you chose the second time. A pending invitation counts toward your plan's member limit — seats can't be stockpiled past the plan by leaving invitations open.
Revoke a pending invitation with DELETE /api/v1/members/invites/{invite_id}; the
emailed link dies immediately.
Accepting
The link opens an acceptance page showing the organization, the role, and the invited email. A new user sets a password and lands signed in (we suggest adding a passkey right away); an invitee who already has a Zynth Auth account signs in first and confirms — the invitation only works for the exact email it was sent to.
Domain auto-join (optional)
If your whole team shares an email domain, you can skip per-person invitations:
POST /api/v1/members/domainswith{"domain": "acme.com"}— the response contains azynth-verify=…value.- Publish it as a TXT record on the domain, then
POST /api/v1/members/domains/{id}/verify. - Turn on the tenant setting
members.domain_join_enabled(it is off by default).
From then on, anyone with a matching email address can join Acme through the API's join call (there is no "join Acme" prompt on the sign-up page today — the door is API-only), and they land as a baseline member — elevation stays a human decision made afterwards. The proof is re-checked continuously: if the TXT record disappears, the door closes by itself. Public email providers (gmail.com and friends) can never be claimed, and only one organization can hold a domain verified at a time.
Managing members
GET /api/v1/members(members:read) — every workforce member, their role, status, and whether they are SCIM-managed.PATCH /api/v1/members/{membership_id}(members:manage) — change a member's role.DELETE /api/v1/members/{membership_id}(members:manage) — remove a member. Removal is immediate and total: the membership ends and every session the member had is revoked in the same operation — there is no window where a removed member's open tab keeps working.
The guardrails
Three refusals you will eventually be glad of:
- The sole owner can neither be removed nor demoted. A tenant can never be left with nobody who can administer it. Add a second owner-capable admin before offboarding the first.
- An invitation whose role breaks your own separation-of-duties rule is refused at the moment it is accepted, naming the rule. The invitation is not used up: reassign the conflicting role (or grant an override through an access request decided by a second approver) and the same link still works. Before v0.33 this refusal was applied to the access but not to the invitation — the person joined with baseline access while this list displayed the role they were invited to.
- SCIM-managed members are refused here with a clear error — changing them in the console would silently fight your IdP's next sync. Change them at the IdP.
- Every action is audited and monitored. Invitations, acceptances, role changes and removals land in the tamper-evident audit log with SOC 2 / ISO 27001 control mappings, and anomaly detection watches for the ugly patterns (invite floods, token guessing, mass removals) out of the box.