API reference

Team

Members, roles, invitations, ownership and the security audit log of a workspace.

A workspace has members, each with one role: viewer, member, admin or owner (ascending). These endpoints manage the member list and invitations, hand over or close the workspace, and read the security audit log. An API key acts as an admin, so it can manage members and invitations but cannot use the owner-only operations.

The server enforces one permission table for every request. You can read it with GET /team/permissions. See the team and security guide for how the roles are meant to be used.

OperationMethod and pathMinimum role
List membersGET /team/membersviewer
Update a memberPATCH /team/members/{member_id}admin
Remove a memberDELETE /team/members/{member_id}admin
List invitationsGET /team/invitesadmin
Invite a personPOST /team/invitesadmin
Resend an invitationPOST /team/invites/{invite_id}/resendadmin
Revoke an invitationDELETE /team/invites/{invite_id}admin
Transfer ownershipPOST /team/transfer-ownershipowner, session only
Delete the workspaceDELETE /team/workspaceowner, session only
Read the audit logGET /team/auditadmin
Get the permission tableGET /team/permissionsviewer

Role errors

When the caller's role is too low, the answer is 403 with one of these messages (the role names and the area vary):

text
Your role (member) can't change team members. It needs admin access; ask an owner or admin of the workspace.
Your role (viewer) can't do this. It needs admin access; ask an owner or admin of the workspace.

Two rules apply on top of the table:

  • Only an owner may change, disable, remove or invite an owner: 403 Only an owner can add, change or remove an owner.
  • A workspace always keeps one owner who can log in: 400 A workspace needs at least one owner. Make someone else an owner first.

Members

List members

GET /team/members

Lists the people who have joined the workspace, in the order they joined. Pending invitations are not included.

Auth: API key or session token. Role: viewer and up.

Request

bash
curl https://api.sevennadi.si/team/members \
  -H "Authorization: Bearer vk-0123456789abcdef0123456789abcdef"

Response 200 OK

json
[
  {
    "id": "0144c9aa-d4fe-4341-99fd-aa27689ab6a0",
    "name": "Asha Rao",
    "email": "asha@example.test",
    "role": "owner",
    "status": "active",
    "email_verified": true,
    "two_factor_enabled": false,
    "joined_at": "2026-10-13T07:21:47Z",
    "last_active_at": "2026-10-13T09:02:10Z",
    "is_you": false
  }
]

status is active or disabled. last_active_at comes from the member's sessions and may be null. is_you is always false for an API key.

Update a member

PATCH /team/members/{member_id}

Changes a member's role, disables their login, or restores it. Disabling ends all of that member's sessions.

Auth: API key or session token. Role: admin and up.

ParameterInTypeRequiredDescription
member_idpathstring (UUID)yesThe member's id.
rolebodystringnoviewer, member, admin or owner.
disabledbodybooleannotrue blocks the login and ends its sessions; false restores it.

Request

bash
curl -X PATCH https://api.sevennadi.si/team/members/7b1c2a90-5a51-4e0e-9c43-0f7f8f1f2a11 \
  -H "Authorization: Bearer vk-0123456789abcdef0123456789abcdef" \
  -H "Content-Type: application/json" \
  -d '{"role": "admin"}'

Response 200 OK

json
{
  "id": "7b1c2a90-5a51-4e0e-9c43-0f7f8f1f2a11",
  "name": "Ravi Menon",
  "email": "ravi@example.test",
  "role": "admin",
  "status": "active",
  "email_verified": true,
  "two_factor_enabled": false,
  "joined_at": "2026-10-13T08:00:00Z",
  "last_active_at": null,
  "is_you": false
}

Errors

StatusMessage
400role must be one of: owner, admin, member, viewer
400You can't change your own role. Ask another owner or admin.
400You can't disable your own login.
400A workspace needs at least one owner. Make someone else an owner first.
403Only an owner can add, change or remove an owner.
404Member not found

Remove a member

DELETE /team/members/{member_id}

Removes a member from the workspace and ends their sessions. You cannot remove yourself.

Auth: API key or session token. Role: admin and up.

ParameterInTypeRequiredDescription
member_idpathstring (UUID)yesThe member's id.

Request

bash
curl -X DELETE https://api.sevennadi.si/team/members/7b1c2a90-5a51-4e0e-9c43-0f7f8f1f2a11 \
  -H "Authorization: Bearer vk-0123456789abcdef0123456789abcdef"

Response 200 OK

json
{"message": "success", "state": "removed"}

Errors

StatusMessage
400You can't remove yourself from the workspace.
400A workspace needs at least one owner. Make someone else an owner first.
403Only an owner can add, change or remove an owner.
404Member not found

Invitations

An invitation is an email with a single-use link, valid for 7 days. The invited person completes it with POST /auth/accept-invite. An email address can have a login in only one workspace.

Note: Invitation emails go through the operator's email backend. The default backend stores emails in an outbox table and sends nothing.

List invitations

GET /team/invites

Lists invitations that have not been accepted yet, oldest first.

Auth: API key or session token. Role: admin and up.

Request

bash
curl https://api.sevennadi.si/team/invites \
  -H "Authorization: Bearer vk-0123456789abcdef0123456789abcdef"

Response 200 OK

json
[
  {
    "id": "c1a5f6f0-3f8f-4f1e-8a51-2d1c9d7b6e02",
    "email": "ravi@example.test",
    "role": "member",
    "invited_at": "2026-10-13T08:00:00Z",
    "invited_by": "Asha Rao",
    "expires_at": "2026-10-20T08:00:00Z",
    "expired": false
  }
]

invited_by is null when the invitation was sent with an API key.

Invite a person

POST /team/invites

Creates a pending member and issues the invitation email.

Auth: API key or session token. Role: admin and up. Only an owner can invite an owner.

ParameterInTypeRequiredDescription
emailbodystringyesThe person's email address.
rolebodystringnoviewer, member, admin or owner. Default member.
Idempotency-KeyheaderstringnoMakes a retry safe: the same key with the same request returns the first response. See Idempotency.

Request

bash
curl -X POST https://api.sevennadi.si/team/invites \
  -H "Authorization: Bearer vk-0123456789abcdef0123456789abcdef" \
  -H "Content-Type: application/json" \
  -d '{"email": "ravi@example.test", "role": "member"}'

Response 201 Created

json
{
  "id": "c1a5f6f0-3f8f-4f1e-8a51-2d1c9d7b6e02",
  "email": "ravi@example.test",
  "role": "member",
  "invited_at": "2026-10-13T08:00:00Z",
  "invited_by": "Asha Rao",
  "expires_at": "2026-10-20T08:00:00Z",
  "expired": false
}

Rate limit: 30 invitations per workspace per hour.

Errors

StatusMessage
400A valid email is required
400role must be one of: owner, admin, member, viewer
403Only an owner can add, change or remove an owner.
409This person is already a member of the workspace
409This person already has a pending invitation. Resend it instead.
409This email address already has a login in another workspace
429Too many invitations in the last hour. Try again later.

Resend an invitation

POST /team/invites/{invite_id}/resend

Issues a fresh link for a pending invitation. The earlier link stops working.

Auth: API key or session token. Role: admin and up.

ParameterInTypeRequiredDescription
invite_idpathstring (UUID)yesThe invitation's id.

Request

bash
curl -X POST https://api.sevennadi.si/team/invites/c1a5f6f0-3f8f-4f1e-8a51-2d1c9d7b6e02/resend \
  -H "Authorization: Bearer vk-0123456789abcdef0123456789abcdef"

Response 200 OK

The invitation, with a new invited_at and expires_at, in the same shape as Invite a person.

Rate limit: 5 resends per invitation per hour.

Errors

StatusMessage
404Invitation not found
429This invitation was resent several times already. Try again in an hour.

Revoke an invitation

DELETE /team/invites/{invite_id}

Deletes a pending invitation. Its link stops working.

Auth: API key or session token. Role: admin and up.

ParameterInTypeRequiredDescription
invite_idpathstring (UUID)yesThe invitation's id.

Request

bash
curl -X DELETE https://api.sevennadi.si/team/invites/c1a5f6f0-3f8f-4f1e-8a51-2d1c9d7b6e02 \
  -H "Authorization: Bearer vk-0123456789abcdef0123456789abcdef"

Response 200 OK

json
{"message": "success", "state": "revoked"}

Errors

StatusMessage
404Invitation not found

Owner-only operations

Both operations need a logged-in owner and that owner's password. An API key acts as an admin, so it gets 403.

Transfer ownership

POST /team/transfer-ownership

Makes another member the owner. The caller becomes an admin.

Auth: session token only. Role: owner.

ParameterInTypeRequiredDescription
member_idbodystring (UUID)yesThe member who becomes the owner.
passwordbodystringyesThe caller's own password.

Request

bash
curl -X POST https://api.sevennadi.si/team/transfer-ownership \
  -H "Authorization: Bearer vs-0123456789abcdef0123456789abcdef" \
  -H "Content-Type: application/json" \
  -d '{"member_id": "7b1c2a90-5a51-4e0e-9c43-0f7f8f1f2a11", "password": "a-long-passphrase-42"}'

Response 200 OK

json
{
  "message": "success",
  "state": "transferred",
  "owner": {
    "id": "7b1c2a90-5a51-4e0e-9c43-0f7f8f1f2a11",
    "name": "Ravi Menon",
    "email": "ravi@example.test",
    "role": "owner",
    "status": "active",
    "email_verified": true,
    "two_factor_enabled": false,
    "joined_at": "2026-10-13T08:00:00Z",
    "last_active_at": null,
    "is_you": false
  }
}

Errors

StatusMessage
400You already own this workspace.
400This member's login is disabled.
400Current password is incorrect
403Your role (admin) can't transfer ownership of the workspace. It needs owner access; ask an owner of the workspace.
404Member not found
429Too many incorrect passwords. Try again in 15 minutes.

Delete the workspace

DELETE /team/workspace

Closes the workspace. Every login, session and API key stops working at once. The data is kept (the workspace is marked deleted, not erased).

Auth: session token only. Role: owner.

ParameterInTypeRequiredDescription
confirmbodystringyesThe workspace's exact name.
passwordbodystringyesThe owner's own password.

Request

bash
curl -X DELETE https://api.sevennadi.si/team/workspace \
  -H "Authorization: Bearer vs-0123456789abcdef0123456789abcdef" \
  -H "Content-Type: application/json" \
  -d '{"confirm": "Example Bank", "password": "a-long-passphrase-42"}'

Response 200 OK

json
{"message": "success", "state": "deleted"}

Warning: There is no endpoint to reopen a closed workspace.

Errors

StatusMessage
400The confirm value is not the workspace's name (message below).
400Current password is incorrect
403Your role (admin) can't delete the workspace. It needs owner access; ask an owner of the workspace.
429Too many incorrect passwords. Try again in 15 minutes.
text
Type the workspace's name in `confirm` to delete it.

Audit and permissions

Read the audit log

GET /team/audit

Returns the workspace's security events, newest first: sign-ups, logins and failed logins, password and two-factor changes, session revocations, API key creation and revocation, invitations, role changes, ownership transfers.

Auth: API key or session token. Role: admin and up.

ParameterInTypeRequiredDescription
page_numberqueryintegernoFrom 1. Default 1.
page_sizequeryintegerno1 to 100. Default 50.
eventquerystringnoOnly this event, for example login_failed.

Event names used by the server: signup, login, login_failed, logout, email_verified, password_reset_requested, password_reset, password_changed, 2fa_enabled, 2fa_disabled, session_revoked, sessions_revoked, api_key_created, api_key_revoked, invite_sent, invite_resent, invite_revoked, invite_accepted, role_changed, member_disabled, member_enabled, member_removed, ownership_transferred, workspace_deleted.

Request

bash
curl "https://api.sevennadi.si/team/audit?event=login_failed&page_size=20" \
  -H "Authorization: Bearer vk-0123456789abcdef0123456789abcdef"

Response 200 OK

json
{
  "page_number": 1,
  "page_size": 20,
  "total": 1,
  "has_more": false,
  "data": [
    {
      "id": 271,
      "event": "login_failed",
      "actor": "asha@example.test",
      "member_id": "0144c9aa-d4fe-4341-99fd-aa27689ab6a0",
      "detail": {"reason": "wrong password"},
      "ip": "203.0.113.7",
      "user_agent": "Mozilla/5.0",
      "created_at": "2026-10-13T07:21:47Z"
    }
  ]
}

For an action done with an API key, actor is API key followed by the key's prefix and member_id is null.

Errors

StatusMessage
400A validation message when page_number or page_size is out of range.
403Your role (member) can't do this. It needs admin access; ask an owner or admin of the workspace.

Get the permission table

GET /team/permissions

Returns the rule table the server checks for every authenticated request. Rules are read top to bottom and the first one that matches the method and path decides the minimum role. A path covers everything below it; a path containing * is a pattern.

Auth: API key or session token. Role: viewer and up.

Request

bash
curl https://api.sevennadi.si/team/permissions \
  -H "Authorization: Bearer vk-0123456789abcdef0123456789abcdef"

Response 200 OK (rules shortened)

json
{
  "roles": ["viewer", "member", "admin", "owner"],
  "your_role": "admin",
  "rank": {"viewer": 0, "member": 1, "admin": 2, "owner": 3},
  "rules": [
    {"methods": ["*"], "path": "/team/transfer-ownership", "role": "owner", "area": "transfer ownership"},
    {"methods": ["POST", "PUT", "PATCH", "DELETE"], "path": "/billing", "role": "owner", "area": "billing"},
    {"methods": ["*"], "path": "/auth/api-keys", "role": "admin", "area": "API keys"},
    {"methods": ["GET", "HEAD", "OPTIONS"], "path": "/", "role": "viewer", "area": "reading"},
    {"methods": ["*"], "path": "/", "role": "member", "area": "agents, knowledge bases, batches, campaigns and calls"}
  ]
}

The last two rules are the defaults: reading needs viewer, changing anything needs member.