Skip to main content

Users API

Base path: /api/users

This section documents all endpoints for managing staff users (admins, sales, finance, agents). Authentication is cookie-based (JWT set as an httpOnly cookie at login). Access to each route is role-gated as noted below.

Roles & access

  • super-admin can view all users and create admins.
  • admin can manage non-admin staff. Creating or updating admin users is restricted to super-admin.
  • sales & finance have limited access (e.g., request password for clients via dedicated route below).

Company scoping: For non–super-admins, list & update operations are limited to users that share at least one company with the requester.


GET /api/users

List users. Results are scoped by the caller's allowed companies unless the caller is super-admin.

Query parameters

  • query (string, optional) — Filter by partial name match.
  • accessLevel ("admin" | "finance" | "sales" | "none", optional) — Exact role filter.
  • includeAdmins (boolean, optional) — When false (default for non–super-admins), admin & super-admin users are excluded.

Responses

  • 200 OK — Array of user objects.
  • 500 Internal Server Error

Example

curl -X GET 'https://api.example.com/api/users?query=ali&accessLevel=sales' \
--cookie "token=<JWT>"

GET /api/users/:id

Fetch a single user by id. Roles: admin (and super-admin).

Path params

  • id (number, required) — User ID.

Responses

  • 200 OK — User object with an allowedCompanies array of { companyId, userId } mappings.
  • 404 Not Found — User not found.
  • 500 Internal Server Error

Example

curl -X GET 'https://api.example.com/api/users/42' \
--cookie "token=<JWT>"

POST /api/users

Create a new staff user. Roles: admin (with restrictions below).

  • Only super-admin may create users with accessLevel = "admin".
  • On success, a password reset email is sent to the user's email with a one-time link.

Request body (JSON)

{
"name": "Jane Doe",
"email": "jane@example.com",
"phone": "+971555555555",
"accessLevel": "sales", // one of: admin | sales | finance | agent
"password": "optional-initial-password", // optional; defaults internally
"dateOfBirth": "1990-05-12", // optional, ISO date
"startDate": "2024-01-01", // optional, ISO date
"endDate": null, // optional, ISO date or null
"governmentIds": [ // optional; will be stored as JSON
{ "type": "EmiratesID", "number": "784-XXXX-XXXXXXX-X" }
],
"allowedCompanies": [1, 3, 9] // optional; company ids the user can access
}

Responses

  • 201 Created — Returns the created user identifier (e.g., { id: 123 }).
  • 400 Bad Request — Incorrect access level, or non–super-admin attempting to create an admin.
  • 500 Internal Server Error

Example

curl -X POST 'https://api.example.com/api/users' \
-H 'Content-Type: application/json' \
--cookie "token=<JWT>" \
-d '{
"name": "Jane Doe",
"email": "jane@example.com",
"accessLevel": "sales",
"allowedCompanies": [1,3]
}'

PUT /api/users/:id

Update a user. Roles: admin (and super-admin).

  • Any provided fields will be updated; omitted fields remain unchanged.
  • Providing password will reset the password (server will hash it).
  • Passing allowedCompanies replaces all existing company relations for the user.
  • If the requester is company-scoped, they can only assign companies they themselves are allowed to access.

Path params

  • id (number, required) — User ID.

Request body (partial JSON)

{
"name": "Updated Name",
"email": "updated@example.com",
"phone": "+971...",
"accessLevel": "finance", // must be one of: admin | sales | finance | agent
"password": "newPassword123", // optional
"dateOfBirth": "1990-05-12",
"startDate": "2024-01-01",
"endDate": null,
"governmentIds": [{ "type": "EID", "number": "..." }],
"allowedCompanies": [2,4]
}

Responses

  • 200 OK{ message: "user updated successfully" }
  • 400 Bad Request — No data to update, or invalid accessLevel.
  • 403 Forbidden — Attempt to assign companies outside caller's allowed companies.
  • 500 Internal Server Error

Example

curl -X PUT 'https://api.example.com/api/users/42' \
-H 'Content-Type: application/json' \
--cookie "token=<JWT>" \
-d '{ "accessLevel": "finance", "allowedCompanies": [2,4] }'

DELETE /api/users/:id

Delete a user. Auth required.

Path params

  • id (number, required) — User ID.

Responses

  • 200 OK{ message: "user deleted successfully" }
  • 500 Internal Server Error

Example

curl -X DELETE 'https://api.example.com/api/users/42' \
--cookie "token=<JWT>"

POST /api/users/requestPassword/:id

Send a password reset email for a client or staff user.

Roles: admin, super-admin, sales, finance.

Behavior

  • If :id belongs to a client and the client is active: a client-specific reset email is sent.
  • Otherwise, the endpoint targets a staff user by id and sends a staff reset email.
  • When called for a staff user by id, attempting to reset for disallowed roles is rejected.

Path params

  • id (number, required) — Target user (client or staff) id.

Alternate targeting by email

  • The service also accepts { "email": "..." } in the body for lookups when an id is not used in internal flows.

Request body (optional for email targeting)

{ "email": "person@example.com" }

Responses

  • 201 Created{ message: "Email has been successfully" }
  • 401 Unauthorized — Attempt to reset for a restricted staff role.
  • 500 Internal Server Error

Example (reset by id)

curl -X POST 'https://api.example.com/api/users/requestPassword/77' \
--cookie "token=<JWT>"

Example (reset by email)

curl -X POST 'https://api.example.com/api/users/requestPassword/0' \
-H 'Content-Type: application/json' \
--cookie "token=<JWT>" \
-d '{ "email": "client@example.com" }'

Data model (response shape)

User (abbreviated)

{
id: number;
name: string;
email: string;
phone?: string;
accessLevel: 'super-admin' | 'admin' | 'sales' | 'finance' | 'agent' | 'none';
// ...additional profile fields
}

AllowedCompany

{
userId: number;
companyId: number;
}

Errors

All endpoints return a JSON body with a message when an error occurs. Common statuses:

  • 400 — Validation or bad request.
  • 401 — Unauthorized (missing/invalid session) or disallowed operation for role.
  • 403 — Forbidden (company scoping violation).
  • 404 — Resource not found.
  • 500 — Server error.

Security

  • Authentication via secure, httpOnly cookie. Requires prior login.
  • Non–super-admin operations are scoped to the caller's allowed companies.
  • Admin-creation restricted to super-admin.
  • Passwords are never returned by the API.