Authentication
To access any endpoint in the iDempiere REST API, you must first authenticate and obtain a Bearer token. This token must be sent in the Authorization header of every request.
Login Overview
You can log in to the REST API in two main ways:
- One-step login — if you already know all the session parameters
- Normal login flow — a step-by-step process similar to the iDempiere UI
Important: You can only log in using roles where
Role Typeis set toWebServiceor is left blank. By default, theSystemrole is not permitted unless you clear itsRole Type, or better: create a dedicated WebService role.
One-Step Login
When you know all the values required to open a session (user, client, role, org, warehouse, language), use:
POST /api/v1/auth/tokens
Request body:
{
"userName": "GardenAdmin",
"password": "GardenAdmin",
"parameters": {
"clientId": 11,
"roleId": 2000001,
"organizationId": 11,
"warehouseId": 103,
"language": "en_US"
}
}
Normal Login Flow
This flow mimics the login process of the iDempiere UI.
Step 1: POST /api/v1/auth/tokens
Body:
{
"userName": "your-username",
"password": "your-password"
}
Response:
{
"clients": [{ "id": 11, "name": "GardenWorld" }],
"token": "eyJraWQiOiJpZGVtcGllcmUi..."
}
Step 2: Use the Token to Retrieve Options
Use the returned token in your request headers:
Authorization: Bearer YOUR_TOKEN
Then query the following endpoints in order:
Get Roles
GET /api/v1/auth/roles?client=11
Get Organizations
GET /api/v1/auth/organizations?client=11&role=2000001
Get Warehouses
GET /api/v1/auth/warehouses?client=11&role=2000001&organization=11
Get Languages
GET /api/v1/auth/language?client=11
Step 3: Finalize Login
PUT /api/v1/auth/tokens
Body:
{
"clientId": 11,
"roleId": 2000001,
"organizationId": 11,
"warehouseId": 103,
"language": "en_US"
}
Fields like language, organizationId, and warehouseId are optional. If omitted, defaults will be used.
Response Payload
{
"userId": 101,
"language": "en_US",
"token": "eyJraWQiOiJpZGVtcGllcmUi...",
"refresh_token": "eyJraWQiOiJpZGVtcGllcmUi..."
}
Use the token in your headers to authenticate future requests.
⚡ Abbreviated Login
If the user has access to only one client, role, and organization, the initial POST /auth/tokens may return the final token directly, without further steps.
Refresh & Logout
🔄 Refresh Token
The login process returns a token and a refresh_token. By default:
tokenexpires in 1 hourrefresh_tokenexpires in 24 hours
These defaults can be changed using the SysConfig keys:
REST_TOKEN_EXPIRE_IN_MINUTESREST_REFRESH_TOKEN_EXPIRE_IN_MINUTES
It's recommended to store the refresh_token in secure storage (e.g. cookies), and keep the token in memory only.
POST /api/v1/auth/refresh
Body:
{
"refresh_token": "your-refresh-token",
"clientId": 11,
"userId": 101
}
clientIdanduserIdare optional unless required via:
REST_MANDATORY_CLIENT_ID_ON_REFRESHREST_MANDATORY_USER_ID_ON_REFRESH
Response:
{
"token": "new-token",
"refresh_token": "new-refresh-token"
}
⚠️ Refresh tokens can only be used once. Reuse triggers a security breach and invalidates all related tokens.
To invalidate tokens, use the "Expire Refresh Tokens" process in iDempiere.
Logout
To log out and revoke the token:
POST /api/v1/auth/logout
Body:
{
"token": "your-auth-token"
}
This ends the session and invalidates both the token and its refresh token.
Password Reset (Forgot Password)
A code-based flow that lets a user who cannot log in reset their password. Unlike the rest of the
API, these endpoints are unauthenticated — do not send an Authorization header.
The flow has three steps:
- Request a one-time code, delivered by email.
- Verify the code to obtain a short-lived, single-use
verifiedToken. - Complete the reset by setting a new password with that token.
Step 1: Request a code
POST /api/v1/auth/password-reset/request
Body:
{
"email": "user@example.com",
"language": "en_US"
}
languageis optional and only selects the locale of the email template.
Response: always a neutral 200, whether or not the email matches an account (so the endpoint
cannot be used to discover which addresses are registered):
{
"summary": "If the email is registered, a code has been sent."
}
| Status | Meaning |
|---|---|
200 | Request accepted (neutral — sent only if the account exists). |
400 | email is missing or blank. |
429 | Too many reset requests for this identifier — try again later. |
Step 2: Verify the code
POST /api/v1/auth/password-reset/verify
Body:
{
"email": "user@example.com",
"code": "123456"
}
Response:
{
"verifiedToken": "3f9a0b7c..."
}
| Status | Meaning |
|---|---|
200 | Code verified — returns the verifiedToken for Step 3. |
400 | Missing fields, or an invalid/expired code, or too many attempts. |
The
400response is uniform and does not reveal whether the email is registered.
Step 3: Set the new password
POST /api/v1/auth/password-reset/complete
Body:
{
"verifiedToken": "3f9a0b7c...",
"newPassword": "MyNewPassw0rd!"
}
Response:
{
"summary": "Password updated successfully."
}
| Status | Meaning |
|---|---|
200 | Password changed. The account's existing sessions are invalidated. |
400 | Missing fields, an invalid/expired verifiedToken, or the new password violates the password policy. |
- Responses are neutral so the flow cannot be used to enumerate accounts - an unknown email behaves exactly like a registered one at every step.
- Codes are rate-limited and lock after a configurable number of wrong attempts; requesting a new code invalidates the previous one.
- The
verifiedTokenis single-use and short-lived.
The flow is tuned through the core PASSWORD_RESET_* System Configurator keys (documented with the
core Code-based password reset feature), not through REST-specific SysConfig keys.