Skip to main content

Create a customer location

POSThttps://api.fieldtask.example/public/v1/customers/{customer_id}/locations
Permissions
customer_locations:create, customer_locations:read, customers:read
Safe retries
Idempotency-Key

Creates one service location for an existing customer: a named address where your team works, with an optional map position and geofence radius.

Locations belong to a customer. You can then attach a location to a job with location_id in Create a job.

This endpoint only creates. It never matches or updates an existing location. If you send the same body twice without the same Idempotency-Key, you get two locations with the same name and address. See Idempotency and safe retries.

Preview

This page is generated from contract 2026-11-03-review.2, a review export that hasn't been released. Looking up coordinates from the address works only where FieldTask has enabled it.

Before you start​

You need:

  1. API access for your organization. An owner or admin requests it in Settings → API connections. Until FieldTask enables it, every request returns 403 api_access_not_enabled.
  2. A REST credential with the permissions below: an API token created in Settings → API connections, or an access token from an OAuth client-credentials connection. Tokens from an MCP sign-in don't work with the REST API.
  3. The ID of an existing customer, for the customer_id in the URL. Find it with GET /public/v1/customers, or create the customer first with POST /public/v1/customers. Archived customers can be used; deleted customers can't.
  4. A check that the location doesn't already exist. List the customer's locations with GET /public/v1/customers/{customer_id}/locations and compare names and addresses. Locations don't accept an external_reference, so this is the only way to find one again.

Permissions​

Every request needs all of these permissions:

PermissionDependency in the permission map
customer_locations:createDepends on customer_locations:read, customers:read
customer_locations:readDepends on customers:read
customers:readNo dependencies

No field needs an additional permission.

Adding a permission to a connection doesn't happen automatically. An owner or admin edits it in Settings → API connections. API tokens keep the same token string when their permissions change. OAuth integrations must also request the new scope when they get an access token.

Request​

Responses​

Created

Response Headers
    Cache-Control

    Responses must not be cached.

    Idempotency-Key

    The operation key used for this create, including a server-generated key when omitted.

    Idempotency-Replayed
    Location
    Operation-Location
    X-Request-ID

    Server-generated request correlation ID.

Field guide​

The customer comes from the URL: POST /public/v1/customers/{customer_id}/locations. It must be a customer in your organization that hasn't been deleted; archived customers are accepted. An ID that doesn't match such a customer is rejected with 422 validation_failed, not 404.

The request body is a single JSON object. name and address are required.

FieldRequiredWhat to send
nameYesA label for the location, such as Main office. At most 256 characters; spaces at either end are removed and what remains can't be empty. Control characters, including tabs and line breaks, aren't allowed.
addressYesThe full street address, with the same length and character rules as name. It's saved as sent, apart from removing spaces at either end, and it's what FieldTask uses to look up coordinates.
latitudeNoA number from -90 to 90. Send it together with longitude, and only when you already know the position. See Coordinates.
longitudeNoA number from -180 to 180. Send it together with latitude.
radiusNoThe geofence radius around the location, in metres, as a whole number from 1 to 2,147,483,647. Defaults to 100. It's always metres, whatever distance unit your organization displays. null and numbers with a decimal point, such as 100.0, are rejected.

Anything else in the body is rejected with 422 validation_failed. That includes customer_id, is_default and external_reference: locations don't accept an external reference.

Body and header rules​

  • Send Content-Type: application/json with an uncompressed body. A Content-Encoding header is rejected with 415.
  • The body can be at most 256 KiB and nest at most 10 levels deep.
  • Duplicate property names, NaN and Infinity are rejected with 400 invalid_json.
  • The URL must have no query string.

Coordinates​

You have two options:

  • You know the position. Send latitude and longitude together. They're saved immediately and FieldTask doesn't look anything up. Sending only one of them, or null for either, is rejected with 422.
  • You don't. Leave both out. The location is saved with latitude and longitude set to null, and FieldTask looks up the address after the request, as follow-up work. Never guess or derive coordinates yourself just to fill the fields.

The lookup only fills in latitude and longitude. It never changes the address, name, radius or default location. It runs only where FieldTask has enabled it; elsewhere the coordinates stay null.

The 201 response is a snapshot from the moment of creation, so it shows null coordinates even if the lookup finishes a moment later. So does a replay with the same key. To see the coordinates, wait until the operation is no longer pending (see What happens after the location is saved), then read the location with GET /public/v1/customer-locations/{resource_id}.

The default location​

Each customer has one default location.

  • The customer's first location becomes the default. Deleted locations don't count. The response has "is_default": true.
  • Every later location is created with "is_default": false, and the existing default doesn't change. The API can't change which location is the default.
  • If the customer already has locations but none of them is the default, which can happen with older data, the request is rejected with 422 validation_failed. Make one of the customer's locations the default in FieldTask, then retry with the same key.

The customer's primary address​

A customer's primary_address is a single address shown on the customer record. Locations don't change it, with one exception: the customer's first location.

When you createAnd the customer's primary_address isResult
The customer's first locationnull or emptyIt's set to this location's address.
The customer's first locationAlready this addressNothing changes.
The customer's first locationA different addressIt stays as it is. The operation reports a blocked target with reconciliation_required. The location is still created.
Any later locationAnythingNothing changes.

Customers created through the API start with no primary address, so their first location sets it unless someone has added one in FieldTask in the meantime.

Idempotency and safe retries​

Send an Idempotency-Key header with a new value, such as a UUID, for every new location, and save it with your own record before sending. If you get no response, a timeout or a 5xx, send the same body to the same URL with the same key again, with backoff.

SituationResult
New keyThe location is created. Response 201, Idempotency-Replayed: false.
Same key, same customer, same body, within 7 daysThe original response is returned again. No second location is created and it isn't counted against your daily create allowance. Response 201, Idempotency-Replayed: true.
Same key, different body or a different customer_id409 idempotency_key_reused. Nothing is created. The customer in the URL is part of the request.
Same key while the first request is still running409 operation_in_progress with Retry-After. Retry with the same key and body.
Same key more than 7 days later409 idempotency_window_expired. A key can never be reused for a different location.
Same key, but the location or its customer was deleted since410 resource_gone. Don't create it again automatically.

"Same body" means the same JSON value: leaving radius out is different from sending "radius": 100, even though the result is the same.

Keys are 16–128 printable ASCII characters and are scoped to the organization, the connection and the kind of request. Without a key, the server generates one and returns it in the Idempotency-Key response header, which only helps if you receive the response. For the full rules, see Idempotency and recovery.

What happens after the location is saved​

A 201 response means the location is saved in FieldTask, together with any change to the customer's primary address. Nothing further is needed for it to exist, and later follow-up work never removes it. No external system is contacted during the request.

Follow-up work is reported on the operation, not on the location. Read the Operation-Location URL from the 201 response with the same credential (needs customer_locations:read and customers:read):

curl "$FIELDTASK_API_ORIGIN/public/v1/operations/OPERATION_ID" \
--header "Authorization: Bearer $FIELDTASK_API_TOKEN"

While FieldTask is looking up coordinates, the operation looks like this:

{
"data": {
"id": "88888888-8888-4888-8888-888888888821",
"command": "customer_location.create",
"local_status": "committed",
"created_at": "2026-11-03T14:01:05.732Z",
"result_expires_at": "2026-11-10T14:01:05.732Z",
"http_status": 201,
"resource": { "type": "customer_locations", "id": "22222222-2222-4222-8222-222222222222" },
"integration": {
"status": "pending",
"updated_at": "2026-11-03T14:01:05.732Z",
"targets": [
{ "id": "99999999-9999-4999-8999-999999999931", "status": "pending", "error_code": null }
]
}
}
}

A location create can have up to three kinds of follow-up work, each reported as one entry in integration.targets:

Follow-up workWhen it's addedWhat the target reports
Coordinate lookupYou left out latitude and longitude.pending while queued, including automatic retries after temporary lookup failures. succeeded once the coordinates are saved. blocked with configuration_required where FieldTask hasn't enabled the lookup. failed with invalid_upstream_data if the address couldn't be resolved. blocked with reconciliation_required if the location was edited or deleted before the lookup finished; FieldTask never overwrites a newer change.
Primary address conflictThis is the customer's first location and the customer already had a different primary address.blocked with reconciliation_required. Nothing is done automatically.
External synchronization of the customer's addressThis location set the customer's primary address and your organization has external customer synchronization turned on.blocked with configuration_required. See the note below.

When there's no follow-up work, integration.status is not_applicable. Targets don't say which kind of work they are; when there's more than one, use each target's status and error_code. See Get an operation for how target statuses combine into integration.status.

Pending confirmation

In the review contract, primary-address changes made through the API aren't sent to a connected CRM. If your organization has external customer synchronization turned on, the operation reports a blocked target with configuration_required. The location and the customer's primary address are still saved.

If the coordinate lookup fails or is blocked, the location keeps null coordinates. The public API can't update a location, so correct it in FieldTask, or create future locations with known coordinates.

Operation results are kept for seven days. After that, GET /public/v1/operations/{id} returns 410 operation_result_expired. That doesn't mean the location wasn't created.

Recovering from failures​

What happenedWhat to do
Timeout, connection error or 5xxRetry the same body to the same URL with the same key, with exponential backoff.
409 operation_in_progress or 429Wait for Retry-After seconds and retry with the same key.
201 receivedStore data.id and the Location and Operation-Location headers. Stop retrying.
Key older than 7 days, or the result expiredDon't create again yet. List the customer's locations and look for the name and address you sent.

Never switch to a new key just because a response was lost. A new key means a new location.

Errors​

Errors use application/problem+json. The top-level code is the stable machine-readable value; error adds a readable message, a suggested fix and a documentation link. For a missing permission, code is insufficient_scope and error.code is missing_permission. Validation errors don't say which field failed, and error responses never echo submitted values. See Errors.

StatuscodeMeaningWhat to do
400invalid_queryThe URL has a query string. Create requests accept none.Send the request to /public/v1/customers/{customer_id}/locations with no query parameters.
400invalid_jsonThe body isn't one valid JSON value, repeats a property name, uses NaN/Infinity or nests deeper than 10 levels.Send a single JSON object encoded as UTF-8.
400invalid_operation_keyIdempotency-Key isn't 16–128 printable ASCII characters.Use a UUID or another 16–128 character key without spaces at either end.
401invalid_tokenThe bearer token is missing, malformed, expired, revoked or issued for a different resource (for example an MCP sign-in).Send a current REST API token or REST OAuth access token as Authorization: Bearer ….
403api_access_not_enabledFieldTask hasn't enabled API access for this organization, or has disabled it.An owner or admin requests access in Settings → API connections.
403insufficient_scopeThe connection lacks customer_locations:create, customer_locations:read or customers:read. error.code is missing_permission.Add the permission named in error.message to the connection, then retry with the same key.
403operation_forbiddenThe connection's access changed while the request was processed, or the result would include data the connection can no longer read.Check the connection's permissions, then retry. Retry creates with the same key and body.
404resource_not_foundThe URL is wrong, for example customer_id isn't a UUID, or the public API isn't available in this environment. A well-formed customer_id that doesn't match a customer returns 422, not 404.Check the API origin and path.
405method_not_allowedLocation creation isn't enabled in this environment. The Allow header lists the methods that are.Contact FieldTask if you expected location creation to be available.
409idempotency_key_reusedThis key was already used with a different body or for a different customer_id.Resend the original body to the original URL with this key, or use a new key for a different location.
409operation_in_progressA request with the same key is still being processed.Wait for Retry-After seconds, then retry with the same key and body.
409idempotency_window_expiredThis key was used more than seven days ago. It can't be replayed or reused. This doesn't mean the original request failed.Reconcile using your saved location ID, or list the customer's locations, before creating anything new.
410resource_goneYou replayed a key whose location, or its customer, has since been deleted in FieldTask.Don't create the location again automatically. Check with an owner or admin whether it was removed on purpose.
413payload_too_largeThe body is larger than 256 KiB.Send a smaller body.
415unsupported_media_typeContent-Type isn't application/json, or the body is compressed.Send an uncompressed body with Content-Type: application/json.
422validation_failedA field is missing, unknown or invalid; only one coordinate was sent; customer_id doesn't match a customer in your organization that hasn't been deleted; or the customer has locations but no default location.Check the request against the field guide and the customer ID. The response doesn't name the field.
429rate_limit_exceededToo many requests in the current minute, or too many concurrent requests, for the organization or connection.Wait for Retry-After seconds. Retry creates with the same key.
429daily_quota_exceededThe organization or connection has used its daily create allowance. Allowances reset at 00:00 UTC.Wait for Retry-After seconds, or check remaining allowance in Settings → API connections.
503temporarily_unavailableThe service couldn't complete the request. The location may or may not have been created.Retry with the same key and body, with exponential backoff.

Every response, including errors, has an X-Request-ID header. Include it, with the time and the status code, when you contact support. Never send tokens or secrets.

Limits​

Location creates count against the same per-minute, concurrency and daily create limits as other creates. Replaying an already-created location with its original key doesn't count as another create. See Rate limits.

Response headers​

A successful create returns 201 Created with these headers:

HeaderAlways presentValue
Cache-ControlYesAlways no-store
Idempotency-KeyYesstring
Idempotency-ReplayedYestrue or false
LocationYesuri-reference
Operation-LocationYesuri-reference
X-Request-IDYesuuid

Location is the location's own URL, /public/v1/customer-locations/{id}, not a path under the customer. The server also returns the Idempotency-Key that was used, including one it generated.