Find eligible locations
Before you can show a delivery promise or offer store pickup, you need to know which of the
merchant's locations can actually serve a given customer. POST /storefront/locations returns
exactly that: the configured stores or warehouses eligible for a customer, nearest first.
A location is eligible when it is active, the merchant has access to it, it carries the function you asked for, and its coverage includes the customer. This recipe covers the two coverage models, the selection order, the filters, and the result cap.
Scenario
A customer in London opens a store locator. You call Carriyo with the customer's location and ask for the nearest fulfillment stores within 25 km. Carriyo returns the eligible stores, each with how far it is from the customer.
How a location becomes eligible
A location is returned only when all of these hold:
- It is active and the merchant has access to it.
- It carries the requested function (
FULFILLMENTorCOLLECTION). - Its geography matches the customer. This is checked differently for each function.
Fulfillment locations are gated by their configured coverage:
| Coverage | How it matches | Needs coordinates |
|---|---|---|
Zone (fulfillment_zones) | The location's zones cover the customer's country, state, city, or area terms. | No |
Radius (fulfillment_radius) | The customer is within the radius. | Yes, on both the location and the customer |
| None configured | The location serves everywhere. | No |
A fulfillment location with radius coverage but no coordinates, or a request with no
customer.coords, is ineligible on the radius rule.
Collection locations are not gated by zones or radius. A location qualifies on its collection
flag alone. The only geographic constraint is max_distance, which caps how far a pickup point can
be from the customer.
Prerequisites
- API credentials: see Getting started for the one-time setup.
- Locations configured for the merchant, with zone or radius coverage set where you want eligibility to be geography-aware.
Step 1, call the endpoint with the customer's location
Send merchant and customer.country at minimum. Supply customer.coords to get a distance
on each location and to sort by it.
curl -X POST 'https://api.carriyo.com/storefront/locations' \
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
-H 'tenant-id: YOUR_TENANT_ID' \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"merchant": "ACME",
"functions": ["FULFILLMENT"],
"location_type": "STORE",
"customer": {
"country": "GB",
"city": "London",
"area": "Marylebone",
"coords": [51.5194, -0.1547]
},
"max_distance": { "value": 25, "unit": "km" },
"max_locations": 20
}'
Step 2, read the response
The response is one complete, capped answer — a bare array in selection order:
{
[
{
"location_id": "loc-uk-marylebone",
"location_code": "STORE-UK-LON-01",
"location_name": "ACME Marylebone",
"location_type": "STORE",
"functions": ["FULFILLMENT", "COLLECTION"],
"address1": "12 Marylebone High Street",
"city": "London",
"country": "GB",
"postcode": "W1U 4RY",
"area": "Marylebone",
"coords": [51.5194, -0.1547],
"distance": { "value": 0.3, "unit": "km" }
},
{
"location_id": "loc-uk-camden",
"location_code": "STORE-UK-LON-02",
"location_name": "ACME Camden",
"location_type": "STORE",
"functions": ["FULFILLMENT"],
"address1": "5 Camden High Street",
"city": "London",
"country": "GB",
"postcode": "NW1 7JE",
"area": "Camden",
"coords": [51.5346, -0.1416],
"distance": { "value": 2.1, "unit": "km" }
}
]
distanceis present only when both the customer and the location have coordinates; otherwise it isnull.
Selection order
The order is fixed — there are no sort parameters:
- With
customer.coords: nearest first. Locations with no computable distance come last. - Without coordinates:
location_codeorder, so results are deterministic.
Filtering
Narrow the result with two filters:
location_typefilters toSTOREorWAREHOUSE. Omit it to include both.functionstakesFULFILLMENT,COLLECTION, or both. Defaults to[FULFILLMENT]. Ask forCOLLECTIONto build a click-and-collect locator.
Use max_distance (which needs customer.coords) to cap how far out to look.
The result cap
One call returns the complete answer, capped by max_locations (default 10, maximum 50; out of
range returns 400). There are no pages: receiving exactly max_locations items means more may
exist, so narrow the filters or raise the cap. page/page_size and sort_by/sort_direction
are rejected with 400.
Pitfalls
- Distance needs coordinates. Supply
customer.coords, or Carriyo can't compute distances — results fall back tolocation_codeorder andmax_distancereturns400. - Radius coverage needs coordinates on both sides. A location with radius coverage is ineligible when either its own coordinates or the customer's are missing. Zone coverage has no such requirement.
- No coverage configured means everywhere. A location with neither zones nor radius is eligible for every customer — deliberate, but easy to forget when you expect geography filtering.
- This endpoint is stateless. No order or shipment is created. Call it as the customer's location changes.