Team
Roles in a workspace, how the owner invites people, and how many people each plan allows.
A workspace can be shared with other people. This page covers who can do what, how invites work, how many people each plan allows, and how access ends.
Roles
A workspace has two roles:
| Role | Who | What changes |
|---|---|---|
owner | The person who created the workspace | Only the owner invites people, revokes invites, removes members and deletes the workspace |
member | Anyone who joined through an invite | Works in the workspace from the dashboard |
Accepting an invite always makes you a member. The dashboard has no other
role and does not change roles.
Some actions belong to the owner alone. A signed-in member who tries them gets
403 FORBIDDEN with the message Only the workspace owner can do this.:
- API keys: listing, creating, updating and revoking them
- Sending domains: adding, verifying and removing them (members can still read them)
- Webhooks: reading, registering, editing and deleting them
- Billing: reading the plan and usage, starting a checkout, opening the billing portal
- Workspace settings: changing or deleting the workspace, its logo and its preferences
API keys are not affected: a key keeps the permissions it was created with, whoever created it. See Permissions.
To know your role before trying, read role in the response of
GET /v1/workspace (the same object is returned by PATCH /v1/workspace and,
with 201, by POST /v1/workspaces): owner for the signed-in owner, member
for any other signed-in person, null when the call uses an API key.
The plan and its quotas belong to the owner's account: what a member sends counts against the owner's monthly email quota. See Rate Limits.
Invite someone
Only the workspace owner can invite people, and only from the dashboard, in Settings → Team. API keys cannot invite anyone, whatever their permissions.
Enter the email address of the person you want to invite. They receive an email with a link to accept the invite.
Inviting members is being opened gradually. If your workspace gets the error
MEMBER_INVITES_RESTRICTED, write to support@tratto.email.
The invite link
- It is personal. Accepting it also confirms the email address it was sent to: the account counts as verified without a separate verification email. Do not forward it.
- It expires after 7 days. After that, the owner sends a new invite.
- It works once. A link that has already been used is refused, except for the account that accepted it, while it is still a member: accepting again succeeds and changes nothing.
- It stops working when the invite is revoked.
What happens to the person who accepts
- They join the workspace as a
member. - They can open the dashboard even without beta access of their own.
- If their account already owns a workspace or belongs to another one, they keep it: their session moves to the workspace they joined, and the selector in the dashboard takes them back to the others (see Workspaces).
How many people each plan allows
The plan of the account that owns the workspace sets how many team members it can have. The team members of your plan are shared by every workspace you own. A person in several workspaces counts once. The count includes the owner (one person) and pending invites:
| Plan | Team members per account |
|---|---|
| Free | 1 (the owner only: the Free plan cannot invite) |
| Starter | 2 |
| Growth | 10 |
| Scale | 25 |
Like the monthly email quota, this limit belongs to the account and is shared
by all its workspaces (requires API 0.28.0 or later; before that, it applied to
each workspace separately). A pending invite holds its place from the moment
the invite is created. The limit is checked when the owner sends an invite and
again when the invite is accepted: if the place was taken in the meantime, the
invited person cannot join until the owner frees one. Over the limit, both
calls answer 429 with QUOTA_EXCEEDED.
If an account is already over the limit, for example after a downgrade, nobody is removed: new people just cannot be invited until the count is back under it.
To free a place, revoke a pending invite or remove a member. To raise the limit, upgrade the plan in Settings → Billing.
GET /v1/workspace returns the limit as limits.membersPerAccount, next to
emailsPerMonth and domains. limits.membersPerWorkspace is still returned
with the same number, kept for compatibility: read membersPerAccount.
Pending invites
Settings → Team lists the members of the workspace and the invites still pending. The owner can revoke a pending invite from there: the link stops working, and the invited person receives no email.
Remove a member
The owner removes members from the dashboard. The removed member loses access immediately and receives an email; their Tratto account stays active. The owner cannot be removed. See Workspaces.
Signing in again
After the sessions of an account are revoked (a password change, or signing out of all devices), sessions started before the revocation no longer open the workspace: the dashboard asks you to sign in again.
From the API
The dashboard uses these routes:
| Route | What it does |
|---|---|
POST /v1/workspace/members/invite | Sends an invite |
GET /v1/workspace/invites | Lists pending invites |
DELETE /v1/workspace/invites/:id | Revokes an invite |
DELETE /v1/workspace/members/:userId | Removes a member |
POST /v1/workspace-invites/lookup | Reads an invite from its link |
POST /v1/workspace-invites/accept | Accepts an invite |
The first four accept the owner's dashboard session only. An API key always
gets 403 FORBIDDEN with the message Only the workspace owner can do this.,
whatever its permissions. For this reason inviteMember and removeMember in
the Node.js SDK, and invite_member and remove_member in the Python SDK,
cannot succeed: use the dashboard.
No route lists the members of a workspace: the list is in the dashboard, in Settings → Team.
Send an invite
{ "email": "ada@example.com", "role": "member" }A successful request returns 201 Created:
{
"data": {
"id": "3f9c0a7e5b2d4c1f8e6a9b0d7c5e3f1a2b4c6d8e0f1a3b5c7d9e1f2a4b6c8d0e",
"email": "ada@example.com",
"invitedAt": "2026-10-06T09:30:00.000Z",
"expiresAt": "2026-10-13T09:30:00.000Z"
}
}The id is 64 hexadecimal characters. The response does not contain the
invite token: the token travels only in the email to the invited person, in
the fragment of the link (https://app.tratto.email/invite?tenant=…#token=…),
so it does not end up in server logs.
GET /v1/workspace/invites returns 200 with the same objects in data:
pending, unexpired invites only, ordered by invitedAt.
DELETE /v1/workspace/invites/:id returns 204.
Accept an invite
The invite page calls lookup and accept with no API key. Both take the
workspace id and the token from the link in the request body:
{ "tenantId": "ws_abc123", "token": "…" }Errors
| Status | Code | When |
|---|---|---|
| 401 | UNAUTHORIZED | The session was started before a revocation of the account's sessions (Sign in again.) |
| 401 | REAUTH_REQUIRED | Accepting with a session older than a revocation of the account's sessions (Sign in again to accept this invite.) |
| 403 | FORBIDDEN | Inviting, listing, revoking or removing without being the owner, or with an API key. A member gets Only the workspace owner can do this. |
| 403 | MEMBER_INVITES_RESTRICTED | Invites are not available for this workspace yet: write to support@tratto.email |
| 404 | NOT_FOUND | Revoking an invite that does not exist, or opening a link whose invite does not exist (Invite not found.) |
| 409 | CONFLICT | Inviting: That address is already a member of this workspace. or That address already has a pending invite. |
| 409 | CONFLICT | Accepting: This invite has already been used., This invite has expired. or You are already a member of this workspace. |
| 409 | CONFLICT | Removing the owner: The workspace owner cannot be removed. |
| 422 | VALIDATION_ERROR | Revoking with an id that is not 64 hexadecimal characters |
| 429 | QUOTA_EXCEEDED | The workspace has reached its limit of people, counting pending invites, when inviting or accepting |
| 429 | RATE_LIMITED | More than 20 invites in an hour by the same owner |
The QUOTA_EXCEEDED body names the plan and the limit:
{
"error": {
"code": "QUOTA_EXCEEDED",
"message": "Member limit reached for the starter plan: 2 people in this workspace, counting pending invites.",
"docs": "https://docs.tratto.email/en/docs/error-codes",
"suggestion": "Revoke a pending invite or remove a member, or upgrade the plan at https://app.tratto.email/settings/billing."
}
}See Error Codes for the format of the error body.
Next: Workspaces · Error Codes
Edit this page on GitHub
Last updated on