Team Management
How to run your team: roles, invitations, member lifecycle, audit logs, and the tenant-admin API behind them.
All of this happens on the Organization page. For a tour of that screen (the member list, per-member usage, and the Identifiers card), see Organization.
Roles
Owner
Full control of the organization:
- Every admin permission
- Change member roles (promote and demote)
- Transfer ownership to another member
- Cannot be removed; ownership must be transferred first
- Exactly one owner per organization
Admin
Full day-to-day management:
- Invite new members
- Suspend, activate and unlock members
- View all member usage
- Access audit logs
- Manage pending invitations
- Cannot change roles or transfer ownership
Member
Standard access:
- Use the platform
- View their own usage
- Manage their own profile and API keys
- Cannot manage other members
Inviting Members
Admin or Owner only
- Click Invite Member
- Enter the email address
- Select a role (Admin or Member)
- Click Send Invite
A person belongs to exactly one organization across the whole platform, so an email address can hold only one account.
- Inviting an address that is already in your own organization is refused: you can see your own member list, so the form tells you plainly that they are already there.
- Inviting an address that already has an account in another organization returns the ordinary success response, but no invitation is created and no email is sent. This is deliberate — a form that answered differently for a known address would be a way of discovering who is on the platform.
So if someone tells you your invitation never arrived, check with them whether they already have an account elsewhere. Moving a person between organizations is a transfer, not a re-registration: ask your platform administrator to arrange it rather than inviting them again.
Invitation Flow
- The invited user receives an email
- They click the invite link
- They set their name and password, which creates their account and signs them in
- They complete onboarding
- They are added to your organization
Invite acceptance is all-or-nothing: the account, the organization membership and the session are created together, so an interrupted acceptance never leaves a half-created account; the invite simply remains usable for a clean retry.
Each invite link works once. After a successful acceptance, reusing the link returns "Invalid or expired invite token". At that point the user should just sign in.
Accepting an Invitation
The invited person opens the link and fills in their name and a password. Two things are worth passing on before they start:
- Name fields accept letters, spaces, hyphens and apostrophes, up to 50 characters. The full Turkish alphabet is accepted. Digits and other punctuation are not — a trailing dot on a surname is the usual culprit — and the form says so inline, under the offending field, before the form is submitted.
- Password requirements are listed on the form as a checklist, so there is no need to guess them.
A successful acceptance leaves them signed in and carries them straight on to onboarding, or to the portal if there is nothing left to complete. They do not have to find the sign-in page and re-enter the password they have just chosen.
When a submission is refused, the page states the actual reason rather than a generic failure, whichever check refused it. A link that has already been used or has expired says exactly that; someone who has already completed their acceptance should simply sign in instead.
The same name rules apply on the onboarding form, so a name accepted in one place is accepted in the other.
Managing Pending Invitations
The pending list shows who has not accepted yet and when each invitation expires. From it you can:
- Resend a pending, still-valid invitation
- Cancel Invite to withdraw one
- Clean up expired to remove all expired invitations at once, leaving valid ones untouched
Invitation Delivery State
An invitation and its email are two separate facts. Creating or resending an invitation succeeds as soon as the invitation exists — the email is handed to a queue and sent a moment later, so anything that goes wrong with the send happens after you have already been told the invitation was created.
The pending list therefore shows a second badge per row, for the email itself:
| Badge | What it means | What to do |
|---|---|---|
| Sending | The email is queued and on its way. | Nothing. Check back shortly. |
| Sent | It was handed to our mail provider successfully. | If it still has not arrived, check spam, then read One email, one account. |
| Delayed | An attempt has not succeeded yet and we are still trying. The invitation link stays valid. | Wait. Resending starts a fresh attempt but does not make it faster. |
| Not delivered | The email will not be sent. | Read the sentence under the badge — it says which case applies. |
| (no badge) | Nothing is recorded about this invitation's email, usually because it predates this feature. | Treat it as unknown, not as failed. |
The most common Not delivered case reads: "This invitation is no longer valid — it expired, was accepted, was cancelled, or a newer invitation replaced it. Create a new invitation if this person still needs access."
That sentence is about the invitation, not the recipient. A resend rotates the token, so an older queued email for the same invitation is dropped rather than sent — which is correct, and which is why you can see this on an invitation you resent successfully seconds earlier.
The platform does not track bounces. No badge here means "the address is wrong" or "their mail server rejected it". Everything on this row describes our own attempt to send.
Hovering a badge shows when the last attempt was made.
Resending Invitations
- Find the invitation in the pending list
- Click Resend
- A reminder email is queued with a fresh link
The reminder is clearly marked as a reminder. Resending invalidates the previous link, so if the recipient received more than one email, only the latest works.
The confirmation reads "Invitation queued — the invitation email has been queued for delivery. Delivery is not confirmed yet." That wording is deliberate: a successful resend means the email was accepted for sending, not that it has been sent. The row's delivery badge is what tells you the rest, and it refreshes itself a couple of seconds later without a page reload.
If the cooldown blocks a resend, the portal shows the platform's own message with the real number of seconds to wait, rather than a generic failure.
Resending has a short cooldown (30 seconds). Expired invitations cannot be resent; the API returns 410 Gone and instructs you to cancel and create a new invitation instead.
POST /api/v1/tenant-admin/invites/{invite_id}/resend
Authorization: Bearer <token>
POST /invites and POST /invites/{id}/resend return the invitation without
a delivery field, on purpose: the email has only just been queued, and
answering delivery: null would assert that no email exists. Only
GET /api/v1/tenant-admin/invites reports delivery. If your integration cares,
read the list back rather than reading the create or resend body.
Member Lifecycle
Admin or Owner only
Suspend User
Temporarily disable access. A suspended member:
- Cannot access the portal
- Cannot make API requests; their keys fail verification while the suspension holds
- Keeps their account, data, settings and keys
This is also what "removing" a member does: it is a reversible suspension, not a deletion.
Activate User
Re-enable a suspended member. Access, including their existing API keys, is restored.
Unlock User
If a member's account is locked after too many failed sign-in attempts, Unlock User clears the lock immediately rather than waiting for it to expire. It clears the lock only; it does not change the member's password, role, or status.
Changing Member Roles
Owner only
- Find the member in the list
- Open the role control
- Select the new role (Admin or Member)
- Confirm the change
Only owners can change roles. Admins cannot promote other members to admin, nor demote existing admins.
PUT /api/v1/tenant-admin/users/{user_id}/role
Authorization: Bearer <token>
Content-Type: application/json
{
"role": "admin"
}
Available roles: admin, user.
Transferring Ownership
Owner only
Ownership transfer is API-only; there is no transfer control in the portal UI.
POST /api/v1/tenant-admin/transfer-ownership
Authorization: Bearer <token>
Content-Type: application/json
{
"new_owner_id": "user-uuid-here"
}
The new owner must be an existing member of the organization. After the transfer you become an admin, and the new owner has full control. This cannot be easily undone.
Usage Visibility
Admins and owners see each member's requests and tokens for the current month to date on the Organization page.
That view is volume only; it carries no per-member cost. To attribute spend to individuals, use the usage export, which includes a cost column. Organization-wide figures live on Usage and Billing.
Audit Logs
Admin or Owner only
Organization activity history, with:
- Timestamp: when the action occurred
- User: who performed it
- Action: what was done
- Details: additional context
Tracked Actions
- Invitations sent, resent and cancelled
- Member suspensions and activations
- Role changes
- Ownership transfers
- API key scope changes
GET /api/v1/tenant-admin/audit-logs
Authorization: Bearer <token>
Query parameters: action (filter by action type), page, page_size.
Your Own Profile
Everyone edits their own details on the Profile page, not the Organization page.
| Editable | Read-only |
|---|---|
| First name | Email (contact an admin to change) |
| Last name | Organization name |
| Phone number | Member since date |
| User ID and Organization ID |
Your User ID and Organization ID are copyable from the Identifiers card, useful for support requests, API debugging and integration setup.
API Reference
Tenant Admin Endpoints
| Method | Endpoint | Description | Access |
|---|---|---|---|
| GET | /api/v1/tenant-admin/users | List all users | Admin, Owner |
| PUT | /api/v1/tenant-admin/users/{id}/role | Update user role | Owner |
| POST | /api/v1/tenant-admin/users/{id}/suspend | Suspend user | Admin, Owner |
| POST | /api/v1/tenant-admin/users/{id}/activate | Activate user | Admin, Owner |
| POST | /api/v1/tenant-admin/users/{id}/unlock | Unlock a locked user | Admin, Owner |
| GET | /api/v1/tenant-admin/invites | List invites, each with a delivery object | Admin, Owner |
| POST | /api/v1/tenant-admin/invites | Create invite | Admin, Owner |
| DELETE | /api/v1/tenant-admin/invites/expired | Clear all expired invites | Admin, Owner |
| DELETE | /api/v1/tenant-admin/invites/{id} | Cancel an invite | Admin, Owner |
| POST | /api/v1/tenant-admin/invites/{id}/resend | Resend invite | Admin, Owner |
| POST | /api/v1/tenant-admin/transfer-ownership | Transfer ownership | Owner |
| GET | /api/v1/tenant-admin/audit-logs | Get audit logs | Admin, Owner |
These endpoints require a JWT session. Public API keys cannot call them. See API Keys.
delivery on a listed invite
GET /api/v1/tenant-admin/invites reports what happened to each invitation's
email:
"delivery": {
"state": "retrying",
"reason_code": "rate_limited",
"last_attempt_at": "2026-09-01T13:20:25.240160+00:00"
}
| Field | Values |
|---|---|
state | queued, retrying, sent, failed |
reason_code | rate_limited, not_deliverable, error, or null |
last_attempt_at | ISO-8601 UTC timestamp, or null |
delivery itself is null when the invitation has no send record at all — an
older invitation, or one created without a notification. That is "unknown", not
"failed".
Retry mechanics and internal error text are not exposed on this endpoint;
state and reason_code are the whole contract. Treat an unrecognised value in
either field as "nothing to report" rather than as an error, so a future value
does not break your integration.
POST /api/v1/tenant-admin/invites answers 400 when the address is already in your own organization, and its ordinary success response when the address has an account in another organization — in the second case nothing is written and no email is sent. A 201 is therefore not proof that an invitation exists; read it back from GET /api/v1/tenant-admin/invites if your integration depends on one. See One email, one account.
Best Practices
For Owners
- Be careful with ownership transfer; it cannot be easily reversed
- Limit admin roles; grant admin only where it is needed
- Review role changes; audit who holds elevated permissions periodically
For Admins
- Clean up expired invitations regularly
- Watch per-member volume for unexpected spikes
- Use audit logs to track important changes
- Record why a member was suspended
For Members
- Keep your profile details current
- Contact your admin about access problems
- Secure your account and rotate your API keys
Troubleshooting
"Cannot invite member"
- Check that you hold the admin or owner role
- Verify the email format
- Check whether an email rate limit has been tripped
"Member not receiving invite"
Start with the row's delivery badge — it tells you whether the email left the platform at all, which decides which of the following is worth doing.
- Delayed: nothing to do yet; the platform is still trying and the link stays valid
- Not delivered: read the sentence under the badge. If it says the invitation is no longer valid, create a new one
- Sent, or no badge at all:
- Check spam and junk folders
- Verify the email address
- Ask whether they already have an account in another organization. If they do, no invitation was sent — see One email, one account
- Resend the invitation, and tell the recipient to use the newest email
"The invitation form will not accept my name"
Names may contain letters (the full Turkish alphabet included), spaces, hyphens and apostrophes, up to 50 characters. Digits and other punctuation are refused, and a trailing dot on a surname is the most common cause. The form points at the offending field before it submits anything.
"Cannot remove member"
- You cannot remove yourself
- You cannot remove the owner; ownership must be transferred first
"Cannot change role"
- Only owners can change roles
- The owner's own role cannot be changed; use ownership transfer instead
"Cannot transfer ownership"
- Only the current owner can transfer
- The target user must already be a member of the organization