Authentication
Password management, MFA settings, and authentication security.
Password Management
PUT /api/users/{username}/password
Change a user's password. Only valid when the user's domain is password-managed by Informer (SSO/IdP domains delegate the credential elsewhere).
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
oldPassword | string | Yes | The current password |
password | string | Yes | The new password (must meet the tenant strength policy and differ from the old one) |
{
"oldPassword": "D0cs-Example-Pass!",
"password": "N3w-Docs-Pass!2026"
}
{
"_links": {
"self": {
"href": "https://informer.example.com/api/users/pat.nguyen/password"
},
"inf:memberships": {
"href": "https://informer.example.com/api/users/pat.nguyen/password/memberships"
},
"inf:avatar-upload": {
"href": "https://informer.example.com/api/users/pat.nguyen/password/_upload/{uploadId}/avatar-upload",
"templated": true
},
"inf:password": {
"href": "https://informer.example.com/api/users/pat.nguyen/password/password"
},
"inf:feed": {
"href": "https://informer.example.com/api/users/pat.nguyen/password/feed"
},
"inf:viewed-feed": {
"href": "https://informer.example.com/api/users/pat.nguyen/password/_markFeedViewed"
},
"inf:superuser": {
"href": "https://informer.example.com/api/users/pat.nguyen/password/superuser"
}
},
"permissions": {
"changeDomain": true,
"changeProfile": true,
"changePassword": true,
"delete": true,
"edit": true,
"reassign": true,
"superuser": true,
"enable": true,
"changeTheme": true,
"lock": true,
"setGlobalPermissions": true,
"manageLogin": true
},
"domain": "local",
"username": "pat.nguyen",
"displayName": "pat.nguyen",
"familyName": null,
"givenName": null,
"middleName": null,
"email": "pat.nguyen@example.com",
"data": null,
"superuser": false,
"timezone": "America/New_York",
"settings": {
"log": {
"log": false,
"info": false,
"warn": false,
"debug": false,
"error": true,
"remote": false
}
},
"enabled": true,
"source": null,
"sourceId": null,
"lastViewedFeed": null,
"tenant": "acme",
"globalPermissions": {
"ai": false,
"jobCreation": false,
"viewAllTeams": false,
"viewAllUsers": false,
"painlessScriptCreation": false
},
"userFields": {},
"locked": false,
"lockedAt": null,
"loginAttempts": 0,
"passwordSetAt": "2026-01-15T16:20:00.000Z",
"passwordExpiresAt": "2026-01-15T16:20:00.000Z",
"forgotPasswordRequestTime": null,
"mfa": null,
"mfaConfig": {},
"aiMessage": null,
"aiConsent": false,
"hasSharedDatasources": false,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"teams": [],
"initials": "PA",
"colorIndex": 4,
"avatarColor": {
"background": "#81C784",
"text": "#1B5E20"
},
"managesPassword": true
}
POST /api/users/{username}/_expire-password
Force password expiration, requiring a password change at next login.
Permissions: user:edit
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
passwordExpiresAt | date | No | When the password expires. Defaults to now. |
{
"passwordExpiresAt": "2026-01-15T16:20:00.000Z"
}
{
"_links": {
"self": {
"href": "https://informer.example.com/api/users/dana.kim/_expire-password"
},
"inf:memberships": {
"href": "https://informer.example.com/api/users/dana.kim/_expire-password/memberships"
},
"inf:avatar-upload": {
"href": "https://informer.example.com/api/users/dana.kim/_expire-password/_upload/{uploadId}/avatar-upload",
"templated": true
},
"inf:password": {
"href": "https://informer.example.com/api/users/dana.kim/_expire-password/password"
},
"inf:feed": {
"href": "https://informer.example.com/api/users/dana.kim/_expire-password/feed"
},
"inf:viewed-feed": {
"href": "https://informer.example.com/api/users/dana.kim/_expire-password/_markFeedViewed"
},
"inf:superuser": {
"href": "https://informer.example.com/api/users/dana.kim/_expire-password/superuser"
}
},
"permissions": {
"changeDomain": true,
"changeProfile": true,
"changePassword": true,
"delete": true,
"edit": true,
"reassign": true,
"superuser": true,
"enable": true,
"changeTheme": true,
"lock": true,
"setGlobalPermissions": true,
"manageLogin": true
},
"domain": "local",
"username": "dana.kim",
"displayName": "dana.kim",
"familyName": null,
"givenName": null,
"middleName": null,
"email": "dana.kim@example.com",
"data": null,
"superuser": false,
"timezone": "America/New_York",
"settings": {
"log": {
"log": false,
"info": false,
"warn": false,
"debug": false,
"error": true,
"remote": false
}
},
"enabled": true,
"source": null,
"sourceId": null,
"lastViewedFeed": null,
"tenant": "acme",
"globalPermissions": {
"ai": false,
"jobCreation": false,
"viewAllTeams": false,
"viewAllUsers": false,
"painlessScriptCreation": false
},
"userFields": {},
"locked": false,
"lockedAt": null,
"loginAttempts": 0,
"passwordSetAt": "2026-01-15T16:20:00.000Z",
"passwordExpiresAt": "2026-01-15T16:20:00.000Z",
"forgotPasswordRequestTime": null,
"mfa": null,
"mfaConfig": {},
"aiMessage": null,
"aiConsent": false,
"hasSharedDatasources": false,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"teams": [],
"initials": "DA",
"colorIndex": 4,
"avatarColor": {
"background": "#81C784",
"text": "#1B5E20"
},
"managesPassword": true
}
PUT /api/users/reset-expired-password
Reset an expired password. Tenant-level: no user session is required, the caller supplies their own credentials. Also clears any lock and the failed-login counter.
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
username | string | Yes | The account to reset |
oldPassword | string | Yes | The current (expired) password |
password | string | Yes | The new password |
{
"username": "evan.cho",
"oldPassword": "D0cs-Example-Pass!",
"password": "Res3t-Docs-Pass!2026"
}
{
"_links": {
"self": {
"href": "https://informer.example.com/api/users/reset-expired-password"
},
"inf:memberships": {
"href": "https://informer.example.com/api/users/reset-expired-password/memberships"
},
"inf:avatar-upload": {
"href": "https://informer.example.com/api/users/reset-expired-password/_upload/{uploadId}/avatar-upload",
"templated": true
},
"inf:password": {
"href": "https://informer.example.com/api/users/reset-expired-password/password"
},
"inf:feed": {
"href": "https://informer.example.com/api/users/reset-expired-password/feed"
},
"inf:viewed-feed": {
"href": "https://informer.example.com/api/users/reset-expired-password/_markFeedViewed"
},
"inf:superuser": {
"href": "https://informer.example.com/api/users/reset-expired-password/superuser"
}
},
"permissions": {
"changeDomain": true,
"changeProfile": true,
"changePassword": true,
"delete": true,
"edit": true,
"reassign": true,
"superuser": true,
"enable": true,
"changeTheme": true,
"lock": true,
"setGlobalPermissions": true,
"manageLogin": true
},
"domain": "local",
"username": "evan.cho",
"displayName": "evan.cho",
"familyName": null,
"givenName": null,
"middleName": null,
"email": "evan.cho@example.com",
"data": null,
"superuser": false,
"timezone": "America/New_York",
"settings": {
"log": {
"log": false,
"info": false,
"warn": false,
"debug": false,
"error": true,
"remote": false
}
},
"enabled": true,
"source": null,
"sourceId": null,
"lastViewedFeed": null,
"tenant": "acme",
"globalPermissions": {
"ai": false,
"jobCreation": false,
"viewAllTeams": false,
"viewAllUsers": false,
"painlessScriptCreation": false
},
"userFields": {},
"locked": false,
"lockedAt": null,
"loginAttempts": 0,
"passwordSetAt": "2026-01-15T16:20:00.000Z",
"passwordExpiresAt": "2026-01-15T16:20:00.000Z",
"forgotPasswordRequestTime": null,
"mfa": null,
"mfaConfig": {},
"aiMessage": null,
"aiConsent": false,
"hasSharedDatasources": false,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"teams": [],
"initials": "EV",
"colorIndex": 4,
"avatarColor": {
"background": "#81C784",
"text": "#1B5E20"
},
"managesPassword": true
}
POST /api/users/{username}/force-password-reset
Email the user a password-reset link. The user must be enabled, unlocked, have an email address, and live in a password-managing domain.
Permissions: user:edit
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
logoutUser | boolean | No | Also destroy the user's active sessions. Defaults to true. |
Behavior:
When a mail server is configured the link is emailed and the response is empty. When none is configured, the route returns the tentative email contents (from/to/subject) so an admin can deliver it manually.
{
"logoutUser": true
}
{
"_links": {
"self": {
"href": "https://informer.example.com/api/users/mira.shah/force-password-reset"
}
},
"from": "",
"to": "mira.shah@example.com",
"subject": "Informer Password Reset",
"html": "(omitted)",
"body": "(omitted)",
"clipboardBody": "(omitted)"
}
Multi-Factor Authentication (MFA)
GET /api/users/{username}/mfa
List the MFA authenticator options available for the user's domain.
Response:
An array of authenticator setup components (each with id, name, and the data needed to render its enrollment UI). Empty when the tenant has no MFA providers enabled.
PUT /api/users/{username}/mfa
Enroll the user in an authenticator. The server verifies the submitted code before saving the method, so a live code from the authenticator is required.
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
mfaConfig | object | Yes | The authenticator config |
mfaConfig.id | string | Yes | The authenticator driver id (from the GET response) |
mfaConfig.code | string | Yes | The current verification code to confirm setup |
Responds 200 on success; 400 if the code is invalid.
DELETE /api/users/{username}/mfa
Remove the user's MFA enrollment.
Permissions: user:edit or own account
Response:
Clears the user's MFA method and config; returns the updated user.
{
"_links": {
"self": {
"href": "https://informer.example.com/api/users/omar.haddad/mfa"
},
"inf:memberships": {
"href": "https://informer.example.com/api/users/omar.haddad/mfa/memberships"
},
"inf:avatar-upload": {
"href": "https://informer.example.com/api/users/omar.haddad/mfa/_upload/{uploadId}/avatar-upload",
"templated": true
},
"inf:password": {
"href": "https://informer.example.com/api/users/omar.haddad/mfa/password"
},
"inf:feed": {
"href": "https://informer.example.com/api/users/omar.haddad/mfa/feed"
},
"inf:viewed-feed": {
"href": "https://informer.example.com/api/users/omar.haddad/mfa/_markFeedViewed"
},
"inf:superuser": {
"href": "https://informer.example.com/api/users/omar.haddad/mfa/superuser"
}
},
"permissions": {
"changeDomain": true,
"changeProfile": true,
"changePassword": true,
"delete": true,
"edit": true,
"reassign": true,
"superuser": true,
"enable": true,
"changeTheme": true,
"lock": true,
"setGlobalPermissions": true,
"manageLogin": true
},
"domain": "local",
"username": "omar.haddad",
"displayName": "omar.haddad",
"familyName": null,
"givenName": null,
"middleName": null,
"email": "omar.haddad@example.com",
"data": null,
"superuser": false,
"timezone": "America/New_York",
"settings": {
"log": {
"log": false,
"info": false,
"warn": false,
"debug": false,
"error": true,
"remote": false
}
},
"enabled": true,
"source": null,
"sourceId": null,
"lastViewedFeed": null,
"tenant": "acme",
"globalPermissions": {
"ai": false,
"jobCreation": false,
"viewAllTeams": false,
"viewAllUsers": false,
"painlessScriptCreation": false
},
"userFields": {},
"locked": false,
"lockedAt": null,
"loginAttempts": 0,
"passwordSetAt": "2026-01-15T16:20:00.000Z",
"passwordExpiresAt": "2026-01-15T16:20:00.000Z",
"forgotPasswordRequestTime": null,
"mfa": null,
"mfaConfig": {},
"aiMessage": null,
"aiConsent": false,
"hasSharedDatasources": false,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"teams": [],
"initials": "OM",
"colorIndex": 4,
"avatarColor": {
"background": "#81C784",
"text": "#1B5E20"
},
"managesPassword": true
}
Account Locking
Unlocking a locked account lives under Account Management.