Skip to main content

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 Type is set to WebService or is left blank. By default, the System role is not permitted unless you clear its Role 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"
}
tip

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:

  • token expires in 1 hour
  • refresh_token expires in 24 hours

These defaults can be changed using the SysConfig keys:

  • REST_TOKEN_EXPIRE_IN_MINUTES
  • REST_REFRESH_TOKEN_EXPIRE_IN_MINUTES
Security Tip

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
}

clientId and userId are optional unless required via:

  • REST_MANDATORY_CLIENT_ID_ON_REFRESH
  • REST_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:

  1. Request a one-time code, delivered by email.
  2. Verify the code to obtain a short-lived, single-use verifiedToken.
  3. 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"
}

language is 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."
}
StatusMeaning
200Request accepted (neutral — sent only if the account exists).
400email is missing or blank.
429Too 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..."
}
StatusMeaning
200Code verified — returns the verifiedToken for Step 3.
400Missing fields, or an invalid/expired code, or too many attempts.

The 400 response 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."
}
StatusMeaning
200Password changed. The account's existing sessions are invalidated.
400Missing fields, an invalid/expired verifiedToken, or the new password violates the password policy.
Security
  • 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 verifiedToken is 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.