Customers API¶
Enterprise feature
The REST API is available on Enterprise plans. Compare plans to find the right fit for your team.
The Customers API lets you create, retrieve, and update customer records and their service locations programmatically. Use it to sync your CRM, import customer data, or build custom dashboards.
Endpoints summary¶
| Method | Path | Scope | Description |
|---|---|---|---|
GET | /api/v1/customers | customers:read | List customers |
GET | /api/v1/customers?id={id} | customers:read | Get a single customer |
POST | /api/v1/customers | customers:write | Create a customer |
PUT | /api/v1/customers?id={id} | customers:write | Update a customer |
GET | /api/v1/customers?id={id}&locations=1 | customers:read | List customer locations |
POST | /api/v1/customers?id={id}&locations=1 | customers:write | Create a location |
PUT | /api/v1/customers?id={id}&locations=1&location_id={loc_id} | customers:write | Update a location |
Customer object¶
Every customer returned by the API contains these fields:
| Field | Type | Description |
|---|---|---|
customer_id | integer | Unique customer identifier |
customer_name | string | Customer or company name |
customer_email | string | Primary contact email |
customer_phone | string | Primary contact phone (E.164 format) |
default_sla_hours | integer | Default SLA response time in hours |
tax_exempt | boolean | Whether the customer is tax exempt |
tax_exemption_reason | string / null | Reason for tax exemption (max 255 characters) |
created_at | string | When the customer was created (ISO 8601) |
updated_at | string | When the customer was last updated (ISO 8601) |
List customers¶
GET /api/v1/customers
Returns a paginated list of customers.
Query parameters¶
| Parameter | Type | Description |
|---|---|---|
search | string | Search by customer name, email, or phone |
created_after | string | Filter customers created after this date (ISO 8601 format, e.g., 2026-01-15T00:00:00Z) |
created_before | string | Filter customers created before this date (ISO 8601 format) |
has_locations | string | Filter by location status: 1 to return only customers with locations, 0 for customers without |
page | integer | Page number (default: 1) |
per_page | integer | Results per page (default: 50, max: 100) |
Example request¶
Example response¶
{
"data": [
{
"customer_id": 201,
"customer_name": "Acme Corporation",
"customer_email": "[email protected]",
"customer_phone": "+15551234567",
"default_sla_hours": 24,
"tax_exempt": false,
"tax_exemption_reason": null,
"created_at": "2026-01-15T10:00:00Z",
"updated_at": "2026-02-20T08:30:00Z"
}
],
"pagination": {
"page": 1,
"per_page": 50,
"total": 1,
"total_pages": 1
},
"request_id": "a1b2c3d4e5f6"
}
Get a single customer¶
GET /api/v1/customers?id={id}
Retrieves full details for one customer. Add &include=locations to embed service locations in the response.
Example request¶
curl -X GET "https://fsmnavigator.com/api/v1/customers?id=201&include=locations" \
-H "X-API-Key: YOUR_API_KEY"
Example response¶
{
"data": {
"customer_id": 201,
"customer_name": "Acme Corporation",
"customer_email": "[email protected]",
"customer_phone": "+15551234567",
"default_sla_hours": 24,
"tax_exempt": false,
"tax_exemption_reason": null,
"created_at": "2026-01-15T10:00:00Z",
"updated_at": "2026-02-20T08:30:00Z"
},
"request_id": "a1b2c3d4e5f6"
}
Create a customer¶
POST /api/v1/customers
Creates a new customer record. Returns 201 Created on success. Locations are managed separately — see Customer locations below.
Request body¶
| Field | Type | Required | Description |
|---|---|---|---|
customer_name | string | Yes | Customer or company name |
customer_email | string | Yes | Primary contact email |
customer_phone | string | Yes | Primary contact phone (E.164 format recommended) |
default_sla_hours | integer | Yes | Default SLA response time in hours |
tax_exempt | boolean | No | Whether the customer is tax exempt (default: false) |
tax_exemption_reason | string | No | Reason for tax exemption (max 255 characters) |
Example request¶
curl -X POST "https://fsmnavigator.com/api/v1/customers" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"customer_name": "Riverside Medical Center",
"customer_email": "[email protected]",
"customer_phone": "+15559876543",
"default_sla_hours": 24,
"tax_exempt": false,
"tax_exemption_reason": null
}'
Example response¶
{
"success": true,
"message": "Customer created successfully",
"data": {
"customer_id": 202,
"customer_name": "Riverside Medical Center"
},
"request_id": "a1b2c3d4e5f6"
}
Update a customer¶
PUT /api/v1/customers?id={id}
Updates one or more fields on an existing customer record.
Example request¶
curl -X PUT "https://fsmnavigator.com/api/v1/customers?id=201" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"customer_email": "[email protected]"
}'
Example response¶
{
"success": true,
"message": "Customer updated successfully",
"data": {
"customer_id": 201,
"customer_name": "Acme Corporation"
},
"request_id": "a1b2c3d4e5f6"
}
Customer locations¶
Locations are managed as a sub-resource of a customer. Each customer can have multiple service locations, and each location is automatically geocoded when created or updated.
v1 API change (2026-05-27): Location response now includes
contact_email,contact_phone, andnotes. Fields default tonullwhen not populated server-side.Initial-create mirror (2026-05-27): When a customer is created with an inline
locationobject (POST /v1/customerswithlocationin the request body), the first location row now automatically mirrors the customer-levelcontact_emailandcontact_phoneinto the location's per-location contact fields. This ensures default-location billing and service notifications route through the customer's primary contact without a follow-upPATCH. Locations created via the separatePOST /v1/customers/{customer_id}/locationsendpoint (additional locations) do NOT auto-mirror — passcontact_email/contact_phoneexplicitly if you want a per-location override.
Location object¶
| Field | Type | Description |
|---|---|---|
location_id | integer | Unique location identifier |
location_name | string | Name for this location |
address_street | string | Street address |
address_city | string | City |
address_state | string | Two-letter state code |
address_zip | string | ZIP code (5 digits) |
latitude | number | Latitude (auto-geocoded) |
longitude | number | Longitude (auto-geocoded) |
is_primary | boolean | Whether this is the primary location |
created_at | string | When the location was created (ISO 8601) |
updated_at | string | When the location was last updated (ISO 8601) |
contact_email | string | Email for location-specific contact (optional, nullable) |
contact_phone | string | Phone for location-specific contact (optional, E.164 format recommended) |
notes | string | Internal notes about this location (optional, max ~2KB) |
List locations¶
GET /api/v1/customers?id={id}&locations=1
Returns a paginated list of locations for the specified customer.
Example request¶
curl -X GET "https://fsmnavigator.com/api/v1/customers?id=201&locations=1" \
-H "X-API-Key: YOUR_API_KEY"
Example response¶
{
"data": [
{
"location_id": 87,
"location_name": "Main Office",
"address_street": "123 Commerce Blvd",
"address_city": "Austin",
"address_state": "TX",
"address_zip": "78701",
"latitude": 30.2672,
"longitude": -97.7431,
"is_primary": true,
"created_at": "2026-01-15T10:00:00Z",
"updated_at": "2026-01-15T10:00:00Z",
"contact_email": "[email protected]",
"contact_phone": "+15558901234",
"notes": "Main office with 2 conference rooms"
}
],
"pagination": {
"page": 1,
"per_page": 50,
"total": 1,
"total_pages": 1
},
"request_id": "a1b2c3d4e5f6"
}
Create a location¶
POST /api/v1/customers?id={id}&locations=1
Creates a new service location for the specified customer. The address is automatically geocoded. Returns 201 Created on success.
Request body¶
| Field | Type | Required | Description |
|---|---|---|---|
location_name | string | Yes | Name for this location |
address_street | string | Yes | Street address |
address_city | string | Yes | City |
address_state | string | Yes | Two-letter state code (e.g., TX) |
address_zip | string | Yes | ZIP code (5 digits) |
contact_email | string | No | Email for location-specific contact |
contact_phone | string | No | Phone for location-specific contact (E.164 format recommended) |
notes | string | No | Internal notes about this location (max ~2KB) |
Example request¶
curl -X POST "https://fsmnavigator.com/api/v1/customers?id=201&locations=1" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"location_name": "East Wing",
"address_street": "456 Health Park Dr",
"address_city": "Dallas",
"address_state": "TX",
"address_zip": "75201"
}'
Example response¶
{
"success": true,
"message": "Location created successfully",
"data": {
"location_id": 88,
"location_name": "East Wing",
"address_street": "456 Health Park Dr",
"address_city": "Dallas",
"address_state": "TX",
"address_zip": "75201",
"latitude": 32.7767,
"longitude": -96.7970,
"contact_email": "[email protected]",
"contact_phone": "+15559876500",
"notes": "Dedicated HVAC maintenance area"
},
"request_id": "a1b2c3d4e5f6"
}
Update a location¶
PUT /api/v1/customers?id={id}&locations=1&location_id={loc_id}
Updates one or more fields on an existing service location. If the address changes, it is automatically re-geocoded.
Example request¶
curl -X PUT "https://fsmnavigator.com/api/v1/customers?id=201&locations=1&location_id=87" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"location_name": "Main Office - Renovated",
"address_street": "125 Commerce Blvd"
}'
Example response¶
{
"success": true,
"message": "Location updated successfully",
"data": {
"location_id": 87,
"location_name": "Main Office - Renovated",
"address_street": "125 Commerce Blvd",
"address_city": "Austin",
"address_state": "TX",
"address_zip": "78701",
"latitude": 30.2675,
"longitude": -97.7428,
"contact_email": "[email protected]",
"contact_phone": "+15558901234",
"notes": "Recently renovated reception area"
},
"request_id": "a1b2c3d4e5f6"
}
Error responses¶
See Error codes for the full reference. Common customer-specific errors:
| HTTP code | Error | Description |
|---|---|---|
400 | validation_failed | Missing required fields or invalid data |
404 | not_found | Customer or location ID does not exist |
400 | duplicate_customer | A customer with this email already exists |
Related guides¶
- Endpoints overview — all available endpoints
- Authentication — API key setup
- Jobs API — create jobs linked to customer locations
- Managing customers — web dashboard guide
- Bulk import — import customers via CSV