Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/CodexaCP/DG_BACK/llms.txt

Use this file to discover all available pages before exploring further.

The standard login flow is the primary authentication path for back-office users — supervisors, administrators, and any operator who logs in through the web interface. The client submits an email address and password; Dragon Guard verifies the BCrypt hash, checks that the user’s tenant is active, and returns a signed JWT along with user and company metadata.

POST /api/auth/login

Authenticates a user with their email address and password. Returns a JWT token and session metadata on success.

Request body

email
string
required
The user’s email address. Must match an existing auth.Users record.
password
string
required
The user’s plaintext password. Verified against the BCrypt hash stored in auth.Users.PasswordHash.
isHandheld
boolean
Set to true when the login request originates from a handheld device. When true and a deviceId is provided, the device is validated and its last-seen metadata is updated as part of the login flow.
deviceId
string
Device identifier (typically a MAC address). Required when isHandheld is true. The value is normalized to uppercase colon-separated format (e.g. AA:BB:CC:DD:EE:FF) before lookup.
deviceName
string
Human-readable label for the device (e.g. "Scanner-01"). When supplied alongside deviceId, it updates the DeviceName field on the device record. Optional.

Response fields

token
string
Signed HMAC SHA-256 JWT. Pass this value as Authorization: Bearer <token> on subsequent requests.
userId
string (UUID)
The authenticated user’s unique identifier (auth.Users.Id).
email
string
The authenticated user’s email address.
fullName
string
The authenticated user’s display name.
isSuperAdmin
boolean
true when the user holds the global SUPERADMIN_SUPREMO role. SUPERADMIN_SUPREMO tokens do not contain company_access claims.
mustChangePassword
boolean
true when the user is required to change their password before proceeding. Newly registered users always have this flag set.
companies
array
List of company/role pairs the user can access. Each entry contains:
  • companyId (UUID) — the tenant identifier
  • roleCode (string) — the role assigned in that tenant (e.g. OPERATOR, ADMIN)
Empty for SUPERADMIN_SUPREMO accounts.

Example

curl -s -X POST https://api.example.com/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "password": "Secure.Pass.2024!"
  }'
{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "userId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "email": "[email protected]",
  "fullName": "Warehouse Admin",
  "isSuperAdmin": false,
  "mustChangePassword": false,
  "companies": [
    {
      "companyId": "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed",
      "roleCode": "ADMIN"
    }
  ]
}

Error responses

StatusBody / messageKeyCause
400EMAIL_AND_PASSWORD_REQUIREDemail or password is missing or blank.
401USER_NOT_FOUNDNo auth.Users record matches the supplied email.
401INVALID_USERThe matched user record has no stored password hash (account not fully initialised).
401INVALID_PASSWORDThe password does not match the stored BCrypt hash.
401NO_ACTIVE_COMPANY_AVAILABLEisHandheld is true but the user has no active company assignment.
402plans.deviceLimitExceededThe tenant’s active device count exceeds the plan’s deviceLimit.
403auth.companyInactiveThe user’s tenant exists but IsActive = false or Status ≠ "Active".
403plans.deviceNotAuthorizedisHandheld is true but the device key is not pre-authorized for the tenant.
403plans.deviceInactiveThe device record exists but IsActive = false.
409auth.userAssignedToOtherTenantThe user record is linked to more than one tenant — data must be corrected by an admin.
503LOGIN_TEMPORARILY_UNAVAILABLEAn unexpected server error occurred during login. Retry with exponential back-off.

POST /api/auth/register

Self-service registration endpoint. Creates a new user (or assigns an existing user to a company) with the default OPERATOR role. Intended for handheld and warehouse operator onboarding.

Request body

email
string
required
The new user’s email address. Must satisfy the tenant’s UserEmailDomain restriction when one is configured (e.g. only @atp.com.py addresses accepted).
password
string
required
Plaintext password for the new account. Must satisfy the password policy (see below).
fullName
string
required
The user’s display name.
companyId
string (UUID)
The tenant to register the user in. When omitted, the first active company returned by /api/auth/registration-options is used.

Password policy

Passwords must meet all of the following requirements:
  • Minimum 8 characters
  • At least one uppercase letter
  • At least one lowercase letter
  • At least one digit
  • At least one special character (non-alphanumeric)

Error responses

StatusBody / messageKeyCause
400PASSWORD_POLICY_NOT_METThe supplied password does not satisfy all policy requirements.
400MISSING_REQUIRED_FIELDSOne or more of email, password, or fullName is blank.
409auth.userAlreadyExistsInTenantA user with this email is already assigned to the specified tenant.
409auth.userAssignedToOtherTenantThe email belongs to a user already assigned to a different tenant.

POST /api/auth/change-password

Changes the password for the currently authenticated user. Requires a valid Bearer token.
This endpoint only works for accounts with authProvider = DragonGuardLocal. Delegated handheld accounts authenticated through GrupoMAS receive 400 auth.externalPasswordManaged because password authority remains in the MAS system.

Request body

currentPassword
string
required
The user’s current plaintext password, used to re-verify identity before the change is applied.
newPassword
string
required
The desired new password. Must satisfy the same password policy as registration (min 8 chars, upper, lower, digit, special character).

Example

curl -s -X POST https://api.example.com/api/auth/change-password \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "currentPassword": "OldPassword.1!",
    "newPassword": "NewSecure.Pass.2024!"
  }'
{
  "message": "PASSWORD_CHANGED"
}

Error responses

StatusBody / messageKeyCause
400CURRENT_PASSWORD_INVALIDThe supplied currentPassword does not match the stored hash.
400PASSWORD_POLICY_NOT_METThe newPassword does not satisfy policy requirements.
400auth.externalPasswordManagedAccount uses GrupoMAS delegated auth; password is managed by MAS.
401INVALID_SESSIONThe token does not contain a valid userId or email claim.

GET /api/auth/registration-options

Returns the data needed to populate a self-registration form: the list of active companies available for selection and the default role code that will be assigned to new registrations.

Response

{
  "companies": [
    {
      "id": "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed",
      "code": "ATP",
      "name": "ATP Logistics S.A."
    }
  ],
  "defaultRoleCode": "OPERATOR"
}
This endpoint is public and does not require authentication.

GET /api/auth/test

Verifies that the caller’s JWT is valid and returns the key claims resolved from the token. Useful for debugging authentication issues and confirming which company context, role, and company access claims the server sees. Requires a valid Bearer token ([Authorize] — no specific role required).

Response

{
  "message": "OK",
  "userId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "companyId": "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed",
  "role": "ADMIN",
  "companies": ["1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed"],
  "companyRoles": ["1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed:ADMIN"]
}

Example

curl -s https://api.example.com/api/auth/test \
  -H "Authorization: Bearer <token>"

Error responses

StatusCause
401No token supplied or the token is invalid/expired.

Build docs developers (and LLMs) love