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.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 Perihelium account signs in first and confirms — the invitation only works for the exact email it was sent to. Accepting the invitation also verifies that address, because the link was mailed there and nowhere else.
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 who controls a matching email address can join Acme — from the "join your organization" section of the sign-up page, or through the API's join calls — and they land as a baseline member — elevation stays a human decision made afterwards. The mailbox is proved first: asking to join mails the address a one-time link, and the person chooses a password and joins only when they open it, so nobody can join as an address they cannot read. Asking looks the same for every address, so it cannot be used to find out who has an account. 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.
Lending a slice of your authority to a teammate
A member who holds a permission can delegate it to another member for a bounded time (1 to 30
days): the console's Members page has a Delegate action on each active member, and the API is
POST /api/v1/authz/delegations with delegate_type: "user". You can only lend what you hold, the
usual separation-of-duties rules apply, and the chain is capped at three links. The teammate holds the
permission only while you still do: if your role is removed or lapses, or you leave the organisation,
their delegated permission ends on their next request, and the effective-access view shows each
delegation with what it confers right now. Revoking the delegation ends it at once. Use an access
request when a permission should be granted by someone who reviews it rather than lent by a holder.
Handing over ownership
Ownership moves by an offer, never by editing a role. The owner proposes
(POST /api/v1/ownership-transfers, naming an active member); that member accepts
(POST /api/v1/ownership-transfers/{id}/accept). Both must have signed in recently, only a
person can do either, and the offer lapses after seven days. When it is accepted the
member becomes an owner and the previous owner becomes an administrator in the same
transaction, so nobody is ever without access and the organization is never without an owner.
The proposer can withdraw the offer and the member can decline it. An organization has one open
offer at a time, and a member managed by your identity provider cannot be offered ownership.
Today this is done through the API, and the member is not emailed, so tell them an offer is
waiting. Reference: Ownership transfer.
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. To hand the organization over, transfer ownership; the old owner stays as an administrator and can be removed afterwards.
- 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.