NoteBugsDocs

API reference

Users

The installation's account catalogue. An admin prefix.

ADMIN in every method, reading included: the list of accounts and roles is not visible to members.

GET/api/users
Role: Admin

The installation's accounts, with each one's role and workspaces.

Request

curl -s http://localhost:3000/api/users \
  -H "Authorization: Bearer $TOKEN"

Response200

[
  {
    "id": "cmt94cjx5000vql01imegem2r",
    "name": "Ana",
    "email": "[email protected]",
    "role": "MEMBER",
    "avatarUrl": null,
    "jobTitle": "Product Owner",
    "timezone": "America/Sao_Paulo",
    "notifyBackupReady": true,
    "hasApiToken": false,
    "apiTokenCreatedAt": null,
    "apiTokenLast4": null,
    "passwordPending": false,
    "lastLoginAt": "2026-08-27T19:50:42.947Z",
    "createdAt": "2026-08-25T20:29:57.593Z",
    "tenants": [
      {
        "id": "cmsp4djx60002p801o7ybpkv7",
        "name": "Pessoal",
        "color": "amber",
        "role": "MEMBER",
        "membership": "MEMBER"
      }
    ]
  }
]

Error responses

CodeWhen it happens
401No credential, or one that no longer holds. Send the session cookie or the Authorization: Bearer header.
403The account is not an admin. This prefix requires ADMIN in every method, reading included.
POST/api/users
Role: Admin

Creates an account, optionally with its workspaces already set.

Request body

FieldTypeDescription
namerequiredstring
emailrequiredstring
passwordrequiredstringThe initial password. There is no e-mail delivery in this installation, so arrange it out of band.
rolerequiredenumRole in the INSTALLATION. It decides the routes that belong to no workspace.ADMIN · MEMBER · VIEWER
jobTitlestring | null
tenants{ tenantId, role }[]Pairs of { tenantId, role }. The in-workspace role only takes MEMBER or VIEWER.

Request

curl -s -X POST http://localhost:3000/api/users \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Bruno",
    "email": "[email protected]",
    "password": "uma senha longa",
    "role": "MEMBER",
    "tenants": [
      { "tenantId": "cmsp4djx60002p801o7ybpkv7", "role": "MEMBER" }
    ]
  }'

Response201

{
  "id": "cmt94cjx5000vql01imegem2r",
  "name": "Ana",
  "email": "[email protected]",
  "role": "MEMBER",
  "avatarUrl": null,
  "jobTitle": "Product Owner",
  "timezone": "America/Sao_Paulo",
  "notifyBackupReady": true,
  "hasApiToken": false,
  "apiTokenCreatedAt": null,
  "apiTokenLast4": null,
  "passwordPending": false,
  "lastLoginAt": "2026-08-27T19:50:42.947Z",
  "createdAt": "2026-08-25T20:29:57.593Z",
  "tenants": [
    {
      "id": "cmsp4djx60002p801o7ybpkv7",
      "name": "Pessoal",
      "color": "amber",
      "role": "MEMBER",
      "membership": "MEMBER"
    }
  ]
}

Error responses

CodeWhen it happens
401No credential, or one that no longer holds. Send the session cookie or the Authorization: Bearer header.
403The account is not an admin. This prefix requires ADMIN in every method, reading included.
409Another account already uses that e-mail.
422The body did not pass the schema. The details field carries zod's fieldErrors and formErrors, field by field.

The narrowest of the two axes wins: a VIEWER of the installation writes nowhere, even as a MEMBER of a workspace.

PATCH/api/users/[id]
Role: Admin

Edits another account: name, e-mail, role and the password reset.

Path parameters

FieldTypeDescription
idrequiredcuid

Request body

FieldTypeDescription
namestring
emailstring
roleenumADMIN · MEMBER · VIEWER
passwordstringThe RESET performed by an admin. It does not ask for the current password: this is the installation's recovery path.
jobTitlestring | null

Request

curl -s -X PATCH http://localhost:3000/api/users/cmt94cjx5000vql01imegem2r \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "role": "VIEWER" }'

Response200

{
  "id": "cmt94cjx5000vql01imegem2r",
  "name": "Ana",
  "email": "[email protected]",
  "role": "VIEWER",
  "avatarUrl": null,
  "jobTitle": "Product Owner",
  "timezone": "America/Sao_Paulo",
  "notifyBackupReady": true,
  "hasApiToken": false,
  "apiTokenCreatedAt": null,
  "apiTokenLast4": null,
  "passwordPending": false,
  "lastLoginAt": "2026-08-27T19:50:42.947Z",
  "createdAt": "2026-08-25T20:29:57.593Z",
  "tenants": [
    {
      "id": "cmsp4djx60002p801o7ybpkv7",
      "name": "Pessoal",
      "color": "amber",
      "role": "MEMBER",
      "membership": "MEMBER"
    }
  ]
}

Error responses

CodeWhen it happens
401No credential, or one that no longer holds. Send the session cookie or the Authorization: Bearer header.
403The account is not an admin. This prefix requires ADMIN in every method, reading included.
404The resource does not exist, or has already been deleted.
409Another account already uses that e-mail.
422One admin always remains: the installation never ends up with nobody able to restore access.

The reset performed here drops ALL of that person's sessions: no older access stays valid.

DELETE/api/users/[id]
Role: Admin

Removes an account.

Path parameters

FieldTypeDescription
idrequiredcuid

Request

curl -s -X DELETE http://localhost:3000/api/users/cmt94cjx5000vql01imegem2r \
  -H "Authorization: Bearer $TOKEN"

Response200

{ "deleted": true }

Error responses

CodeWhen it happens
401No credential, or one that no longer holds. Send the session cookie or the Authorization: Bearer header.
403The account is not an admin. This prefix requires ADMIN in every method, reading included.
404The resource does not exist, or has already been deleted.
422One admin always remains: the installation never ends up with nobody able to restore access.

The last admin cannot be removed: the installation cannot end up with nobody able to restore access.

PUT/api/users/[id]/tenants
Role: Admin

Sets a person's workspaces: the FINAL list.

It is PUT and not PATCH because the body is the whole set, like tagIds on a card form: whatever is not in the list stops being reachable.

Path parameters

FieldTypeDescription
idrequiredcuid

Request body

FieldTypeDescription
tenantsrequired{ tenantId, role }[]A workspace outside this list stops being reachable; a new one enters with the given role.

Request

curl -s -X PUT http://localhost:3000/api/users/cmt94cjx5000vql01imegem2r/tenants \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "tenants": [
      { "tenantId": "cmsp4djx60002p801o7ybpkv7", "role": "MEMBER" },
      { "tenantId": "tenant-pessoal", "role": "VIEWER" }
    ]
  }'

Response200

{
  "id": "cmt94cjx5000vql01imegem2r",
  "name": "Ana",
  "email": "[email protected]",
  "role": "MEMBER",
  "avatarUrl": null,
  "jobTitle": "Product Owner",
  "timezone": "America/Sao_Paulo",
  "notifyBackupReady": true,
  "hasApiToken": false,
  "apiTokenCreatedAt": null,
  "apiTokenLast4": null,
  "passwordPending": false,
  "lastLoginAt": "2026-08-27T19:50:42.947Z",
  "createdAt": "2026-08-25T20:29:57.593Z",
  "tenants": [
    {
      "id": "cmsp4djx60002p801o7ybpkv7",
      "name": "Pessoal",
      "color": "amber",
      "role": "MEMBER",
      "membership": "MEMBER"
    }
  ]
}

Error responses

CodeWhen it happens
401No credential, or one that no longer holds. Send the session cookie or the Authorization: Bearer header.
403The account is not an admin. This prefix requires ADMIN in every method, reading included.
404The resource does not exist, or has already been deleted.
422The body did not pass the schema. The details field carries zod's fieldErrors and formErrors, field by field.