CHAPTER 02 OF 8
Find the customer and service address
Resolve the caller to the right customer and property before checking coverage or scheduling work.
1. Match an existing customer, or create one
Ask for the caller’s name and contact information. Search using a confirmed email, then verify the returned match. A search result is not identity verification: resolve ambiguous matches with the caller before reading private job details or changing records. The demo uses a unique synthetic email.
List results are paginated. Follow has_more with the documented limit and offset before concluding a customer does not exist. Persist the resulting ID in your call workflow so a reconnect does not create the customer again.
GET/field_service/customers
List customers
| Name | Location | Type / schema |
|---|---|---|
search | query | string |
status | query | string |
customer_id | query | string |
property_id | query | string |
job_id | query | string |
limit | query | integer |
offset | query | integer |
created_after | query | string |
created_before | query | string |
Documented responses: 200 401 403
POST/field_service/customers
Create customer
| Name | Location | Type / schema |
|---|---|---|
recordrequired | body | models.FieldServiceRecord |
Documented responses: 201 400 409
const email = 'alex@example.com'; // Confirmed with the caller.
let customer;
for (let offset = 0; ; offset += 100) {
const query = new URLSearchParams({ search: email, limit: '100', offset: String(offset) });
const result = await api('GET', '/customers?' + query);
customer = result.items.find(item => item.email === email);
if (customer || !result.has_more) break;
}
if (!customer) {
customer = await api('POST', '/customers', {
name: 'Alex Morgan', email, phone: '+12025550142', status: 'active',
});
}JavaScript · server side2. Save only the confirmed changes
A customer record carries a version. Send the current version when patching it and replace your saved copy with the response. A stale update returns a conflict; reload, reconcile the change, and ask again if the caller’s intended outcome has changed.
Use a separate call note for new instructions when you should preserve existing notes. This example updates the synthetic customer’s note field deliberately.
PATCH/field_service/customers/{id}
Update customer (PATCH)
| Name | Location | Type / schema |
|---|---|---|
idrequired | path | string |
recordrequired | body | models.FieldServiceRecord |
Documented responses: 200 400 409
customer = await api('PATCH', '/customers/' + customer.id, {
version: customer.version,
notes: 'Caller confirmed the best callback time is after 3 pm.',
});JavaScript · server side3. Confirm the service location
List the customer’s locations and confirm which property needs service. Do not assume the first address is the right one. If the address is new, create it under that customer. The returned location’s id becomes property_id in downstream requests.
The caller can now hear an address confirmation before you check whether the business serves the property.
GET/field_service/locations
List tenant service locations
| Name | Location | Type / schema |
|---|---|---|
customer_id | query | string |
property_id | query | string |
location_id | query | string |
address | query | string |
postal_code | query | string |
limit | query | integer |
offset | query | integer |
Documented responses: 200 400 401 403 500
POST/field_service/locations
Create a customer service location
| Name | Location | Type / schema |
|---|---|---|
locationrequired | body | models.FieldServiceLocation |
Documented responses: 201 400 401 403 404 409 500
const locations = await api('GET', '/locations?' + new URLSearchParams({
customer_id: customer.id,
}));
// Review existing locations with the caller first. If this is a new address:
const location = await api('POST', '/locations', {
customer_id: customer.id,
name: 'Home', address: '123 Demo Lane', city: 'Madison',
region: 'WI', postal_code: '53703', country: 'US',
});JavaScript · server side