Skip to content

Users API

The Users API manages user accounts, authentication, and identity on the Canvus server. Use it to sign users in and out, create and manage accounts, handle password resets, and perform administrative operations like blocking or approving users.

Authentication overview:

  • Most endpoints require a Private-Token header or an active session cookie
  • Authentication endpoints (login, register, password reset) do not require authentication
  • Admin-only endpoints are noted per section

Related APIs:

Current behavior

  • When a non-administrator makes a change they are not allowed to make through update, delete, block, unblock or approve, the server returns 401 Unauthorized rather than 403 Forbidden.
  • Update, delete, block, unblock and approve on a user ID that does not exist return 400 Bad Request rather than 404.
  • Change email with an address already in use returns 500 Internal Server Error rather than 409 Conflict.
  • Confirm email with an invalid token returns 403 Forbidden, and validating or using an invalid password-reset token returns 404 Not Found, rather than 400.
  • An invalid or expired token returns 403 Forbidden, not 401. See Current behavior.

These are being corrected.


User object

Every user-related endpoint that returns user data uses the same JSON structure.

Note: User IDs (and group IDs) are integers, unlike most other API resources which use UUIDs.

Fields:

  • id (integer) -- unique user identifier
  • name (string) -- display name
  • email (string) -- email address, also used as the login name
  • admin (boolean) -- whether the user has administrator privileges
  • approved (boolean) -- whether the user account has been approved
  • blocked (boolean) -- whether the user account is blocked from signing in
  • state (string) -- account state (e.g., "normal")
  • created_at (string) -- ISO 8601 timestamp of account creation
  • last_login (string) -- ISO 8601 timestamp of last sign-in, or empty string if never signed in

Example:

{
  "id": 1002,
  "name": "Alice Chen",
  "email": "alice@example.com",
  "admin": false,
  "approved": true,
  "blocked": false,
  "state": "normal",
  "created_at": "2025-03-15T09:22:41.817Z",
  "last_login": "2025-03-28T14:05:12.003Z"
}

Sign in

Signs the user in with email and password, returning a session token.

POST /api/v1/users/login

Authentication: None required.

Streaming: Not supported.

Request body (JSON):

  • email (string, required) -- the user's email address
  • password (string, required) -- the user's password
  • remember (boolean, optional) -- if true, extends the session lifetime

Send only these fields. A body with any other field, for example username, is rejected with 400 Bad Request and the message "Login request must have either email and password or token".

curl -X POST \
  -H "Content-Type: application/json" \
  -d '{"email":"alice@example.com","password":"s3cureP@ss"}' \
  https://canvus.example.com/api/v1/users/login

Response (200 OK):

{
  "token": "EXAMPLE_SESSION_TOKEN_REPLACE_WITH_YOUR_OWN",
  "user": {
    "id": 1002,
    "name": "Alice Chen",
    "email": "alice@example.com",
    "admin": false,
    "approved": true,
    "blocked": false,
    "state": "normal",
    "created_at": "2025-03-15T09:22:41.817Z",
    "last_login": "2025-03-28T14:05:12.003Z"
  }
}

Use the returned token value in subsequent requests as the Private-Token header.

Token validation mode: You can also POST an existing token to validate it and get a new one. If the token is valid, the server returns a new session token with a fresh lifetime. The token you sent is not extended; it stays valid until its own expiry.

  • token (string, required) -- an existing access token to validate
curl -X POST \
  -H "Content-Type: application/json" \
  -d '{"token":"EXAMPLE_SESSION_TOKEN_REPLACE_WITH_YOUR_OWN"}' \
  https://canvus.example.com/api/v1/users/login

Error responses:

  • 401 Unauthorized -- invalid email/password or invalid token, or the account is blocked or not yet approved

Current behavior

In token validation mode, an invalid or expired token currently returns 500 Internal Server Error rather than 401. This is being corrected.


SAML 2.0 sign in

Validates a SAML 2.0 assertion and signs the user in. The server must have SAML authentication enabled in server settings.

POST /api/v1/users/login/saml

Authentication: None required.

Streaming: Not supported.

Request body (JSON):

  • inResponseTo (string, required) -- the request ID known to the SAML initiator (correlates response to request)
  • responseXml (string, required) -- the full SAML response XML
  • remember (boolean, optional) -- if true, extends the session lifetime
curl -X POST \
  -H "Content-Type: application/json" \
  -d '{"inResponseTo":"_abc123","responseXml":"<samlp:Response>...</samlp:Response>","remember":true}' \
  https://canvus.example.com/api/v1/users/login/saml

Response (200 OK): Same token + user object as the standard sign-in endpoint.

Error responses:

  • 400 Bad Request -- invalid or malformed SAML assertion, or the assertion failed validation
  • 403 Forbidden -- SAML sign-in is disabled in server settings

Sign out

Invalidates a session token, signing the user out.

POST /api/v1/users/logout

Authentication: Required.

Streaming: Not supported.

Request body (JSON, optional):

  • token (string, optional) -- specific token to invalidate. If omitted, the token from the Private-Token header is invalidated.
curl -X POST \
  -H "Private-Token: EXAMPLE_SESSION_TOKEN_REPLACE_WITH_YOUR_OWN" \
  https://canvus.example.com/api/v1/users/logout

Response (200 OK): Empty body on success.


List users

Returns all user accounts on the server, including the built-in Guest account. Accounts that are still waiting for email confirmation are not included.

GET /api/v1/users

Authentication: Required.

Streaming: Supports ?subscribe for live updates.

Query parameters:

  • subscribe (flag, optional) -- when present, keeps the connection open and streams updates as newline-delimited JSON. The parameter takes no value; its presence alone turns streaming on, so ?subscribe=false also streams.
curl -H "Private-Token: YOUR_TOKEN" \
  https://canvus.example.com/api/v1/users

Response (200 OK):

[
  {
    "id": 100,
    "name": "Guest",
    "email": "",
    "admin": false,
    "approved": true,
    "blocked": false,
    "state": "normal",
    "created_at": "2025-03-15T09:20:18.817Z",
    "last_login": "2025-03-15T09:21:48.569Z"
  },
  {
    "id": 1000,
    "name": "Admin",
    "email": "admin@example.com",
    "admin": true,
    "approved": true,
    "blocked": false,
    "state": "normal",
    "created_at": "2025-03-15T09:20:33.392Z",
    "last_login": "2025-03-28T14:05:12.003Z"
  },
  {
    "id": 1002,
    "name": "Alice Chen",
    "email": "alice@example.com",
    "admin": false,
    "approved": true,
    "blocked": false,
    "state": "normal",
    "created_at": "2025-03-15T09:22:41.817Z",
    "last_login": ""
  }
]

Get single user

Returns details for a specific user.

GET /api/v1/users/:user_id

Authentication: Required.

Streaming: Supports ?subscribe for live updates.

Path parameters:

  • user-id (integer, required) -- the ID of the user
curl -H "Private-Token: YOUR_TOKEN" \
  https://canvus.example.com/api/v1/users/1002

Response (200 OK):

{
  "id": 1002,
  "name": "Alice Chen",
  "email": "alice@example.com",
  "admin": false,
  "approved": true,
  "blocked": false,
  "state": "normal",
  "created_at": "2025-03-15T09:22:41.817Z",
  "last_login": ""
}

Error responses:

  • 404 Not Found -- no user with the given ID exists

Create user

Creates a new user account. If no password is provided, the server sends a password reset email to the new user.

POST /api/v1/users

Authentication: Admin required.

Streaming: Not supported.

Request body (JSON):

  • email (string, required) -- email address, used as the login name. Must be unique across all users.
  • name (string, required) -- display name
  • password (string, optional) -- initial password. If omitted, a password reset email is sent.
  • admin (boolean, optional) -- grant administrator privileges. Default: false.
  • approved (boolean, optional) -- mark the account as approved. Default: true.
  • blocked (boolean, optional) -- create the account in blocked state. Default: false.
curl -X POST \
  -H "Private-Token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"email":"bob.martinez@example.com","name":"Bob Martinez","password":"b0bSecure!"}' \
  https://canvus.example.com/api/v1/users

Response (200 OK):

{
  "id": 1003,
  "name": "Bob Martinez",
  "email": "bob.martinez@example.com",
  "admin": false,
  "approved": true,
  "blocked": false,
  "state": "normal",
  "created_at": "2025-03-28T15:10:22.501Z",
  "last_login": ""
}

Error responses:

  • 400 Bad Request -- missing required fields, invalid email format, or a user with this email already exists
  • 403 Forbidden -- caller is not an administrator

Update user

Changes user profile data. Regular users can update their own name and blocked fields. Administrators can change all fields of any user.

PATCH /api/v1/users/:user_id

Authentication: Required. Admin required for other users' profiles or admin-only fields.

Streaming: Not supported.

Path parameters:

  • user-id (integer, required) -- the ID of the user to update

Request body (JSON) -- all fields optional, include only those being changed:

  • name (string) -- display name
  • email (string) -- email address. Must be unique. Admin-only; regular users change their own address through Change email.
  • password (string) -- new password. Admin-only.
  • admin (boolean) -- grant or revoke admin privileges. Admin-only.
  • approved (boolean) -- approve the user (can only change from false to true). Admin-only.
  • blocked (boolean) -- block or unblock the user
  • need_email_confirmation (boolean) -- confirm email on behalf of user. Only false is accepted, which confirms a pending account; true is rejected. Admin-only.
curl -X PATCH \
  -H "Private-Token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Alice Chen-Williams"}' \
  https://canvus.example.com/api/v1/users/1002

Response (200 OK):

{
  "id": 1002,
  "name": "Alice Chen-Williams",
  "email": "alice@example.com",
  "admin": false,
  "approved": true,
  "blocked": false,
  "state": "normal",
  "created_at": "2025-03-15T09:22:41.817Z",
  "last_login": "2025-03-28T14:05:12.003Z"
}

Error responses:

  • 400 Bad Request -- email already in use by another user
  • 403 Forbidden -- insufficient permissions for the requested change
  • 404 Not Found -- no user with the given ID exists

Delete user

Permanently deletes a user account.

DELETE /api/v1/users/:user_id

Authentication: Admin required.

Streaming: Not supported.

Path parameters:

  • user-id (integer, required) -- the ID of the user to delete
curl -X DELETE \
  -H "Private-Token: YOUR_TOKEN" \
  https://canvus.example.com/api/v1/users/1003

Response (200 OK): Empty body on success.

Error responses:

  • 403 Forbidden -- caller is not an administrator
  • 404 Not Found -- no user with the given ID exists

Change password

Allows a user to change their own password by providing the current password. To set another user's password, administrators use the password field of Update user.

POST /api/v1/users/:user_id/password

Authentication: Required.

Streaming: Not supported.

Path parameters:

  • user-id (integer, required) -- the ID of the user

Request body (JSON):

  • current_password (string, required) -- the user's current password
  • new_password (string, required) -- the desired new password
curl -X POST \
  -H "Private-Token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"current_password":"s3cureP@ss","new_password":"n3wS3cure!"}' \
  https://canvus.example.com/api/v1/users/1002/password

Response (200 OK): Returns the updated user object.

{
  "id": 1002,
  "name": "Alice Chen",
  "email": "alice@example.com",
  "admin": false,
  "approved": true,
  "blocked": false,
  "state": "normal",
  "created_at": "2025-03-15T09:22:41.817Z",
  "last_login": "2025-03-28T14:05:12.003Z"
}

Error responses:

  • 401 Unauthorized -- current password is incorrect
  • 403 Forbidden -- non-admin trying to change another user's password

Change email

Initiates an email change for a user. The server sends a confirmation link to the new email address.

POST /api/v1/users/:user_id/change-email

Authentication: Required.

Streaming: Not supported.

Path parameters:

  • user-id (integer, required) -- the ID of the user

Request body (JSON):

  • new_email (string, required) -- the new email address
curl -X POST \
  -H "Private-Token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"new_email":"alice.new@example.com"}' \
  https://canvus.example.com/api/v1/users/1002/change-email

Error responses:

  • 400 Bad Request -- invalid email format
  • 409 Conflict -- email already in use by another user

Confirm email

Confirms a user's email address using a token received via email. This completes the email change or registration process.

POST /api/v1/users/confirm-email

Authentication: None required.

Streaming: Not supported.

Request body (JSON):

  • token (string, required) -- the confirmation token from the email
curl -X POST \
  -H "Content-Type: application/json" \
  -d '{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}' \
  https://canvus.example.com/api/v1/users/confirm-email

Response (200 OK): Empty body on success.

Error responses:

  • 400 Bad Request -- {"msg": "Invalid email confirmation token."} -- token is expired, malformed, or already used

Request password reset

Sends a password reset email to the specified address. If the email matches an existing account, the user receives a reset token.

For security, this endpoint returns success even if no matching account exists.

POST /api/v1/users/password/create-reset-token

Authentication: None required.

Streaming: Not supported.

Request body (JSON):

  • email (string, required) -- the email address of the account to reset
curl -X POST \
  -H "Content-Type: application/json" \
  -d '{"email":"alice@example.com"}' \
  https://canvus.example.com/api/v1/users/password/create-reset-token

Response (200 OK): Empty body on success.


Validate password reset token

Checks whether a password reset token is still valid without consuming it. Use this to verify a token before showing the password reset form.

GET /api/v1/users/password/validate-reset-token

Authentication: None required.

Streaming: Not supported.

Query parameters:

  • token (string, required) -- the reset token from the email
curl "https://canvus.example.com/api/v1/users/password/validate-reset-token?token=eyJhbGciOiJIUzI1NiJ9..."

Response (200 OK): Empty body if the token is valid.

Error responses:

  • 400 Bad Request -- {"msg": "Invalid token"} -- token is expired, malformed, or already consumed

Reset password

Sets a new password using a reset token from the password reset email.

POST /api/v1/users/password/reset

Authentication: None required.

Streaming: Not supported.

Request body (JSON):

  • token (string, required) -- the reset token from the email
  • password (string, required) -- the new password
curl -X POST \
  -H "Content-Type: application/json" \
  -d '{"token":"eyJhbGciOiJIUzI1NiJ9...","password":"myN3wP@ssword!"}' \
  https://canvus.example.com/api/v1/users/password/reset

Response (200 OK): Empty body on success.

Error responses:

  • 400 Bad Request -- {"msg": "Invalid token"} -- token is expired, malformed, or already consumed

Register user (self-registration)

Allows a new user to create their own account. Self-registration must be enabled in the server settings.

On success, the server sends a confirmation email. The account is not active until the email is confirmed via the Confirm Email endpoint.

POST /api/v1/users/register

Authentication: None required.

Streaming: Not supported.

Request body (JSON):

  • email (string, required) -- email address, used as the login name. Must be unique.
  • name (string, required) -- display name
  • password (string, required) -- password for the new account
  • admin (boolean, optional) -- only administrators can set this to true; a request from anyone else that sets it to true is rejected. Default: false.
  • approved (boolean, optional) -- when the server requires admin approval, a non-admin request that sets this to true is rejected. Default depends on server settings.
  • blocked (boolean, optional) -- default: false
curl -X POST \
  -H "Content-Type: application/json" \
  -d '{"email":"carol.nguyen@example.com","name":"Carol Nguyen","password":"c@r0lSecure"}' \
  https://canvus.example.com/api/v1/users/register

Response (200 OK): Returns the new user object.

Error responses:

  • 400 Bad Request -- missing required fields, or a user with this email already exists
  • 403 Forbidden -- {"msg": "Sign-up using a password is not enabled"} -- self-registration is disabled in server settings

Block user

Blocks a user account, preventing them from signing in. All active sessions are revoked.

Regular users can block their own account. Administrators can block any user.

POST /api/v1/users/:user_id/block

Authentication: Required.

Streaming: Not supported.

Path parameters:

  • user-id (integer, required) -- the ID of the user to block
curl -X POST \
  -H "Private-Token: YOUR_TOKEN" \
  https://canvus.example.com/api/v1/users/1002/block

Response (200 OK):

{
  "id": 1002,
  "name": "Alice Chen",
  "email": "alice@example.com",
  "admin": false,
  "approved": true,
  "blocked": true,
  "state": "normal",
  "created_at": "2025-03-15T09:22:41.817Z",
  "last_login": "2025-03-28T14:05:12.003Z"
}

Error responses:

  • 403 Forbidden -- non-admin trying to block another user
  • 404 Not Found -- no user with the given ID exists

Unblock user

Unblocks a previously blocked user account, allowing them to sign in again.

POST /api/v1/users/:user_id/unblock

Authentication: Admin required.

Streaming: Not supported.

Path parameters:

  • user-id (integer, required) -- the ID of the user to unblock
curl -X POST \
  -H "Private-Token: YOUR_TOKEN" \
  https://canvus.example.com/api/v1/users/1002/unblock

Response (200 OK):

{
  "id": 1002,
  "name": "Alice Chen",
  "email": "alice@example.com",
  "admin": false,
  "approved": true,
  "blocked": false,
  "state": "normal",
  "created_at": "2025-03-15T09:22:41.817Z",
  "last_login": "2025-03-28T14:05:12.003Z"
}

Error responses:

  • 403 Forbidden -- caller is not an administrator
  • 404 Not Found -- no user with the given ID exists

Approve user

Approves a user account that is pending approval (e.g., after self-registration when admin approval is required).

POST /api/v1/users/:user_id/approve

Authentication: Admin required.

Streaming: Not supported.

Path parameters:

  • user-id (integer, required) -- the ID of the user to approve
curl -X POST \
  -H "Private-Token: YOUR_TOKEN" \
  https://canvus.example.com/api/v1/users/1002/approve

Response (200 OK):

{
  "id": 1002,
  "name": "Alice Chen",
  "email": "alice@example.com",
  "admin": false,
  "approved": true,
  "blocked": false,
  "state": "normal",
  "created_at": "2025-03-15T09:22:41.817Z",
  "last_login": ""
}

Error responses:

  • 403 Forbidden -- caller is not an administrator
  • 404 Not Found -- no user with the given ID exists

Force password reset

Forces a password reset for a user. The user's password is cleared and all of their active sessions are revoked, so they cannot sign in until they set a new password. The server emails them a password reset link automatically, unless the account is blocked.

POST /api/v1/users/:user_id/reset-password

Authentication: Admin required.

Streaming: Not supported.

Path parameters:

  • user-id (integer, required) -- the ID of the user
curl -X POST \
  -H "Private-Token: YOUR_TOKEN" \
  https://canvus.example.com/api/v1/users/1002/reset-password

Response (200 OK):

  • user (object) -- the updated user object
  • removed_login_token_count (integer) -- number of session tokens revoked
  • remaining_login_token_count (integer) -- number of session tokens still valid
  • remaining_access_token_count (integer) -- number of the user's access tokens
  • token_delete_error (string) -- present only if revoking the sessions failed
  • email_send_error (string) -- present only if the reset email was not sent, for example because the account is blocked

Error responses:

  • 403 Forbidden -- caller is not an administrator
  • 404 Not Found -- no user with the given ID exists