Developer Documentation

Identity for teams that read the docs first.

Algebrix Identity is a standards-based authentication and user management platform. This document covers everything needed to integrate sign-in, single sign-on, multi-factor authentication, and programmatic management of users, sessions, invitations, and the audit trail.

Version
v2.1
Protocols
OAuth 2.0, OIDC 1.0
Transport
HTTPS only
Token format
JWT, RS256

01 Overview

Algebrix Identity handles the parts of authentication that are expensive to build and dangerous to get wrong: credential storage, session management, multi-factor enrolment, token issuance, and an auditable record of administrative change.

The platform implements OAuth 2.0 and OpenID Connect as published. There is no proprietary SDK requirement and no custom handshake. Any conformant OIDC client library works against it, so integration effort is measured in configuration rather than in code, and migrating away is a matter of repointing an authority URL.

What this version covers

  • Sign-in for single-page, native or mobile, and server-side web applications, using the authorization code flow
  • Machine-to-machine access to your own services using the client credentials grant
  • Single sign-on across every application in one organization
  • Time-based one-time password (TOTP) multi-factor authentication, enforceable for administrators or for everyone
  • Self-service applications created from four templates, with an integration view for each
  • A management API for users, roles, required actions, password reset emails, invitations, CSV import and export, sessions, sign-in branding, the audit log, and sign-in activity
  • Configurable sign-in security: password policy, brute-force protection, session and token lifetimes
  • A hosted administration console for every organization, requiring no build effort of your own
Before you start

Integration requires an organization. Create one at https://identity.algebrix.co/signup. You choose an identifier, the platform provisions the organization, and you create the applications you need from templates in the console. Section 03 covers signup and section 06 takes you from there to a first authenticated call. If you prefer to start from working code, section 06 also lists runnable sample applications for each application type.

Every example in this document uses {organization} as a placeholder for the identifier you choose.

The hosted console

There are two sign-in addresses for the console, one for each kind of administrator:

AddressWho signs in there
https://identity.algebrix.coAccount administrators. They manage the account: its organizations, subscription, and usage, plus their own profile, password, and multi-factor enrolment. They can also administer every organization in the account.
https://identity.algebrix.co/{organization}Organization administrators, meaning users of that organization who hold the admin role.

In the console, administrators can do the following:

  • Manage users, roles, invitations, and sessions.
  • Create and configure applications.
  • Set authentication policy.
  • Upload a sign-in logo.
  • Review the audit log and sign-in activity.
  • See usage against the plan.

The management API in section 08 covers user-facing operations programmatically. Automate what you want and leave the rest to the console.

02 Core concepts

Accounts, organizations, applications, users

ConceptWhat it is
AccountThe commercial entity that holds the subscription. Plan allowances belong to the account and are shared across all of its organizations. A billing restriction on the account applies to every organization in it.
OrganizationThe isolation boundary. Users, credentials, sessions, roles, signing keys, and audit records belong to exactly one organization and are invisible to every other. Addressed by a permanent identifier.
ApplicationA client registered in an organization, created from one of four templates. It has a client ID, and a secret if it is confidential. See section 04.
UserA person in an organization's directory. They hold exactly one role: admin, manager, or end-user.

Roles

RoleGrants
adminAccess to the organization console and to every endpoint under /api/admin
managerAn application-level role for your own authorization decisions. It carries no access to the management API.
end-userStandard access. No management API access.

Roles are exclusive: assigning one replaces the previous one.

Two surfaces

Algebrix Identity exposes two separate HTTP surfaces. They serve different purposes and are scoped differently. Confusing them is the most common cause of a failed first integration.

Identity surface
auth.algebrix.co/{organization}/oauth2/…

Token issuance, sign-in, sign-out, key publication. Every path carries an organization segment, and the segment is mandatory.

Scoped per organization
Management surface
api.algebrix.co/api/admin/no segment…

Administration of users, sessions, invitations, branding, and the audit trail. The organization is read from the access token, and every operation is scoped to it.

Scoped by token issuer

On the identity surface you state the organization, in the URL. On the management surface you do not: it is derived from the iss claim of the token you present, and every read and write is confined to that organization before any handler runs. There is no organization parameter to pass, and no way to reach another organization's data by changing one.

The same base URL, paths, and code serve every organization you run. Which organization you act on is decided entirely by which token you send.

One exception carries an identifier in the path: the anonymous public endpoint under /api/public/organizations/{organization}, which returns only a sign-in logo. It does not weaken the scoping guarantee, because it exposes nothing beyond a public image. See section 08.

Which credential reaches what

CredentialReaches
A signed-in user holding admin, through any application in the organizationEvery endpoint under /api/admin documented in section 08, for that organization only
A signed-in user holding manager or end-userNo management endpoint. Calls return 403.
A machine-to-machine application (client credentials)No management endpoint in this version. Calls return 403. Machine tokens are for your own services.
An account administratorThe console, including account-level operations: organizations, billing, usage, and entitlements. These operations are console-only in this version. An organization token, whatever its role, is refused on them with 403.

How a request flows

Your application never handles user credentials. The browser is redirected to the identity surface, the user authenticates there, and your application receives an authorization code, which it exchanges for tokens. Calls to the management surface carry the resulting access token as a bearer credential. The platform validates its signature against the organization's published key set before any handler runs.

03 Getting started

Signup

Signup at https://identity.algebrix.co/signup begins with the organization identifier. Because the identifier is permanent, decide on it before you start. There are two paths:

PathWhat happens
FreeYou choose an identifier and give an email address. The identifier is reserved for 24 hours and a verification email is sent. Nothing else is created until you verify. After you verify, the account and organization are provisioned and you set your password directly. No second email is sent.
PaidYou choose an identifier. It is reserved for 30 minutes while you complete payment details. If the reservation lapses first, the identifier returns to the pool. Nothing is created until payment details are accepted.

Payment details are handled entirely by Stripe. Card numbers never reach Algebrix systems.

Identifier format

PropertyValue
Pattern[a-z][a-z0-9-]{2,39}
Length3 to 40 characters
CaseLowercase only. Requests using uppercase are not matched.
ReservedInfrastructure hostnames, the Algebrix brand, master, and the console's own route names are refused
MutabilityPermanent once issued
The identifier cannot be changed, and is never reissued

The identifier is embedded in the iss claim of every token the platform signs. Changing it would invalidate every token already issued and break every application configured against it. Treat it with the same permanence as a domain name.

If an organization is deleted, its identifier is never released to another account. Only the account that owned it can claim it again. This means a client still configured against the old issuer can never present credentials to a different customer.

Two behaviours to expect

Identifiers are case-sensitive. A request to /ACME-CORP/oauth2/keys returns 404, while /acme-corp/oauth2/keys succeeds. If a first attempt returns 404 on every endpoint, check the case of the identifier first.

An unknown identifier still returns a discovery document. Discovery for an organization that does not exist returns 200, because the platform does not confirm or deny which organizations exist. The endpoints inside that document return 404. If discovery succeeds but every later call fails, the identifier is misspelled.

What arrives with an organization

A new organization contains no customer applications. You create the applications you need from templates in the console (section 04).

The organization also holds one platform-managed application, which the hosted console uses to sign administrators in. It is not listed in the console, cannot be edited or deleted, and must not be used by your own applications.

Organizations created from this version onward enforce the Medium password policy and have brute-force protection off. Section 12 covers both settings.

More organizations, and deleting one

Account administrators can create further organizations from the console, up to the plan's organization allowance (section 11). At the allowance, creation is refused with a 409 that names the plan which lifts it.

Deletion is also driven from the console by an account administrator.

  • It is a hard delete. The organization's users, applications, sessions, and settings are removed, and so are its audit records and sign-in activity. Its active-user figures for the current period are removed too. If you have retention obligations, export the audit log first (section 08).
  • The last organization in an account cannot be deleted. To leave a paid plan, cancel the subscription instead.

04 Applications

An application is a client that signs users in, or that authenticates as itself. You create applications in the console from four templates. Each template fixes the grant, whether the application is confidential, and which addresses it accepts, so you choose a template rather than configuring raw client settings.

TemplateTypeGrantSecretPKCE
Single-page appPublicAuthorization codeNoneRequired, S256 only
Native or mobile appPublicAuthorization codeNoneRequired, S256 only
Server-side web appConfidentialAuthorization codeYesOptional, recommended
Machine-to-machineConfidentialClient credentialsYesNot applicable

Sign-in redirect URIs

The redirect URI in an authorization request must match an address registered on the application, including scheme and port.

TemplateAccepted addresses
Single-page, server-side webhttps:// addresses. http:// is accepted only for localhost and 127.0.0.1, for development.
Native or mobileA custom scheme such as com.example.app://callback, or a loopback address such as http://127.0.0.1:8080/callback. https:// is refused, because a native application cannot receive an https redirect. A custom scheme starts with a letter and contains only letters, digits, +, - and ..
Machine-to-machineNone. The application never sends anyone to a browser.

The same rules apply to every template:

  • Wildcards may appear in the path only, never in the host. For example, https://app.example.com/* is accepted and https://*.example.com/cb is refused.
  • The value + on its own is reserved and refused. A + inside a path is accepted.
  • Empty values, values containing spaces, addresses with no host, and duplicates are refused.
  • A list holds at most 20 addresses.
  • There is no separate post-logout list. A post-logout redirect must be one of the application's sign-in redirect URIs. Register your signed-out landing page, for example your home page, as an additional sign-in redirect URI alongside your callback.

Each refusal names the rule, for example: Sign-in redirect URIs: 'https://*.example.com/cb' is not allowed. A wildcard may only appear in the path, never in the address itself.

Allowed origins

Only single-page applications have allowed origins, which are used for cross-origin requests to the identity surface. Each origin is a bare origin with no path, such as https://app.example.com. A list holds at most 20 origins. Server-side web and machine-to-machine applications do not accept origins.

Lifecycle

  • The client ID is derived from the display name at creation and is permanent. For example, "Billing Portal" becomes billing-portal. The display name can be changed at any time; the client ID cannot. Always read the client ID from the console, not from a naming pattern.
  • Secrets can be revealed and rotated in the console. Rotating a secret invalidates the previous one immediately. There is no period in which both are valid. Requests made with the old secret fail with unauthorized_client until every deployment uses the new one, so plan rotation for a maintenance window.
  • An application can be deactivated.
  • Deleting an application is permanent and ends its active sessions. The console shows the number of affected sessions before you confirm.
  • Every application counts against the account's application allowance, machine-to-machine applications included (section 11).

Integration view

Each application has an integration view in the console. It shows the discovery URL, the exact issuer value to use as the authority, the client ID, and copy-ready curl and JavaScript snippets with your organization filled in. It is the quickest way to configure a client library.

Applications are managed in the console

In this version, creating, configuring, and deleting applications, and revealing or rotating their secrets, are console operations. There is no published API for them.

05 Authentication and tokens

Grants

GrantUse whenActs as
authorization_codeA person signs in through a browser or a native app. Used by single-page, native or mobile, and server-side web applications.The signed-in user
client_credentialsA backend service acts on its own behalf with no user present, and calls your own APIs. Used by machine-to-machine applications.The application
refresh_tokenRenewing an access token without sending the user back through sign-in.The original user

To reach the management API, a token must be a user token carrying the admin role in realm_access.roles. The user can be signed in through any application in your organization. The management API checks the issuer, signature, expiry, and role. It does not check which application the token was issued to. Machine tokens are refused with 403.

Configuring an OIDC client library

Most libraries need only an authority and a client ID, and discover everything else. The discovery document is at:

GET https://auth.algebrix.co/{organization}/.well-known/openid-configuration

Libraries that enforce strict OpenID Connect Discovery validation compare the issuer field of that document with the authority they were configured with, and refuse to start if the two differ. Configure these libraries with the exact published issuer value, which is also shown in each application's integration view:

// issuer value, use verbatim as the authority
https://auth.algebrix.co/realms/{organization}

Libraries differ here. Some accept the path form as an authority, and others, such as openid-client and angular-auth-oidc-client, refuse it with an issuer mismatch. The exact issuer value works with every library, so use it as the authority. Discovery returns the same document from either form, and the endpoints it lists are the documented /{organization}/oauth2/… paths.

Libraries in common use

The platform works with any conformant OIDC library. There is nothing to install from Algebrix. These are widely used and actively maintained:

PlatformLibrary
Angularangular-auth-oidc-client
Reactreact-oidc-context, which wraps oidc-client-ts
Vue and plain JavaScriptoidc-client-ts
Node.jsopenid-client
.NETMicrosoft.AspNetCore.Authentication.OpenIdConnect
Java and SpringSpring Security OAuth2 Client
PythonAuthlib
iOS and AndroidAppAuth

Scopes

Request openid profile email. Other scopes advertised in the discovery document are not covered by support. See the note in section 07.

Client authentication

Confidential applications authenticate at the token endpoint with client_secret_basic (HTTP Basic) or client_secret_post (credentials in the form body). Both are accepted. Keep the secret server-side and out of source control.

Token claims

Access tokens are RS256-signed JWTs. Validate them against the key set published at the keys endpoint, and never trust an unverified token. Claims relevant to integration:

ClaimMeaning
issIssuer, https://auth.algebrix.co/realms/{organization}. This is the only claim that identifies the organization, and the management API reads it to scope every call.
subStable, permanent identifier of the user, or of the machine application's service identity. Use it as the foreign key in your own database, never the email address or username.
azpThe client ID of the application the token was issued to
audAlways account, whatever application issued the token. Do not use it to tell applications apart; use azp.
exp, iatExpiry and issue time, as Unix timestamps
sidThe session the token was issued from. It matches the id returned by the sessions endpoints.
realm_access.rolesThe assigned role, alongside built-in platform roles such as offline_access, uma_authorization, and default-roles-{organization}. Check that the role you need is present; never assume the array has one entry. Machine tokens carry only the built-in roles. Management endpoints require admin here.
preferred_usernameUsername. Mutable, so do not key on it.
emailEmail address. Mutable, so do not key on it.

Validating tokens in your own API

When your service accepts Algebrix Identity tokens, it should:

  1. Verify the signature against the keys endpoint. Select the key by the token's kid and accept only RS256 signatures; the key set also contains an encryption key, which is not for signature checks. Cache the keys and refresh them when you see an unknown kid.
  2. Verify that iss equals your organization's issuer value exactly.
  3. Verify exp.
  4. If only certain applications may call your API, check azp against their client IDs. Because aud is the same on every token, it cannot do this job.

Validate tokens locally in this way. Token introspection is not available in this version. The resource-server/node-express sample (section 06) implements these checks.

Token lifetimes

TokenLifetime
User access token300 seconds by default. Administrators can change it from 60 to 3,600 seconds in the console (section 12).
Machine-to-machine access token3,600 seconds. No refresh token is issued; request a new token when it expires.
Refresh tokenValid for the organization's idle sign-out period, which is 1,800 seconds by default. Each refresh restarts that period, up to the maximum session length (36,000 seconds by default), after which the user must sign in again.

Read expires_in from the token response rather than hardcoding a duration. An administrator can change the user token lifetime at any time.

Refresh tokens are not rotated. Each refresh returns a new refresh token value, and the previous one also stays valid until the session ends or is revoked. Store the latest one. Keep refresh tokens server-side, and never in browser-accessible storage.

Sign-out is shared across the organization. When a user signs out of any application in the organization, or the session reaches its idle or maximum limit, the next refresh in every application fails with invalid_grant and Session not active. Send the user back through sign-in.

Revocation

Know what each kind of revocation does before you rely on it:

  • Revoking a refresh token through POST /oauth2/revoke stops it immediately. The next refresh fails with 400 invalid_grant.
  • Revoking an access token does not stop the management API accepting it. The API validates tokens by signature and does not query the identity server on each request. A revoked access token stays usable until its exp.
  • Revoking a session (section 08) signs the user out and stops their refresh token. An access token already issued from that session stays valid until it expires, which is at most the organization's access token lifetime.
Suspected compromise

Revoke the user's sessions and disable the user. The access token lifetime is your revocation window, so keep it short if this matters to you.

06 Quickstarts

Every path starts the same way: create an application of the right type in the console, register its addresses, and copy its client ID from the integration view. These examples use the path form of the identity endpoints. Section 05 explains when to use the issuer value instead.

Sample applications

Runnable starter apps are published at github.com/algebrix/algebrix-identity-samples. They use the standard open-source OIDC libraries listed in section 05. They are not an SDK: there is nothing Algebrix-specific to install, and the code applies exactly the configuration this document describes. Each sample runs locally, uses placeholders for your organization and client ID, and states the documentation version it was tested against.

Application typeStackFolder
Single-page appReactspa/react
Single-page appAngularspa/angular
Server-side web appNode.js, Expressserver-side-web/node-express
Machine-to-machineNode.jsmachine-to-machine/node
Protecting your own APINode.js, Expressresource-server/node-express

Download a single sample without cloning the whole repository:

npx degit algebrix/algebrix-identity-samples/<type>/<stack> my-app

# for example
npx degit algebrix/algebrix-identity-samples/spa/react my-app

Then follow the sample's README: create the matching application in the console, register the addresses it lists, and fill in your organization and client ID. Samples for further stacks and for native applications will be listed here as they become available.

Path A: sign a user in (single-page or native app)

1

Create the application

Create a single-page app or a native or mobile app, and register the redirect URI your application will use, plus the page users should land on after signing out. An unregistered redirect URI is refused before the user sees a sign-in screen. The identity server shows its own error page, and no error is returned to your callback.

2

Send the user to the authorization endpoint

Generate a PKCE code verifier and its S256 challenge, store the verifier, then redirect:

GET https://auth.algebrix.co/{organization}/oauth2/authorize
  ?client_id={client_id}
  &redirect_uri=https://app.example.com/callback
  &response_type=code
  &scope=openid profile email
  &code_challenge={challenge}
  &code_challenge_method=S256
  &state={random_value}

Without code_challenge_method, or with plain, the request is refused with invalid_request.

3

Exchange the code for tokens

The user signs in, completes multi-factor authentication if required, and returns to your redirect URI with a code. Check that state matches the value you sent, then exchange the code:

POST https://auth.algebrix.co/{organization}/oauth2/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&client_id={client_id}
&code={code}
&redirect_uri=https://app.example.com/callback
&code_verifier={verifier}
4

Read the response

{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "refresh_token": "eyJhbGciOiJIUzUxMiIs...",
  "id_token": "eyJhbGciOiJSUzI1NiIs...",
  "token_type": "Bearer",
  "expires_in": 300,
  "refresh_expires_in": 1800
}

expires_in reflects the organization's configured lifetime; 300 is the default.

Sample: spa/react and spa/angular implement this path end to end, including sign-out.

Path B: sign a user in (server-side web app)

Create a server-side web app and register its redirect URI. The flow is Path A, with two differences:

  • The token exchange happens on your server and authenticates with the client secret, using either HTTP Basic or client_secret in the form body.
  • PKCE is optional. Using it is recommended.
curl -X POST https://auth.algebrix.co/{organization}/oauth2/token \
  -u "{client_id}:{client_secret}" \
  -d "grant_type=authorization_code" \
  -d "code={code}" \
  -d "redirect_uri=https://app.example.com/callback"

Sample: server-side-web/node-express.

Path C: authenticate a service to your own API

Create a machine-to-machine application and copy its client ID and secret from the console. No addresses need registering.

curl -X POST https://auth.algebrix.co/{organization}/oauth2/token \
  -d "grant_type=client_credentials" \
  -d "client_id={client_id}" \
  -d "client_secret={client_secret}"

The response carries an access token with expires_in: 3600 and no refresh token. Your API validates the token as described in section 05, checking azp if it should accept only this application.

  • Machine tokens are metered per calendar month against the account's allowance (section 11).
  • They cannot call the management API.
  • The secret must never reach a browser or a mobile binary.

Samples: machine-to-machine/node obtains and uses a machine token, and resource-server/node-express is an API that validates it.

Path D: call the management API

Sign in a user who holds admin through any application in your organization, using Path A or B. Then call the management API from server-side code with the resulting access token:

curl https://api.algebrix.co/api/admin/users?page=1&size=25 \
  -H "Authorization: Bearer {access_token}"

How to read the response:

  • 200 returns one page of users in your organization, and only yours. No organization parameter is sent; the platform reads it from the token.
  • 403 means the token is valid but the user does not hold admin, or the token is a machine token.
  • 401 means the token was rejected before authorization. Read the WWW-Authenticate header for the reason.
Attribution in the audit record

Every administrative change is recorded under the administrator who made it, in an audit trail scoped to your organization. Because management API calls are always made as a signed-in user, each change is traceable to an individual.

07 OIDC endpoints

All paths below are relative to https://auth.algebrix.co/{organization}. The organization segment is required on every one of them.

GET/.well-known/openid-configuration

Discovery document. Publishes the issuer, endpoint locations, supported scopes, and signing algorithms. Fetch it at startup rather than hardcoding endpoints.

GET/oauth2/authorize

Authorization endpoint. The browser redirect target that begins sign-in.

POST/oauth2/token

Token endpoint. Exchanges an authorization code, a refresh token, or client credentials for tokens.

GET/oauth2/userinfo

Returns claims about the authenticated user. Requires a bearer access token.

GET/oauth2/keys

JSON Web Key Set. It holds a signing key (use: sig, RS256) and an encryption key (use: enc). Verify signatures with the key matching the token's kid. Cache the keys, and refresh when you see an unknown key ID.

GET/oauth2/logout

Ends the session. Sign-out is shared across every application in the organization. A post_logout_redirect_uri is accepted only if it is registered as one of the application's sign-in redirect URIs; otherwise the identity server shows an "Invalid redirect uri" page and does not redirect.

POST/oauth2/revoke

Revokes a refresh token so it can no longer be used. Revoking an access token does not stop the management API accepting it before it expires. See section 05.

On the discovery document

The discovery document advertises the full capability of the underlying authorization server, which is broader than what is documented here. For example, it lists a registration endpoint, additional scopes, and additional client authentication methods. Endpoints, grants, and scopes absent from this document are not covered by support. If you need one of them, raise it with Algebrix before building against it.

08 Management API

Base URL https://api.algebrix.co. Every endpoint under /api/admin requires a user access token carrying the admin role (section 05). Every operation is scoped to the organization the token was issued for. Paths carry no organization segment, and none should be added. An identifier belonging to another organization resolves to 404, never to someone else's record.

Authorization: Bearer {access_token}

Conventions

TopicBehaviour
Content typeRequest bodies are application/json; any other content type returns 415. File uploads are multipart/form-data with the field name file. JSON responses are application/json; charset=utf-8, and CSV downloads are text/csv.
Field namesResponses use camelCase. Request property names are matched case-insensitively.
Unknown fieldsUnknown request properties and query parameters are ignored, not rejected. A misspelled field produces a success that changes nothing, so check responses rather than status codes alone.
TimestampsUTC, ISO 8601, with a Z suffix. Sub-second precision varies (for example 2026-09-25T08:10:50.42Z), and session timestamps are whole seconds. Parse with a standard ISO 8601 parser rather than a fixed pattern.
Date filtersyyyy-MM-dd, interpreted as UTC
Paging1-based page. The page-size parameter and its limits are given per endpoint. Out-of-range values are clamped to the nearest valid value rather than refused.
Rate limitsNone are applied to the management API or the OIDC endpoints in this version. Limits may be introduced later, so handle 429 with backoff.

Users

GET/api/admin/users

Lists users. The response shape depends on whether any query parameter is sent. With no parameters, it returns a bare array of every AdminUser in the organization, unpaged. With any parameter, it returns an AdminUserPage. Use the paged form for any directory of meaningful size.

ParameterTypeNotes
pageinteger1-based, default 1
sizeintegerDefault 25, maximum 200
searchstringCase-insensitive substring match across username, first name, last name, and email. A term in double quotes, "david.lee", matches exactly.
statusstringenabled, disabled, or all (the default). Any other value returns 400.
rolestringadmin, manager, or end-user. Cannot be combined with search or status; the combination returns 400. When role is sent, totalCount and totalPages are null, so paginate with hasNextPage.

Paged results are ordered by username, ascending. There is no filter for multi-factor state; read mfaEnabled on each user instead.

POST/api/admin/users

Creates a user. The body is CreateUserRequest. Returns 201 with the created AdminUser. The temporary password must be changed by the user at first sign-in, and it must satisfy the organization's password policy.

Refusals:

  • 409 for a duplicate username or email.
  • 409 with upgradeLifts: true when a plan user limit is reached (section 11).
  • 400 when the identity server rejects the user, for example a username below the minimum length or a password that fails the policy.
GET/api/admin/users/{id}

Returns one AdminUser. The id is the sub claim of that user's tokens.

GET/api/admin/users/{id}/detail

Returns UserDetail: the user, together with whether they are the organization's last administrator and which applications they have used.

GET/api/admin/users/{id}/activity

Returns audit and sign-in entries concerning this user, as an AuditPage, within the retention window. Parameters: page, and pageSize (default 20). An identifier with no recorded activity returns an empty page rather than 404, and this includes an identifier that does not exist.

PUT/api/admin/users/{id}

Updates profile fields. The body is UpdateUserRequest. Returns the updated AdminUser. The username cannot be changed.

DELETE/api/admin/users/{id}

Permanently removes the user, together with their sign-in record. Returns 204. Prefer disabling where a record of the account must survive.

PUT/api/admin/users/{id}/enabled

Enables or disables sign-in. The body is {"enabled": boolean}. Returns the updated AdminUser. A disabled user cannot authenticate, but keeps their record, role, and multi-factor enrolment.

PUT/api/admin/users/{id}/role

Assigns a role. The body is {"role": "admin" | "manager" | "end-user"}. Returns the updated AdminUser. Roles are exclusive, so assigning one replaces the previous one.

DELETE/api/admin/users/{id}/mfa

Clears the user's authenticator, for recovery when a device is lost. Returns the updated AdminUser. Returns 409 if the user has no authenticator to clear.

Clearing does not by itself make the user enrol again. They can then sign in with a password alone. Unless multi-factor enforcement applies to their role, follow the clear with a CONFIGURE_TOTP required action.

Required actions and password reset

POST/api/admin/users/{id}/required-actions

Requires the user to complete an action at their next sign-in. The body is {"action": "UPDATE_PASSWORD" | "CONFIGURE_TOTP"}. Values are case-sensitive, and any other value returns 400. Returns 200 with {"userId": "…", "pending": ["UPDATE_PASSWORD", "CONFIGURE_TOTP"]}, listing every action the user now owes.

  • Actions are additive: requiring a second action keeps the first.
  • The identity server decides the order in which pending actions are shown.
  • Each action clears itself once completed.
  • Actions can be set on a disabled user, so you can queue a password change before enabling the account.
POST/api/admin/users/{id}/password-reset

Emails the user a link to set a new password. There is no request body. Returns 204.

  • The link is valid for 24 hours, and the previous password stops working once the new one is set.
  • The email is the account-action email (section 12), not the "Forgot password?" email.
  • A disabled user returns 400; enable the account first.
  • 502 means the mail relay did not accept the message, so nothing was sent.

Invitations

Inviting someone creates their user account immediately, with no password, and emails them a link to choose one. They appear in the users list from that moment. Following the link proves the email address, so the account is marked verified when they finish. An invitation's status is derived from the account: pending until the password is set, accepted after, and revoked if withdrawn. Invitation links are valid for 72 hours.

GET/api/admin/invitations?status={status}

Returns a bare array of Invitation. status is pending (the default), accepted, or revoked. Capped at 100 per status.

POST/api/admin/invitations

Invites a person. The body is {"email": "…", "role": "admin" | "manager" | "end-user"}; role defaults to end-user. Returns 200 with the Invitation.

Refusals, each 400 with a message naming the cause:

  • a pending invitation already exists for the address, so resend it instead;
  • a user with the address already exists;
  • the role is invalid.

An address whose earlier invitation was revoked can be invited again. The invitation counts against the stored-user limit (section 11).

POST/api/admin/invitations/{id}/resend

Sends the email again to the existing account. It never creates a second account. Returns 200 with the Invitation, with lastSentAt updated.

DELETE/api/admin/invitations/{id}

Revokes a pending invitation. This deletes the account the invitation created, the emailed link stops working, and the stored-user allowance is released.

An accepted invitation cannot be revoked, because it is now a working account; disable or delete the user instead. An unknown id returns 404.

Import and export

GET/api/admin/users/csv/sample

Downloads a sample import file with the header username,email,firstName,lastName,role.

POST/api/admin/users/csv/preview

A dry run. It validates the uploaded file and creates nothing. Returns CsvPreview, which gives the total and valid rows, the room remaining under the stored-user limit, any shortfall, and a failure for each invalid row. The dry run does not refuse a file for exceeding the limit; the commit refuses the rows that do not fit.

POST/api/admin/users/csv

Commits the file. Partial success is the defined behaviour. Valid rows are created and failed rows are reported, and the response is always 200 with CsvCommit. Each row goes through the same validation and plan limits as POST /api/admin/users. failureReportCsv holds the failed rows with an error column, ready to correct and import again.

GET/api/admin/users/csv/export

Exports every user as CSV, with the columns username,email,firstName,lastName,role,status,mfa,createdAt. The export is designed to round-trip: the importer ignores the read-only columns. Existing users in a re-imported file are refused as duplicates rather than updated, so a round trip adds new rows only. The last sign-in time is not exported.

Import file rules

RuleValue
FormatRFC 4180 CSV. Quoted fields may contain commas and line breaks.
Columnsusername, email, and role are required; firstName and lastName are optional. role must be admin, manager, or end-user. A blank or unknown role fails that row and is never defaulted. There is no password column.
File sizeUnder 1,024 KB
RowsAt most 500 data rows. The limit is enforced while parsing, because a quoted field can contain a line break, so counting lines in advance would miscount. Larger files are refused before any user is touched.
Line numbersFailures report the file line: the header is line 1, and the first data row is line 2.
What an imported user is

An imported user is created with no password, owing UPDATE_PASSWORD, and with an unverified email address. No email is sent. Imported users cannot sign in until you send each of them a password reset email (POST /api/admin/users/{id}/password-reset). This version has no way to email all imported users at once. Imported users do not appear as invitations.

Sessions

GET/api/admin/sessions

Returns SessionList: every active session in the organization, capped at 500. truncated is true when the cap is reached.

GET/api/admin/users/{id}/sessions

Returns SessionList for one user. This list is complete.

DELETE/api/admin/sessions/{sessionId}

Ends one session. Returns 204, including for a session that has already ended.

DELETE/api/admin/users/{id}/sessions

Ends every session for the user. Returns 200 with {"revoked": n}.

Revoking a session signs the user out and stops its refresh token immediately. An access token already issued from that session remains valid until it expires, which is at most the organization's access token lifetime (accessTokenLifespanSeconds in the list response). For a suspected compromise, revoke the sessions and disable the user.

Some further details:

  • A session used across several applications appears once.
  • Offline sessions are not included.
  • A session's id equals the sid claim of tokens issued from it.

Branding

GET/api/admin/branding/logo

Returns LogoInfo for the organization's sign-in logo.

PUT/api/admin/branding/logo

Uploads the logo as multipart field file, replacing any existing logo. Returns 200 with LogoInfo.

Rules, each refused with 400 and a message naming the limit:

  • PNG or JPG only, detected from the file's contents rather than its name or declared type;
  • SVG is refused, because an SVG can carry script;
  • at most 512 KB;
  • at most 2,000 by 2,000 pixels.
DELETE/api/admin/branding/logo

Removes the logo. Returns 200. Returns 409 if there is no logo to remove.

GET/api/public/organizations/{organization}/logoAnonymous

Returns the organization's sign-in logo image, with no authentication. If no logo is uploaded, it returns the default Algebrix mark as SVG.

An unknown identifier also returns the default mark, byte-identical, so the endpoint cannot be used to discover which organizations exist.

An uploaded logo carries ETag and Cache-Control: no-cache, must-revalidate, so a replacement shows promptly. The default mark is cacheable for 300 seconds.

The logo appears on the organization's sign-in and multi-factor enrolment pages, at a fixed height. It does not appear in emails, which carry a text header only. Colours, backgrounds, and wording are configured by Algebrix on request.

Audit log and sign-in activity

Two separate trails are kept:

  • The audit log records administrative actions, such as creating a user, changing a role, rotating a secret, or changing billing.
  • Sign-in activity records authentication events.

Both are kept for the plan's retention window (section 11). Each response carries retentionDays, so read the window from there rather than hardcoding it.

GET/api/admin/audit-logs

Returns an AuditPage of administrative actions.

ParameterNotes
actorCase-insensitive substring of the acting administrator's username. % and _ are matched literally.
actionExact action name, from the actions endpoint below
targetSubstring of the target's username
fromDate, inclusive, UTC
toDate, exclusive, UTC. from=2026-09-25&to=2026-09-25 returns nothing; to include the 25th, send to=2026-09-26. This failure is silent, so it is worth getting right.
page, pageSizepageSize defaults to 20, maximum 100
GET/api/admin/audit-logs/actions

Returns a bare array of every administrative action name. Use this list rather than a hardcoded catalogue, because new actions are added as the platform grows.

GET/api/admin/audit-logs/export

Downloads the audit log as CSV. It takes the same filters as the list and honours every one, so the file matches the filtered view row for row. The columns are Timestamp,ActorUsername,Action,TargetUsername,Metadata, with Metadata as a CSV-quoted JSON object.

GET/api/admin/audit-logs/authentication

Returns an AuditPage of sign-in activity. Filters: actor, action, from, to, with the same semantics and paging as the audit log.

  • There is no outcome filter; filter by action=LOGIN_SUCCESS or action=LOGIN_FAILURE instead.
  • Events are collected every 30 seconds (ingestionIntervalSeconds), so a new sign-in can take up to that long to appear. This is not a live feed.
  • There is no CSV export for sign-in activity.
GET/api/admin/audit-logs/authentication/actions

Returns the sign-in action names: LOGIN_SUCCESS, LOGIN_FAILURE, LOGOUT, MFA_ENROLLED. A failed sign-in carries the reason in metadata.error, for example invalid_user_credentials.

More about both trails:

  • Every entry names the person who acted. Refused or failed operations write no entry.
  • Metadata keys are camelCase.
  • A user's own activity (/api/admin/users/{id}/activity) deliberately shows both kinds together: their sign-ins alongside the actions taken on them.
IP addresses in this version

Audit and session records include an ipAddress value. In this version it can record an address inside the Algebrix network rather than the originating client, so do not rely on it to identify a caller.

09 Schemas

AdminUser

{
  "id": "a87a5de8-1ab3-4716-b86a-3104f3f277f2",
  "username": "david.lee",
  "email": "[email protected]",
  "firstName": "David",
  "lastName": "Lee",
  "enabled": true,
  "roles": ["end-user"],
  "mfaEnabled": false,
  "createdAt": "2026-09-18T08:15:54.42Z",
  "lastSignInAt": "2026-09-19T11:02:10.503Z"
}
FieldNotes
idStable and permanent. Equal to the sub claim.
rolesAn array holding the user's single role
mfaEnabledWhether a TOTP authenticator is enrolled
lastSignInAtThe most recent successful sign-in, or null. It is kept independently of audit retention. null does not mean "never signed in": it means no sign-in has been recorded since sign-in tracking began for the organization.

AdminUserPage

{
  "items": [ /* AdminUser */ ],
  "page": 1,
  "size": 25,
  "totalCount": 312,        // null when filtered by role
  "totalPages": 13,         // null when filtered by role
  "hasNextPage": true,
  "signInHistoryDays": 90   // the per-user activity window
}

CreateUserRequest

FieldTypeNotes
usernamestringRequired. The sign-in identifier. It cannot be changed later.
emailstringRequired
firstNamestring
lastNamestring
temporaryPasswordstringRequired. Must satisfy the organization's password policy, and must be changed by the user at first sign-in.

A new user holds no role until one is assigned with PUT /api/admin/users/{id}/role.

UpdateUserRequest

FieldTypeNotes
emailstringRequired
firstNamestringOptional
lastNamestringOptional

UserDetail

{
  "user": { /* AdminUser */ },
  "isLastAdministrator": false,
  "signInHistoryDays": 90,
  "applicationsInUse": ["billing-portal", "mobile-app"]
}

applicationsInUse lists client IDs. Check isLastAdministrator before disabling, deleting, or changing the role of an administrator, so the organization is not left without one.

Invitation

{
  "id": "7a5a5053-8d98-4909-bde7-d4e3e3dddc10",
  "email": "[email protected]",
  "role": "end-user",
  "status": "pending",
  "invitedBy": "[email protected]",
  "createdAt": "2026-09-25T08:18:18.7939597Z",
  "lastSentAt": "2026-09-25T08:18:18.7939601Z",
  "acceptedAt": null,
  "revokedAt": null,
  "emailDelivered": true
}

SessionList

{
  "sessions": [
    {
      "id": "w9rZQFadZ0Zyqo8_t7PJsLq_",
      "userId": "a87a5de8-1ab3-4716-b86a-3104f3f277f2",
      "username": "david.lee",
      "ipAddress": "203.0.113.10",
      "startedAt": "2026-09-25T08:16:14Z",
      "lastAccessAt": "2026-09-25T08:16:14Z",
      "applications": ["billing-portal"]
    }
  ],
  "accessTokenLifespanSeconds": 300,
  "truncated": false
}

applications lists client IDs.

AuditPage

This shape is returned by the audit log, sign-in activity, and per-user activity endpoints.

{
  "items": [
    {
      "id": "cd147816-…",
      "timestamp": "2026-09-25T08:21:11.764Z",
      "actorUserId": "a87a5de8-…",
      "actorUsername": "david.lee",
      "action": "LOGIN_FAILURE",
      "targetUserId": null,
      "targetUsername": null,
      "metadata": { "error": "invalid_user_credentials" }
    }
  ],
  "totalCount": 15,
  "page": 1,
  "pageSize": 20,
  "totalPages": 1,
  "retentionDays": 90,
  "ingestionIntervalSeconds": 30   // 0 on the administrative log, written synchronously
}

CsvPreview

{
  "fileName": "users.csv",
  "totalRows": 4,
  "validRows": 3,
  "remainingStoredUsers": 9992,
  "shortfall": null,
  "failures": [
    { "line": 3, "username": "g.two", "email": "not-an-email", "firstName": "G",
      "lastName": "Two", "role": "end-user", "reason": "'not-an-email' is not a valid email address." }
  ],
  "failureReportCsv": null
}

CsvCommit

{
  "fileName": "users.csv",
  "totalRows": 3,
  "created": 2,
  "failed": 1,
  "failures": [ /* as in CsvPreview */ ],
  "failureReportCsv": "username,email,firstName,lastName,role,error\r\n…"
}

LogoInfo

{
  "hasLogo": true,
  "contentType": "image/png",
  "width": 240,
  "height": 80,
  "byteSize": 296,
  "updatedAt": "2026-09-25T08:33:17.5027867Z"
}

10 Errors

Response bodies differ by failure type. Handle every shape below rather than assuming a single envelope, and branch on the status code and on the machine-readable fields, not on message text. Messages are written for people and may be reworded.

StatusMeaningBody
200, 201, 204SuccessThe documented resource, or empty for 204
400Invalid input, or a business rule refused the requestA message body, or a validation Problem Details object for malformed input
401Missing, expired, or otherwise invalid tokenEmpty. The reason is in the WWW-Authenticate header.
402Administrative write blocked because the subscription is unpaidmessage and billingState
403Valid token without the required privilege: no admin role, a machine token, or an account-level operationEmpty, with no WWW-Authenticate header. The status code is the signal.
404No such resource in your organizationA message body, or a Problem Details object. An unrouted path returns an empty body.
409Conflict: a duplicate, nothing to remove, or a plan limit reachedA message body. upgradeLifts is true for plan limits.
415The request body is not application/jsonProblem Details
429Too many requestsEmpty. Not applied to the management API in this version; handle it anyway.
500Unexpected server-side failureQuote the traceId, if present, when contacting support
502An email could not be handed to the mail relay, so nothing was sentA message body

Message body

This shape is used for business-rule refusals with 400, 404, 409, and 502:

{
  "message": "Your plan (Free) includes 3 applications and you have 3. Starter includes 10.",
  "upgradeLifts": true
}

upgradeLifts is true only when moving to a higher plan removes the refusal, and false for every other refusal. Use it to decide whether to route a person to upgrading.

Validation Problem Details

This shape is returned for malformed input, such as an invalid email format, a missing required field, a missing upload, or malformed JSON:

{
  "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "errors": { "Email": ["The Email field is not a valid e-mail address."] },
  "traceId": "00-cdb2562e8941de77...-86ee0d1ec5ff51e3-00"
}

404 Not Found

Most not-found responses use the message body, for example {"message": "User not found.", "upgradeLifts": false}. GET /api/admin/users/{id} returns an RFC 9457 Problem Details object instead:

{
  "type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
  "title": "Not Found",
  "status": 404,
  "traceId": "00-df7c6aa7...-00"
}

Handle both shapes by status code.

401 Unauthorized

The body is empty. The diagnostic is in the response header, per RFC 6750:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer error="invalid_token",
  error_description="The issuer '...' is invalid"

With no token at all, the header is simply Bearer. An empty body here is expected behaviour, not a fault.

402 Payment Required

{
  "message": "A payment failed and the grace period has ended, so administrative changes are paused. Update your payment details in Billing to resume, or contact [email protected].",
  "billingState": "grace_expired"
}

billingState is one of trial_failed, grace_expired, or canceled. See section 11.

Diagnosing a failed call

SymptomLikely cause
404 on every identity endpointUppercase characters in the organization identifier, or a misspelling
Discovery returns 200, everything else 404The organization identifier does not exist
404 on /{organization}/protocol/openid-connect/…Under the organization prefix, the endpoints are /{organization}/oauth2/…. See section 07.
Library refuses to start, with an issuer mismatchThe authority is configured with the path form instead of the published issuer value. See section 05.
Sign-in shows an error page reading "Invalid parameter: redirect_uri" and never returns to the callbackThe redirect URI is not registered on the application, or does not match it exactly. Nothing is sent to the unregistered address.
Sign-out shows "Invalid redirect uri"The post_logout_redirect_uri is not registered as a sign-in redirect URI. There is no separate post-logout list.
invalid_request: "Missing parameter: code_challenge_method" or "code challenge method is not matching the configured one"A single-page or native application sent no PKCE challenge, or sent plain. Use S256.
401 unauthorized_client on the token endpointWrong client secret, or a secret that has since been rotated
401 invalid_client on the token endpointThe client ID does not exist in this organization
login_required, with no description, on a prompt=none requestThe user has no active session. Send them through interactive sign-in.
Refresh fails with invalid_grant, "Session not active"The session ended: idle sign-out, maximum session length, or sign-out from any application in the organization
400 on the token endpointThe redirect URI differs from the one used at authorization, or the PKCE verifier does not match the challenge
401 with an issuer messageThe token was not issued by Algebrix Identity, or its organization is not recognised
403 on /api/adminThe user does not hold admin, or the token is a machine-to-machine token. Machine tokens cannot call the management API.
403 on an account-level routeOrganizations, billing, and usage are console-only for account administrators
404 on a user you know existsThe user belongs to a different organization than the token. Operations never cross organizations.
401 on the token endpoint for a machine application, while others workThe account's monthly machine token allowance is exhausted and machine token issuance is paused. See section 11.
409 with upgradeLifts: trueA plan limit has been reached
402 on a write that used to succeedThe subscription is unpaid. Reads still work.
A request succeeds but changes nothingA misspelled field. Unknown fields are ignored, not rejected.
Audit query returns nothing for todayto is exclusive. Send the following day.
Password refused at the set-password page although it looks strongThe organization's password policy requires a rule the password misses. The page lists every rule.
Correct password refused after several failuresBrute-force protection has locked the account temporarily. An administrator can unlock it from the console.
Users are unexpectedly prompted to enrol an authenticatorMulti-factor enforcement was turned on for their role

11 Plans, limits, and billing

Allowances belong to the account and are shared across all of its organizations. Current usage against every allowance is shown in the console.

FreeStarterGrowthScale
Organizations252550
Applications (all types)31050100
Machine-to-machine tokens per calendar month5002,0005,00015,000
Monthly active users10,00025,00050,000100,000
Console administrators131025
SSO connections351025
Audit and sign-in retention7 days30 days90 days365 days

Scale is a negotiated plan: its figures are included amounts, not ceilings, and never block.

How each allowance is measured and enforced

AllowanceBehaviour
OrganizationsCreation is refused at the allowance with 409, upgradeLifts: true.
ApplicationsEvery customer application counts, machine-to-machine included. The platform-managed console application does not. Creation is refused at the allowance with 409.
Monthly active usersDistinct users who signed in during the current calendar month. Machine applications are excluded.
  • Paid plans are warned, never blocked.
  • Free refuses new user creation once the allowance is reached.
  • Existing users always keep signing in.
Stored users (Free)Free organizations can hold up to 10,000 users in the directory. At that limit, creating, inviting, or importing a user is refused with 409, naming the plan that lifts the limit. Invitations and imported users count, because they create directory users.
Machine-to-machine tokensTokens issued through the client credentials grant in the calendar month. A warning is shown at 80% of the allowance, and the account is emailed at 100%.
  • On Free, issuance pauses once the allowance is reached.
  • On paid plans, service continues for a limited margin past the allowance, then pauses if usage continues.
  • While paused, token requests for the account's machine applications fail with 401.
  • User sign-in and every other endpoint are unaffected.
  • Service resumes at the start of the next calendar month, or within a minute or two of an upgrade that raises the allowance.
  • Enforcement runs on a short cycle, and tokens already issued stay valid until they expire, so issuance stops slightly above the threshold.
Console administrators, SSO connectionsPublished allowances. They are not enforced at creation in this version. Enterprise SSO is set up with Algebrix assistance.
RetentionAudit and sign-in activity records older than the window are removed. Aggregated sign-in statistics are kept, so usage figures are unaffected, and lastSignInAt is not bounded by the window. Organizations on an invoiced agreement retain records for 45 days. If you have compliance retention requirements, export within your window. Read retentionDays from the audit responses rather than relying on this table.

Plan changes

Plan changes are made in the console by an account administrator. You can move between paid plans and switch between monthly and annual billing.

  • A downgrade is refused if current usage exceeds the target plan, and the refusal names the dimension.
  • Moving from a paid plan to Free is not possible. Cancelling is the exit from a paid plan.

Billing restrictions

If a subscription goes unpaid, administrative changes are paused. Nothing else is. Understand this before you build, because it determines what your integration can and cannot do in that state.

What keeps working

Your users keep signing in. Token issuance and every OIDC endpoint are unaffected in every unpaid state. No token is revoked and no session is ended. A billing problem is never allowed to take down authentication for people who have no idea one exists.

Reads keep working. Every GET under /api/admin continues to return data, so you can still list users and export the audit log.

What pauses is every write under /api/admin: creating, updating, disabling, or deleting users; roles and required actions; password reset emails; invitations; CSV import, including the dry run; session revocation; logo changes; and clearing multi-factor enrolment. Each returns 402. Writes resume automatically, within about a minute of a successful payment.

  • The restriction is account-wide. One unpaid subscription pauses writes in every organization of the account.
  • A trial that ends without a successful payment restricts writes immediately, reported as trial_failed.
  • When an established subscription's payment fails, there is a seven-day grace period from the first failure, during which everything works normally. After that, it is reported as grace_expired. Retries do not extend the grace period.
  • A cancelled subscription is reported as canceled.
  • Organizations on an invoiced agreement, including Enterprise, are billed separately and are never restricted.

Administrators see the current state, and the date on which access will be restricted, in the console. If your operations team monitors integrations rather than the console, treat a 402 as the signal to check billing.

12 Security settings and the end-user experience

Administrators configure these settings per organization in the console. Changes take effect immediately and are recorded in the audit log. They are not available through the API in this version, but they change what your users and your integration experience, so they are documented here.

Password policy

RuleWeakMediumStrong
Minimum length81012
Upper case, lower case, digitNot required1 of each1 of each
Special characterNot requiredNot required1
Must differ from the usernameYesYesYes
Cannot repeat recent passwordsNoLast 3Last 5
ExpiryNoneNoneNone
  • New organizations use Medium. Organizations created before this default was introduced have no password policy until an administrator selects one, and the console says so.
  • A policy applies when a password is next set or changed. Existing passwords are not re-checked, and nobody is forced to change theirs.
  • Rules beyond the three levels, such as a longer minimum or a blocklist, are configured by Algebrix on request.

Brute-force protection

Brute-force protection is off by default. When it is on, an account is locked temporarily after a number of consecutive failed sign-ins, and while it is locked even the correct password is refused. Each further failure doubles the lockout, up to the maximum. Administrators see locked accounts in the console and can unlock them. The list can lag by up to 30 seconds.

SettingRangeDefault when first enabled
Failures before lockout3 to 10030
First lockout10 to 3,600 seconds60 seconds
Maximum lockout60 to 86,400 seconds900 seconds
Permanent lockoutOn or offOff

Session and token lifetimes

SettingRangeDefault
Access token lifetime60 to 3,600 seconds300 seconds
Idle sign-out300 to 2,592,000 seconds1,800 seconds
Maximum session length600 to 2,592,000 seconds36,000 seconds

Some constraints link these settings:

  • The maximum session length cannot be shorter than the idle sign-out.
  • An access token never outlives its session.
  • The access token lifetime is also how long a revoked session's last access token remains usable, which is why it is capped at one hour.

Multi-factor authentication

EnforcementEffect
Off (default)No one is required to enrol
AdministratorsEvery user holding admin must enrol a TOTP authenticator at their next sign-in
EveryoneEvery user must enrol at their next sign-in
  • Turning enforcement off does not remove anyone's authenticator.
  • Enforcement is independent of the per-user CONFIGURE_TOTP required action, which works in every mode.
  • A TOTP code is single-use. The code used to enrol cannot also be used to sign in within the same 30-second window, which can look like a failed sign-in during testing.

Self-registration

Self-registration is off by default. When it is on, a Register link appears on the organization's sign-in page, and people who register count towards the plan's user allowances. Email verification can be required for people who register. Invited people already prove their address by following the emailed link.

What your users see

  • Sign-in and enrolment pages carry the organization's logo, if one is uploaded.
  • There is no end-user account page. https://auth.algebrix.co/realms/{organization}/account returns 404. Users change their password through the "Forgot password?" link, a password reset email, or an UPDATE_PASSWORD required action.
  • Users enrol an authenticator only when enforcement or a CONFIGURE_TOTP required action asks them to. They cannot enrol or remove one on their own initiative; an administrator clears an authenticator for recovery. Managing your own authenticator in Account settings is available to account administrators only.
  • The set-password page lists the organization's rules before the person types.
  • A dead, expired, or revoked link shows a plain message asking for a new link. A mistyped password at sign-in shows the same message.
  • After setting a password, the person sees a Back to the application link. It goes to one of the organization's applications that has a concrete, non-wildcard redirect URI registered. Without one, it goes to the organization's console address, which a non-administrator cannot use. Register at least one concrete redirect URI so that invited and reset users land in your application.
  • A person invited with an email address only is asked for their name before finishing. They are not signed in automatically; they sign in afterwards.

Emails your users receive

EmailSent whenSubject
Password resetThe user chooses "Forgot password?"Reset your password
Account actionAn administrator sends a password reset or an invitation, or the user owes an actionAction needed on your account
Email verificationVerification is requiredConfirm your email address
  • The sender name is the organization's display name, from [email protected], with replies going to [email protected].
  • Every body names the organization, but subjects cannot include it, which is a platform constraint.
  • The set-password email includes the full sign-in address for the user's organization and their username, as they will type it.
  • Emails carry no remote images.
  • Signup verification and account administrator emails are sent by Algebrix Identity and do not name an organization.

13 Scope and behaviour

What the platform does and does not do, stated plainly so that evaluation does not turn up surprises.

Not available in this version

CapabilityStatus
Machine-to-machine access to the management APINot available. Call the management API as a signed-in administrator.
API management of applications, organizations, billing, and authentication settingsConsole only
SAML federation to a corporate IdPOn the roadmap
SCIM provisioningNot available. Use the management API or CSV import.
Token exchange, RFC 8693On the roadmap. Not supported for integration.
Dynamic client registration, RFC 7591Not supported, although the discovery document lists a registration endpoint. Create applications in the console.
Passkeys and WebAuthnNot available. Multi-factor authentication is TOTP only.
End-user self-service account pageNot available
Token introspection, RFC 7662Not available, although the discovery document lists the endpoint. Validate tokens locally against the keys endpoint (section 05).
Refresh token rotationNot enabled
Overlapping client secrets during rotationNot available. Rotation takes effect immediately.
Platform SDKsNone. Use the standard OIDC libraries in section 05, or start from a sample application (section 06).
Forced password expiry, or forcing a reset after a policy changeNot offered
Sign-in activity exportNot available. The audit log exports.
Filtering users by multi-factor stateNot available
Emailing many users at onceNot available
Self-service branding beyond the logoColours, backgrounds, and wording are configured by Algebrix on request
Webhooks, API keys, directory syncOn the roadmap
Enterprise SSO, custom domainsAvailable with Algebrix assistance

Operational notes

  • HTTPS only. Plaintext HTTP is not served on any endpoint.
  • Organizations share nothing. Users, credentials, sessions, roles, signing keys, and audit records belong to exactly one organization.
  • User identifiers are stable. The id field and the sub claim are the same value and never change. Usernames and email addresses can change, so do not key on them.
  • Client IDs are permanent. Display names can change.
  • Disable rather than delete where the audit trail must keep resolving an account. User deletion is permanent, and there is no undelete.
  • Deleting an application ends its sessions. Deleting an organization destroys its audit trail, so export first.
  • Authentication is never gated on billing or on machine token allowances. User sign-in continues in every subscription and quota state.
  • Sign-in activity arrives within 30 seconds, not in real time.

Standards implemented

OAuth 2.0 (RFC 6749), Bearer Token Usage (RFC 6750), PKCE (RFC 7636), Token Revocation (RFC 7009), JSON Web Token (RFC 7519), OpenID Connect Core 1.0, and OpenID Connect Discovery 1.0. The authorization core is Apache-2.0 licensed and standards-conformant. No proprietary protocol extension is required for integration, and there is no lock-in at the protocol layer.

Versioning and support

API paths carry no version segment, and this document is versioned instead. Version 2.1 describes the platform as of September 2026. Changes that would break an existing integration are published as a new major version of this document; minor versions add guidance and clarifications.

Version 2.1 adds the sample applications and clarifies secret rotation, post-logout redirects, the roles claim, refresh token behaviour, signing key selection, and common error responses. Token introspection is no longer listed as available.

For support, write to [email protected]. For a specific failed call, include the traceId where one is returned.