Skip to main content
API Reference

Users API

REST endpoints to list, retrieve, create, update, and delete users in octoja.

Users API

The Users API lets you query and manage user records. All endpoints require a valid access token in the Authorization: Bearer <token> header — see API Authentication for how to obtain one.

For the complete, always-current list of endpoints, parameters, and response fields for the version you are running, use the interactive OpenAPI (Swagger) interface at https://<your-octoja-instance>/openapi/index.html. This article keeps only the permissions, behaviors, and validation rules that the schema cannot express.

Endpoints

OperationEndpointNotes
List usersGET /api/usersOptional search filters by email address, first name, or last name.
Get a userGET /api/users/{id}Returns a single User object.
Get the current userGET /api/users/meSession-scoped view of the caller. Response shape differs — see below.
Create a userPOST /api/usersRequires users.manage. See Creating a user.
Update a userPOST /api/users/{id}Requires users.manage. See Updating a user.
Delete a userDELETE /api/users/{id}Requires users.manage. Subject to the groups.manage safety guard — see Deleting a user.
Invite a userPOST /api/user-invitationsRequires users.manage. Adding groupIds also requires groups.manage. See Inviting a user.
List invitationsGET /api/user-invitationsRequires users.manage. Each entry carries a status of Pending, Expired, Accepted, or Revoked.
Get an invitation linkGET /api/user-invitations/{id}/linkRequires users.manage. Returns the invite URL so you can pass it on yourself.
Resend an invitationPOST /api/user-invitations/{id}/resendRequires users.manage. Sends the email again and restarts the expiry. Returns 204 No Content.
Revoke an invitationDELETE /api/user-invitations/{id}Requires users.manage. Returns 204 No Content.
Preview an invitationGET /api/user-invitations/by-token/{token}No authentication — this is what the invite page calls to show who the invitation is for.
Accept an invitationPOST /api/user-invitations/acceptNo authentication. Creates the account from the invitation. See Inviting a user.
Update your own profilePOST /api/users/meAny authenticated user; no users.manage required.
Change your own passwordPOST /api/users/me/change-passwordAny authenticated user. Plain fields, not the UpdateValue envelope.
Remove your own passwordDELETE /api/users/me/passwordAny authenticated user. Makes the account SSO-only. See Remove your own password.
Update your preferencesPOST /api/users/me/preferencesAny authenticated user. Updates the preferences object from GET /api/users/me.

Get the current user

GET /api/users/me returns a session-scoped view of the authenticated caller whose shape differs from the regular User object: the email field is named email (not mailAddress), the full groups objects are returned with their resolved permissions (not only groupIds), and an additional preferences field is included. Field-by-field details are in Swagger.

Creating a user

Requires the users.manage permission. Required: mailAddress (the login email address, which must be unique) and lastname. firstname and password are optional; the full field list is in Swagger.

If you create a user without a password, that user has no local password login and needs a linked OIDC / SSO login before they can sign in. A common example is Microsoft SSO. For Microsoft SSO, the first sign-in may require a Microsoft administrator in the Microsoft tenant to grant consent for octoja.

POST /api/users creates the account directly and assigns no groups. To let someone choose their own password, start out in the right groups, and link an SSO login as part of sign-up, send an invitation instead — see Inviting a user.

Updating a user

POST /api/users/{id}

Requires the users.manage permission. Send only the fields you want to change. Each field is wrapped in an UpdateValue<T> envelope of the shape { "hasValue": true, "value": <T> }; omit the field entirely to leave it untouched. Sending a bare value (for example "newFirstname": "Max") is rejected as a deserialization error. The full updatable-field list is in Swagger; the fields below carry behavior worth knowing:

{
  "newFirstname": { "hasValue": true, "value": "Max" },
  "newPassword": { "hasValue": true, "value": null }
}
  • newMailAddress — new login email address; must be unique.
  • newPassword — a value of null removes the local password login, making the account SSO-only unless a new password is set later.
  • newFirstname / newLastname — a value of null clears the name.
  • newMobileNumber — the number SMS and call notifications go to. An empty or whitespace-only value clears it.
  • newRemoteSupportDisplayName — the name shown on the customer's device during a remote support session. An empty or whitespace-only value clears it; the name from the technician name template is shown instead, or the user's own name if no template is set.
  • newTotpSecret — a value of null disables TOTP.
  • oidcProvidersToUnlink — OIDC providers to unlink, for example ["Microsoft"].

Group membership is not part of this request. A user's groups are assigned through POST /api/groups/{id} with newMemberUserIds, which requires the groups.manage permission — see Groups API.

Validation rules

  • newMailAddress with an empty or whitespace-only value, or one already used by another user, returns 400 Bad Request.
  • newPassword with an empty or whitespace-only value returns 400 Bad Request — use null to remove the password.

Deleting a user

Requires the users.manage permission. A safety guard applies: deleting a user is rejected if it would leave no remaining member of a group with the groups.manage permission.

Inviting a user

POST /api/user-invitations

Requires the users.manage permission. An invitation records who is being onboarded and emails them a link; the account itself is created when they accept. Required: mailAddress and lastname. firstname is optional. groupIds sets the groups the new account joins on acceptance and additionally requires the groups.manage permission — without it the request returns 403 Forbidden. The response carries the invitation id and the invite URL, so you can pass the link on through another channel as well.

The recipient has two ways to accept: set a password through POST /api/user-invitations/accept (minimum 8 characters), or sign in with an OIDC provider, which links that provider to the new account. Either way, any group that was deleted between invitation and acceptance is dropped from the assignment.

Validation rules

  • An empty or whitespace-only mailAddress returns 400 Bad Request.
  • An address that already belongs to a user, or that already has a pending invitation, returns 400 Bad Request.
  • groupIds containing an unknown group ID returns 400 Bad Request.
  • Invitations expire 7 days after they are sent. POST /api/user-invitations/{id}/resend emails the link again and restarts those 7 days; calling it within 60 seconds of the last send returns 429 Too Many Requests.
  • POST /api/user-invitations/accept returns 404 Not Found for an unknown or already-accepted token, 410 Gone for an expired one, 400 Bad Request for a password shorter than 8 characters, and 409 Conflict if a user with that address was created in the meantime.

GET /api/user-invitations lists every invitation, newest first, including the ones already accepted or revoked. Read the status field to tell them apart.

Update your own profile

POST /api/users/me is available to every authenticated user — no users.manage permission required. Fields use the same UpdateValue<T> envelope as "Updating a user" and the endpoint returns the updated user. Behaviors worth knowing:

  • newFirstname — a value of null or an empty string clears it.
  • newLastname — an empty or whitespace-only value is rejected with 400 Bad Request.
  • newMobileNumber — the number your SMS and call notifications go to. An empty or whitespace-only value clears it.
  • newTotpSecret — a value of null disables TOTP.
  • oidcProvidersToUnlink — unlink your own OIDC sign-ins, for example ["Microsoft"]. Rejected with 400 Bad Request if it would leave you with no way to sign in (no local password and no remaining linked login).

Change your own password

POST /api/users/me/change-password

Available to every authenticated user. This endpoint uses plain fields (currentPassword, newPassword), not the UpdateValue envelope. It returns 400 Bad Request if either field is empty, if the account has no local password set, or if currentPassword is incorrect. On success the response is 204 No Content.

Remove your own password

DELETE /api/users/me/password

Available to every authenticated user. This removes your local password so the account signs in through SSO only. It returns 400 Bad Request if no password is set, or if the account has no linked OIDC login — octoja always keeps at least one sign-in method, so the password stays in place until another login is linked. On success the response is 204 No Content.

Update your preferences

POST /api/users/me/preferences is available to every authenticated user and updates the preferences object returned by GET /api/users/me. It returns the updated preferences object. Behaviors worth knowing:

  • toggleFavoriteAssetId — toggles the device in the favorites list: adds it if absent, removes it if present. Maximum 100 favorites; adding beyond that is rejected with 400 Bad Request.
  • startPage — the page shown after sign-in. One of a fixed set of values (Dashboard, Cases, Devices, Customers, PatchCycles); default Dashboard.
  • openDevicesInNewTab — whether device links open in a new browser tab.
  • locale — your profile language, for example de. SMS, call, and app-push notifications are sent in this language; SMS and calls fall back to English and push to the device language when it is unset. An empty or whitespace-only value clears it.
  • welcomeSeen — whether you have already seen the welcome dialog. The web interface sets this to true once you close it.

Fields worth knowing

The full User object is documented field-by-field in Swagger. A few fields carry behavior that is easy to miss:

  • mailAddress — the login email address on the standard User object; note GET /api/users/me returns this as email instead.
  • groupIds — the IDs of the groups this user belongs to; the resolved group objects with permissions are returned only by GET /api/users/me. Read-only on this object — membership is set through the Groups API.
  • hasPassword / hasTotpSecret — booleans that report whether a local password or TOTP is set, without exposing the secret.
  • oidcLogins — linked OIDC sign-ins; each entry carries providerId (for example Microsoft), subjectId, and linkedAt.