---
title: "Create or update a location"
method: POST
path: "/locations"
tags: ["Locations"]
---

# Create or update a location

`POST /locations`

## Request

- Base URL: `https://api.ekho.com`
- URL: `https://api.ekho.com/locations`
- Auth: HTTP bearer

Adds a location to your program, or updates one already in it.

An `id` updates that location; failing that a known `external_id` does; failing both, the address is matched against locations already known to Ekho and a new one is created only if nothing matches. Sending the same `external_id` again updates rather than conflicts, so a nightly full sync is safe to run.

Neither identifier is required. Omit `external_id` and work off the `id` returned. Renaming an `external_id` means sending `id` alongside the new value.

Adding a location needs `name` and `address`. An update, by `id` or by a known `external_id`, may omit either and keeps what is stored. A `name` on an update sets what your program calls the location and takes effect at checkout. An `address` naming the same building is accepted however it is spelled. One naming a different building moves the location when Ekho created it through this API for your program alone and the new address is in the same state; otherwise it returns 409 for Ekho to review, and nothing is changed.

A new `external_id` whose address matches a location your program already holds under another `external_id` returns 409 rather than taking that location over. Update it by its `id` instead. Prices are never sent or returned, and each service is charged at your program's own rate.

## Request body

- object
  - `id` string: An Ekho location id. Updates that location, and is required to change its external_id.
  - `external_id` string: Your own id for this location. Unique within your program.
  - `services` string[], required: The services this location performs for your program.
  - `name` string: What your program calls this location. This is the name a buyer sees at checkout. Required to add a location; an update that omits it keeps the current name.
  - `address` object: Required to add a location. An update that omits it keeps the current address. One naming a different building moves the location when Ekho created it through this API for your program alone and the move stays in the same state; otherwise it returns 409 for Ekho to review.
    - `address_line_one` string, required
    - `address_line_two` string
    - `city` string, required
    - `state` string, required: Two-letter state code.
    - `zip` string, required
  - `email` string, email: Business contact, not a person. Every write saves it for your program and reads return it as you sent it; an update that omits it keeps the last value.
  - `phone` string: Business contact, not a person. Every write saves it for your program and reads return it as you sent it; an update that omits it keeps the last value.

## Response `200`

An existing location was updated.

- object
  - `data` Location, required
    - `id` string, required
    - `external_id` string, nullable, required: Your own id for this location. Null when you have not set one.
    - `name` string, required
    - `email` string, nullable, required
    - `phone` string, nullable, required
    - `address` LocationAddress, required
      - `address_line_one` string, required
      - `address_line_two` string, nullable, required
      - `city` string, required
      - `state` string, required
      - `zip` string, required
      - `lat` number, nullable, required
      - `lng` number, nullable, required
    - `services` string[], required: The services this location performs for your program.
    - `created_at` integer, required: When this location joined your program, in epoch milliseconds.
    - `updated_at` integer, required: When this location was last changed, in epoch milliseconds.

## Other responses

- `201`: The location was added to your network.
- `400`: The request was malformed or failed validation. `errors` itemizes every field at fault, so one response names them all; the fields in the example stand in for this request's own.
- `401`: Authentication is missing or invalid.
- `403`: The token lacks the scope this endpoint requires, or the account behind it does not run a program and so has no locations.
- `404`: No location in your program matches that id.
- `409`: The address matches more than one location, the matched location does not offer a requested service, the address matches a location your program holds under another `external_id`, an update moves a location Ekho must review, or the `external_id` already names a different location.
- `429`: The rate limit has been exceeded.
- `500`: An unexpected error occurred.

## Changes

- **2026-10-01** `c83d76f6a847`: 2 info
  - the request property `address` became optional
  - the request property `name` became optional
- **2026-09-18** `c4f268c2d91b`: 1 breaking, 3 warning, 3 info
  - removed the enum value `delivery` of the request property `services/items/`
  - removed the request property `legal_name`
  - added the new `last_leg_delivery` enum value to the `data/services/items/` response property for the response status `200`
  - added the new `last_leg_delivery` enum value to the `data/services/items/` response property for the response status `201`
  - …3 more
- **2026-09-18** `78c545d96a34`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/ekho/apis/ekho-api/changes/locations/post.md)

---

[API](https://skmtc.dev/ekho/apis/ekho-api.md) · [All operations](https://skmtc.dev/ekho/apis/ekho-api/llms.txt) · [OpenAPI document](https://skmtc.dev/ekho/apis/ekho-api/revisions/efe485119dd7?raw)
