Skip to main content

Clients API

Base URL: /api/clients

This section documents the endpoints for managing clients/leads and their assignments. All routes require authentication. Role-based access is enforced per endpoint.

Auth model: Cookie-based session (JWT under the hood). Send your authenticated cookie with each request.


Authorization matrix

EndpointMethodRoles
/api/clientsGETadmin, sales, finance
/api/clients/:idGETadmin, sales, finance, agent
/api/clients/userClients/:idGETadmin, sales, finance
/api/clientsPOSTadmin, sales, finance
/api/clients/:idPUTadmin, sales, finance
/api/clients/:idDELETEadmin, sales, finance
/api/clients/:id/change-passwordPOSTadmin, sales, finance
/api/clients/passport/:idPOST (multipart)admin, sales, finance

Data models

Client

{
"id": 123,
"name": "Jane Doe",
"email": "jane@example.com",
"phone": "+971500000000",
"address": "Dubai, UAE",
"isActive": true,
"createdBy": 12,
"createdAt": "2025-01-02T10:15:36.000Z",
"updatedAt": "2025-01-15T08:01:10.000Z",
"company": "Acme Properties", // company name
"hasJoined": true, // whether the client has set a password
"agents": [
{ "agentId": 42, "agentName": "Ahmed Ali" }
]
}

Pagination envelope

  • Default page size: 10
  • Query param: page (1-based index)

Common list response shape:

{
"leads": [ /* Client[] */ ],
"totalPages": 5
}

Some endpoints return clients instead of leads for the array key (see each endpoint).


GET /api/clients

List clients with optional filters and pagination.

Query parameters

  • query (string, optional) — search by name, email, or phone (contains).
  • category (string, optional) — one of: active, not_active.
  • page (number, optional) — 1-based page index; when omitted, returns the full list.
  • company (number, optional) — filter by company id. If omitted and the caller is not super-admin, results are limited to the caller’s allowed companies.

Response

200 OK

{
"leads": [Client, ...],
"totalPages": 3
}

cURL

curl -X GET "https://your.api/api/clients?query=jane&category=active&page=1" \
-H "Cookie: token=..."

GET /api/clients/:id

Get a single client by id.

Path parameters

  • id (number, required) — client id.

Response

200 OK

{
"leads": Client
}

Note: the top-level key is leads by implementation.

404 Not Found — when the client does not exist.

cURL

curl -X GET "https://your.api/api/clients/123" -H "Cookie: token=..."

GET /api/clients/userClients/:id

List clients assigned to a specific agent.

Path parameters

  • id (number, required) — agent (user) id.

Query parameters

  • page (number, optional) — 1-based page index.

Response

200 OK

{
"clients": [Client, ...],
"totalPages": 2
}

cURL

curl -X GET "https://your.api/api/clients/userClients/42?page=1" \
-H "Cookie: token=..."

POST /api/clients

Create a new client/lead and (optionally) assign one or more agents.

Request body

{
"name": "Jane Doe",
"email": "jane@example.com",
"phone": "+971500000000",
"address": "Dubai, UAE",
"source": "referral", // optional
"agents": [ // optional; one or many
{ "agentId": 42, "agentName": "Ahmed Ali" }
],
"isActive": true,
"company": 7 // numeric company id (required)
}

Responses

  • 201 Created{ "message": "LeadClient created successfully" }
  • 400 Bad Request — e.g., duplicate email { "message": "Lead with this email already exists" }

cURL

curl -X POST "https://your.api/api/clients" \
-H "Content-Type: application/json" \
-H "Cookie: token=..." \
-d '{
"name": "Jane Doe",
"email": "jane@example.com",
"phone": "+971500000000",
"address": "Dubai, UAE",
"company": 7,
"agents": [{"agentId":42,"agentName":"Ahmed Ali"}],
"isActive": true
}'

PUT /api/clients/:id

Update client fields and/or reassign agents.

Path parameters

  • id (number, required) — client id.

Request body

Any updatable subset of:

{
"name": "Jane Doe",
"email": "jane@example.com",
"phone": "+971500000000",
"address": "Dubai, UAE",
"source": "referral",
"agents": [ { "agentId": 42, "agentName": "Ahmed Ali" } ],
"isActive": true
}

Notes:

  • When agents is provided, existing assignments are replaced with the provided list.

Responses

  • 200 OK{ "message": "LeadClient updated successfully" }
  • 404 Not Found — if the client id does not exist.

cURL

curl -X PUT "https://your.api/api/clients/123" \
-H "Content-Type: application/json" -H "Cookie: token=..." \
-d '{"phone":"+971511111111","agents":[{"agentId":42,"agentName":"Ahmed Ali"}]}'

DELETE /api/clients/:id

Soft-disable a client (sets isActive to false).

Path parameters

  • id (number, required) — client id.

Response

200 OK

{ "message": "Lead disabled successfully" }

cURL

curl -X DELETE "https://your.api/api/clients/123" -H "Cookie: token=..."

POST /api/clients/:id/change-password

Set or change a client’s password (admin-side action).

Path parameters

  • id (number, required) — client id.

Request body

{ "password": "NewStrongPassword!" }

Response

200 OK

{ "message": "Password changed successfully" }

cURL

curl -X POST "https://your.api/api/clients/123/change-password" \
-H "Content-Type: application/json" -H "Cookie: token=..." \
-d '{"password":"NewStrongPassword!"}'

POST /api/clients/passport/:id

Upload or replace a client’s passport document (admin-side upload).

Path parameters

  • id (number, required) — client id.

Request

Content-Type: multipart/form-data

  • Field name: passport
  • File: image/PDF/etc.

Response

200 OK

{
"message": "Passport uploaded successfully",
"path": "https://.../path/to/passport.pdf"
}

cURL

curl -X POST "https://your.api/api/clients/passport/123" \
-H "Cookie: token=..." \
-F "passport=@/path/to/passport.pdf"

Errors

The API uses standard HTTP status codes. Common error shapes:

{ "message": "Invalid company ID" }
{ "message": "Error updating leadClient" }
  • 400 Bad Request — malformed or invalid parameters.
  • 401 Unauthorized — missing/invalid session.
  • 403 Forbidden — authenticated but lacks the required role.
  • 404 Not Found — resource doesn’t exist.
  • 500 Internal Server Error — unexpected server error.

Notes & constraints

  • Page size is fixed at 10 items when page is used.
  • When company is not specified and the caller is not super-admin, results are limited to the caller’s allowed companies.
  • The hasJoined flag indicates whether a client has created a password (joined the portal).
  • File uploads overwrite the previously stored passport; the previous file is removed server-side.