Clients | FieldCamp API
Use the FieldCamp Clients API to create, search, update, soft-delete, and sync the people and companies you do work for.
The FieldCamp Clients API is how your integration creates and maintains the people or companies you do work for. Every job, estimate, invoice, and visit eventually references a client, so most integrations create a client once on first contact and then reuse the same client ID on every follow-up. With release_v2, the resource is available under the versioned path /api/v1/clients, which adds server-side search, stage, and since filters, a soft-delete endpoint, and geocoded address fields.
What changed in release_v2
The /api/v1/clients namespace is now the recommended path for new integrations. The legacy /api/clients endpoints still exist for backward compatibility, but they do not expose the new filters or the geocoded address fields, and we strongly recommend migrating.
- Versioned base path:
/api/v1/clients(instead of/api/clients). - Server-side filters on the list endpoint:
search,stage, andsince. - New
DELETE /api/v1/clients/{id}soft-delete endpoint that hides the client from the UI without losing history. - Geocoded address fields on every client:
latitude,longitude, andplusCode, populated automatically when an address is provided. - Consistent stage vocabulary aligned with client categories and stages used in the FieldCamp UI.
If you previously built your own deduplication loop on top of GET /api/clients, you can now collapse it into a single GET /api/v1/clients?search=jane@acme.com call. See Idempotency for safe-retry patterns.
Fields worth knowing
emailis still the de-facto lookup key. Always store it. Withrelease_v2you can pass it to thesearchquery parameter instead of paginating client-side.phoneNumberis structured —{ countryCode, number, countryIdentifier }. See the PhoneNumber block in theNewClientschema rendered below.billingAddressandpropertyAddressare independent. Pass the sameAddressobject to both if they are identical; do not skipbillingAddress.stageis free-text but commonly one ofLead,Active Client, orInactive. Thestagequery parameter on the list endpoint matches the same vocabulary you configure in the sales pipeline.latitude/longitude/plusCodeare returned read-only on every client whose address could be geocoded. They are the same coordinates the dispatcher uses for route optimization and AI dispatching.
Authentication
All requests to /api/v1/clients require a valid fc_live key passed via the X-Api-Key header with appropriate scopes — see Authentication for setup, and API key management to create and rotate keys per integration.
Filtering and search
GET /api/v1/clients accepts the following query parameters:
search— free-text match against client name, email, and phone number. Case-insensitive, partial-match.stage— exact match against the client's stage field (for exampleLead,Active Client,Inactive).since— ISO 8601 timestamp. Returns clients whoseupdatedAtis greater than or equal to the supplied value. Ideal for delta syncs.limitandcursor— standard pagination parameters used across the API.
Use since for nightly syncs into your data warehouse. Keep the highest updatedAt you have seen and pass it back on the next run — you only pull the records that actually changed. The same pattern powers the calendar and accounting sync API.
Example: find by email
curl https://api.fieldcamp.ai/api/v1/clients?search=jane@acme.com \
-H "Authorization: Bearer $FIELDCAMP_API_KEY"Example: pull leads only
curl "https://api.fieldcamp.ai/api/v1/clients?stage=Lead&limit=100" \
-H "Authorization: Bearer $FIELDCAMP_API_KEY"Example: incremental sync
curl "https://api.fieldcamp.ai/api/v1/clients?since=2026-05-01T00:00:00Z" \
-H "Authorization: Bearer $FIELDCAMP_API_KEY"If you exceed the per-minute request budget, you will receive an HTTP 429 with throttling headers — see Rate limits for the sliding-window details and back-off guidance.
Soft delete
DELETE /api/v1/clients/{id} performs a soft delete. The client is hidden from the FieldCamp UI and excluded from default list responses, but their historical jobs, invoices, and payments remain intact. This mirrors the in-app delete or archive a client flow.
Soft-deleted clients are excluded from GET /api/v1/clients by default. If you maintain a mirror of the table in your own system, listen for the client.deleted webhook so you can mark the row inactive on your side too. See Webhooks and the webhook events catalog for payload shapes.
To restore a soft-deleted client, update the record through PUT /api/v1/clients/{id} — the endpoint accepts updates against archived records and clears the deleted flag on success.
Creating clients safely
Search first
Call GET /api/v1/clients?search=<email> before creating. If you get a hit, reuse the existing client ID.
Send an Idempotency-Key
Pass a unique Idempotency-Key header on POST /api/v1/clients so retries do not create duplicates. See Idempotency.
Always include billingAddress
Even if the billing and property addresses are identical, post the same Address object to both. Missing billingAddress will fail validation.
Trust the geocode
The response will include latitude, longitude, and plusCode if the address could be resolved. Store them — they drive route optimization for the jobs you create later.
If you are wiring this in for the first time, the API quickstart walks through the full flow from issuing an fc_live key to scheduling a job.
Endpoints
/api/v1/clientsPass your JWT API key as Authorization: Bearer <token>. Send
alongside X-API-Key: <token> for maximum compatibility.
In: header
Response Body
application/json
application/json
application/json
curl -X GET "https://api.fieldcamp.ai/api/v1/clients"{
"success": true,
"data": {
"clients": [
{
"firstName": "Jane",
"lastName": "Cooper",
"email": "jane@example.com",
"phoneNumber": {
"countryCode": "+44",
"number": "7555123456",
"countryIdentifier": "gb"
},
"companyName": "Acme Moving Co.",
"companyAddress": {
"street": "221B Baker Street",
"houseNumber": "",
"city": "London",
"state": "England",
"country": "United Kingdom",
"zipCode": "NW1 6XE",
"formattedAddress": "221B Baker Street, London, England, NW1 6XE, United Kingdom",
"latitude": 51.5237,
"longitude": -0.1585,
"plusCode": ""
},
"propertyAddress": {
"street": "221B Baker Street",
"houseNumber": "",
"city": "London",
"state": "England",
"country": "United Kingdom",
"zipCode": "NW1 6XE",
"formattedAddress": "221B Baker Street, London, England, NW1 6XE, United Kingdom",
"latitude": 51.5237,
"longitude": -0.1585,
"plusCode": ""
},
"billingAddress": {
"street": "221B Baker Street",
"houseNumber": "",
"city": "London",
"state": "England",
"country": "United Kingdom",
"zipCode": "NW1 6XE",
"formattedAddress": "221B Baker Street, London, England, NW1 6XE, United Kingdom",
"latitude": 51.5237,
"longitude": -0.1585,
"plusCode": ""
},
"stage": "Active Client",
"properties": [
"string"
],
"jobFormIds": [
"string"
],
"id": "string",
"recordId": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z"
}
]
}
}{
"success": false,
"error": "Invalid or expired token"
}{
"success": false,
"error": "Internal server error"
}/api/v1/clientsPass your JWT API key as Authorization: Bearer <token>. Send
alongside X-API-Key: <token> for maximum compatibility.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
curl -X POST "https://api.fieldcamp.ai/api/v1/clients" \ -H "Content-Type: application/json" \ -d '{ "firstName": "Jane", "lastName": "Cooper", "email": "jane@example.com", "phoneNumber": { "countryCode": "+1", "number": "5550101234", "countryIdentifier": "us" }, "companyName": "Acme Moving Co.", "propertyAddress": { "street": "500 Example Ave", "city": "Springfield", "state": "IL", "country": "United States", "zipCode": "62701" }, "billingAddress": { "street": "500 Example Ave", "city": "Springfield", "state": "IL", "country": "United States", "zipCode": "62701" }, "stage": "Active Client", "properties": [], "jobFormIds": [] }'{
"success": true,
"data": {
"client": {
"firstName": "Jane",
"lastName": "Cooper",
"email": "jane@example.com",
"phoneNumber": {
"countryCode": "+44",
"number": "7555123456",
"countryIdentifier": "gb"
},
"companyName": "Acme Moving Co.",
"companyAddress": {
"street": "221B Baker Street",
"houseNumber": "",
"city": "London",
"state": "England",
"country": "United Kingdom",
"zipCode": "NW1 6XE",
"formattedAddress": "221B Baker Street, London, England, NW1 6XE, United Kingdom",
"latitude": 51.5237,
"longitude": -0.1585,
"plusCode": ""
},
"propertyAddress": {
"street": "221B Baker Street",
"houseNumber": "",
"city": "London",
"state": "England",
"country": "United Kingdom",
"zipCode": "NW1 6XE",
"formattedAddress": "221B Baker Street, London, England, NW1 6XE, United Kingdom",
"latitude": 51.5237,
"longitude": -0.1585,
"plusCode": ""
},
"billingAddress": {
"street": "221B Baker Street",
"houseNumber": "",
"city": "London",
"state": "England",
"country": "United Kingdom",
"zipCode": "NW1 6XE",
"formattedAddress": "221B Baker Street, London, England, NW1 6XE, United Kingdom",
"latitude": 51.5237,
"longitude": -0.1585,
"plusCode": ""
},
"stage": "Active Client",
"properties": [
"string"
],
"jobFormIds": [
"string"
],
"id": "string",
"recordId": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z"
}
}
}{
"success": false,
"error": "jobNumber is required"
}{
"success": false,
"error": "Invalid or expired token"
}{
"success": false,
"error": "Internal server error"
}/api/v1/clients/{id}Pass your JWT API key as Authorization: Bearer <token>. Send
alongside X-API-Key: <token> for maximum compatibility.
In: header
Path Parameters
Response Body
application/json
application/json
curl -X GET "https://api.fieldcamp.ai/api/v1/clients/string"{
"success": true,
"data": {
"client": {
"firstName": "Jane",
"lastName": "Cooper",
"email": "jane@example.com",
"phoneNumber": {
"countryCode": "+44",
"number": "7555123456",
"countryIdentifier": "gb"
},
"companyName": "Acme Moving Co.",
"companyAddress": {
"street": "221B Baker Street",
"houseNumber": "",
"city": "London",
"state": "England",
"country": "United Kingdom",
"zipCode": "NW1 6XE",
"formattedAddress": "221B Baker Street, London, England, NW1 6XE, United Kingdom",
"latitude": 51.5237,
"longitude": -0.1585,
"plusCode": ""
},
"propertyAddress": {
"street": "221B Baker Street",
"houseNumber": "",
"city": "London",
"state": "England",
"country": "United Kingdom",
"zipCode": "NW1 6XE",
"formattedAddress": "221B Baker Street, London, England, NW1 6XE, United Kingdom",
"latitude": 51.5237,
"longitude": -0.1585,
"plusCode": ""
},
"billingAddress": {
"street": "221B Baker Street",
"houseNumber": "",
"city": "London",
"state": "England",
"country": "United Kingdom",
"zipCode": "NW1 6XE",
"formattedAddress": "221B Baker Street, London, England, NW1 6XE, United Kingdom",
"latitude": 51.5237,
"longitude": -0.1585,
"plusCode": ""
},
"stage": "Active Client",
"properties": [
"string"
],
"jobFormIds": [
"string"
],
"id": "string",
"recordId": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z"
}
}
}{
"success": false,
"error": "Invalid or expired token"
}/api/v1/clients/{id}Pass your JWT API key as Authorization: Bearer <token>. Send
alongside X-API-Key: <token> for maximum compatibility.
In: header
Path Parameters
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
curl -X PUT "https://api.fieldcamp.ai/api/v1/clients/string" \ -H "Content-Type: application/json" \ -d '{ "stage": "Active Client", "properties": [ "string" ], "jobFormIds": [ "string" ] }'{
"success": true,
"data": {
"client": {
"firstName": "Jane",
"lastName": "Cooper",
"email": "jane@example.com",
"phoneNumber": {
"countryCode": "+44",
"number": "7555123456",
"countryIdentifier": "gb"
},
"companyName": "Acme Moving Co.",
"companyAddress": {
"street": "221B Baker Street",
"houseNumber": "",
"city": "London",
"state": "England",
"country": "United Kingdom",
"zipCode": "NW1 6XE",
"formattedAddress": "221B Baker Street, London, England, NW1 6XE, United Kingdom",
"latitude": 51.5237,
"longitude": -0.1585,
"plusCode": ""
},
"propertyAddress": {
"street": "221B Baker Street",
"houseNumber": "",
"city": "London",
"state": "England",
"country": "United Kingdom",
"zipCode": "NW1 6XE",
"formattedAddress": "221B Baker Street, London, England, NW1 6XE, United Kingdom",
"latitude": 51.5237,
"longitude": -0.1585,
"plusCode": ""
},
"billingAddress": {
"street": "221B Baker Street",
"houseNumber": "",
"city": "London",
"state": "England",
"country": "United Kingdom",
"zipCode": "NW1 6XE",
"formattedAddress": "221B Baker Street, London, England, NW1 6XE, United Kingdom",
"latitude": 51.5237,
"longitude": -0.1585,
"plusCode": ""
},
"stage": "Active Client",
"properties": [
"string"
],
"jobFormIds": [
"string"
],
"id": "string",
"recordId": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z"
}
}
}{
"success": false,
"error": "Invalid or expired token"
}/api/v1/clients/{id}Pass your JWT API key as Authorization: Bearer <token>. Send
alongside X-API-Key: <token> for maximum compatibility.
In: header
Path Parameters
Response Body
application/json
curl -X DELETE "https://api.fieldcamp.ai/api/v1/clients/string"{
"success": false,
"error": "Invalid or expired token"
}Troubleshooting
search returns no rows but the client clearly exists.
The search filter excludes soft-deleted clients by default. Try the same call without search and look for the record; if you find it via direct GET /api/v1/clients/{id}, it has likely been archived through the client detail page actions menu.
Geocode fields are missing on a freshly created client.
Geocoding runs asynchronously. The POST response returns the record before the geocode resolves. Re-fetch the client a few seconds later, or subscribe to the client.updated webhook and wait for latitude and longitude to populate.
stage filter returns nothing.
The match is exact and case-sensitive on the canonical value. Confirm the stage string you are passing matches the value configured in your pipeline — see client categories and stages for the defaults.
I am getting 4xx responses I do not expect. Check the response envelope and HTTP status against the errors and retries reference before adding new logic — most transient failures have a documented retry pattern.
I am still hitting the old /api/clients paths.
The legacy paths are kept for backward compatibility and will continue to work, but they do not return geocoded fields and do not accept search, stage, or since. Migrate to /api/v1/clients to unlock those features and to keep up with future schema additions documented in the changelog.
FAQs
Can I hard-delete a client?
No. DELETE /api/v1/clients/{id} is always a soft delete. This is intentional — clients are referenced by historical jobs and invoices, and hard deletion would break those records.
Is there a bulk import endpoint?
Not yet. For initial migrations, use the in-app CSV import for very large lists, or loop POST /api/v1/clients with an Idempotency-Key per row for smaller batches.
How do I model leads versus active customers?
Set the stage field. The same vocabulary powers the sales pipeline kanban board so your CRM stays consistent across API and UI.
Why is the email field still optional?
Some field-service customers (especially walk-in or referral work) only have a phone number. Email remains optional, but if you have it, send it — search uses it as the primary match key.
How do I keep my CRM in sync without polling every minute?
Combine the since filter for delta pulls with webhooks for real-time client.created, client.updated, and client.deleted events.
Related articles
- API quickstart
- Authentication
- Idempotency
- Rate limits
- Errors and retries
- Webhooks
- Webhook events catalog
- API changelog
- Jobs API
- Invoices API
- Client categories and stages
- Delete or archive a client
- Client detail page actions menu
- Import clients into FieldCamp
- Route optimization
- How AI Dispatcher works
- Sales pipeline kanban board
FieldCamp Webhook Events Catalog: 20 Event Types and Payloads
Reference for every FieldCamp webhook event, including sample payloads, required scopes, and tips for building reliable webhook receivers.
Jobs | FieldCamp API
Reference for the FieldCamp Jobs API — create, schedule, filter, and update field service jobs with JSON requests on the v1 endpoints.