Skip to main content

Clients

Overview

Clients represent customers or general contractors for whom bids are created. Each bid must be associated with a client.

Endpoints

List Clients

GET /api/clients
Cookie: sAccessToken=...; sRefreshToken=...

Roles: ADMIN, ESTIMATOR, PM


Get Client

GET /api/clients/:id
Cookie: sAccessToken=...; sRefreshToken=...

Roles: ADMIN, ESTIMATOR, PM


Create Client

POST /api/clients
Cookie: sAccessToken=...; sRefreshToken=...
Content-Type: application/json

{
"name": "ABC Construction",
"email": "contact@abcconstruction.com"
}

Roles: ADMIN, ESTIMATOR

Required Fields:

  • name (string) - Client name
  • email (string, optional) - Contact email
warning

Client creation permissions can be restricted via Module Permissions. Check client permission before allowing creation.


Update Client

PUT /api/clients/:id
Cookie: sAccessToken=...; sRefreshToken=...
Content-Type: application/json

{
"name": "ABC Construction LLC",
"email": "info@abcconstruction.com"
}

Roles: ADMIN, ESTIMATOR


Delete Client

DELETE /api/clients/:id
Cookie: sAccessToken=...; sRefreshToken=...

Roles: ADMIN

warning

Deleting a client will cascade delete all associated bids and their data. This operation cannot be undone.

Data Model

interface Client {
id: string // UUID
name: string // Client name
email: string | null // Contact email (optional)
createdBy: string // User email who created
createdAt: DateTime // Creation timestamp
updatedAt: DateTime // Last update timestamp

// Relations
bids: Bid[] // Associated bids
}

Validation Rules

FieldRules
nameRequired, 1-200 characters
emailOptional, valid email format

Common Use Cases

Creating a New Client

const response = await fetch('/api/clients', {
method: 'POST',
credentials: 'include', // Sends session cookies
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'XYZ Developers',
email: 'pm@xyzdev.com'
})
});

const client = await response.json();
console.log('Created client:', client.id);

Listing Clients for Dropdown

const response = await fetch('/api/clients', {
credentials: 'include' // Sends session cookies
});

const clients = await response.json();

// Populate dropdown
const options = clients.map(c => ({
value: c.id,
label: c.name
}));

Error Responses

400 - Validation Error
{
"error": "Client name is required"
}
404 - Not Found
{
"error": "Client not found"
}
409 - Conflict
{
"error": "Client with this name already exists"
}