Invitations
Prerequisites
Section titled “Prerequisites”- You are an admin on the project. Minting and revoking also need a fresh second factor, and the CSRF header on a cookie session, so they are browser-session work rather than API-key work.
- The project has an active email notification channel if you want z4j to auto-send the invite. Without one, the dashboard surfaces the link and you share it manually.
Sending an invite
Section titled “Sending an invite”Dashboard, the project's Members page (/projects/<slug>/settings/members), Invite.
Fill in:
- Email -- target user's email.
- Role --
viewer,auditor,operator, oradmin. There is noownerrole;adminis the highest tier and the brain enforces a last-admin protection so you cannot demote or remove the only admin on a project. - The dialog has no TTL field; links minted from the dashboard are valid for 7 days. Set
ttl_dayson the API call to change it.
Submit. With an active email channel the invitee receives an email containing the single-use accept URL. Without one, the response carries the URL for out-of-band delivery.
Token properties
Section titled “Token properties”- Single-use: accepting invalidates the token immediately. Re-using returns
404witherror: "not_found"and the messageinvalid_or_expired. An unknown, revoked, or expired token returns exactly the same thing, deliberately, so the response never confirms that a token was real. - Default TTL: 7 days (
Z4J_*does not control this; the field is on the invitation record itself). - Bound to the target email: accepting creates the account for the invited address, so the link itself is the credential and no mailbox check happens. If a user with that email already exists, accept is refused with
409; add that user as a member instead. - Stored hashed in Postgres; the plaintext token is shown to the admin once and embedded in the URL.
Accepting
Section titled “Accepting”The accept URL points the invitee at the dashboard's accept page, backed by:
POST /api/v1/invitations/previewBody: {"token": "<single-use-token>"}POST /api/v1/invitations/acceptThe preview returns the invited email, role, and project name. The accept POST takes {token, display_name, password} (password is 12..200 chars, hashed with argon2id); it materialises the user and the membership in one step.
Revoking
Section titled “Revoking”Before acceptance: the project's Members page, "Pending invitations" table, Revoke, then confirm the "Revoke invitation" dialog (or DELETE /api/v1/projects/{slug}/invitations/{invitation_id}).
After acceptance: treat it as a membership change. Demote the role to a lower tier (PATCH membership) or remove the member entirely (DELETE membership). The new authorization takes effect on later project requests, but the user's global browser sessions remain valid for other projects; membership changes do not revoke those sessions.
Rate limits
Section titled “Rate limits”The accept and preview endpoints share a single per-IP bucket: 30 hits per minute combined. The mint endpoint has no separate per-email cap; the per-IP login / general API caps apply to the admin issuing invites.
See rate limits.
Every invite, accept, and revoke writes an audit log entry (invitation.mint, invitation.accept, invitation.revoke). Email delivery adds invitation.email_delivery_requested and invitation.email_delivery_result.