get
https://www.locally.com/headless/api/1.0/product/locate
Given a style or a list of UPCs, locate stores that have the product in stock.
Request Parameters
🏷️ header · unmarked parameters are query params
| Parameter | Type | Required | Description |
|---|---|---|---|
Locally-Api-Token 🏷️ | string | Yes | Locally API token must be passed in the header to authenticate the API consumer. |
company_id | integer | Yes | The ID of the company. |
map_center_lat | string | Yes | The latitude of the geographical region center. |
map_center_lng | string | Yes | The longitude of the geographical region center. |
radius_in_miles | integer | No | The radius of the search region around the map center, in miles. Alternative to radius_in_km. |
radius_in_km | integer | No | The radius of the search region around the map center, in kilometers. Alternative to radius_in_miles. |
only_show_country | string | No | Limit results to a specific country code e.g. US, CA, etc. |
n_dealers | integer | No | The number of stores to return. The default is 3. Requests above the effective maximum are capped. |
product_id | integer | No | The Locally product ID. Used together with company_id; the product must belong to that company. Use instead of UPC, style, or color. |
upc | string | No | The UPC code(s) of the item. For multiple UPCs, specify a comma-separated list. Use instead of product_id, style, or color. Required if product_id, style, and color are not provided. |
style | string | No | The brand's style identifier as stored in Locally (typically the style_number from the brand's product feed). Retrieves stores and in-stock data for related UPC codes. Resolves within the company_id scope — for cross-brand lookups, the company_id must belong to the product owner. Use UPC if the owner is unknown. Use instead of product_id, UPC, or color. Required if product_id, UPC, and color are not provided. |
color | string | No | The ID of the color. Retrieves stores and in-stock data for related UPC codes. Use instead of product_id, UPC, or style. Required if product_id, UPC, and style are not provided. |
show_only_upc_stocking_dealers | integer | No | Set to 1 to return only stores that have the requested UPC(s) in stock. If no store in the region stocks them, the API returns success: false with error_code 1105. |
category | string | No | The name of the dealer category. |
paths_to_purchase | string | No | Comma delimited list of paths to purchase to filter by. Valid statuses are bopis, ropis, sdd and sts. If no paths to purchase supplied then all paths to purchase are returned. |
Example Request
curl --get 'https://www.locally.com/headless/api/1.0/product/locate' \
--header 'Locally-Api-Token: {{API_TOKEN}}' \
--data-urlencode 'company_id={{COMPANY_ID}}' \
--data-urlencode 'style={{STYLE}}' \
--data-urlencode 'map_center_lat=41.8756719' \
--data-urlencode 'map_center_lng=-87.6243469' \
--data-urlencode 'radius_in_miles=200' \
--data-urlencode 'only_show_country=US' \
--data-urlencode 'n_dealers=3'const params = new URLSearchParams({
company_id: '{{COMPANY_ID}}',
style: '{{STYLE}}',
map_center_lat: '41.8756719',
map_center_lng: '-87.6243469',
radius_in_miles: '200',
only_show_country: 'US',
n_dealers: '3'
});
const response = await fetch(
`https://www.locally.com/headless/api/1.0/product/locate?${params}`,
{
headers: { 'Locally-Api-Token': '{{API_TOKEN}}' }
}
);
const data = await response.json();import requests
response = requests.get(
'https://www.locally.com/headless/api/1.0/product/locate',
headers={'Locally-Api-Token': '{{API_TOKEN}}'},
params={
'company_id': '{{COMPANY_ID}}',
'style': '{{STYLE}}',
'map_center_lat': '41.8756719',
'map_center_lng': '-87.6243469',
'radius_in_miles': 200,
'only_show_country': 'US',
'n_dealers': 3,
},
)
data = response.json()Identify the product with exactly one of product_id, upc (accepts a comma-separated list), style, or color. product_id must belong to the company_id you pass. style resolves within the company_id scope, so a lookup for a product owned by another brand must pass the owner's company_id — use upc when the owner is unknown.
Example Response
{
"success": true,
"data": {
"product": {
"id": 123456,
"long_description": "Waterproof three-season trail jacket with pit zips and an adjustable storm hood.",
"name": "Trailblazer Jacket",
"image": "image.jpg",
"n_reviews": 12,
"average_rating": 4.5,
"style_number": "999",
"company_id": 999,
"company": {
"id": 999,
"address": "15 ACME Ave",
"logo": "image.jpg",
"name": "ACME Outfitters",
"phone": "(312) 555-0175"
},
"upcs": [
{
"id": 111111,
"code": "000000000001",
"color_code": "BLK",
"color_name": "Black",
"size_1": "M",
"size_2": "",
"image_url": "image.jpg"
},
{
"id": 111112,
"code": "000000000002",
"color_code": "BLK",
"color_name": "Black",
"size_1": "L",
"size_2": "",
"image_url": "image.jpg"
}
]
},
"all_upcs_carried": [
"000000000001",
"000000000002",
"000000000003"
],
"markers": [
{
"id": 37175,
"name": "ACME Outfitters Chicago",
"distance": "6.0 mi",
"address": "15 ACME Ave",
"city": "Chicago",
"state": "IL",
"zip": "60647",
"country": "US",
"phone": "(312) 555-0142",
"url": "",
"has_stock": 1,
"feature_constants": [
{
"key": "IN_STORE_PICKUP_AVAILABLE",
"value": "Store Pickup Available"
}
],
"status_label": "Open",
"status_class": "success",
"today_hours": "7am-8pm",
"next_open": "",
"hours_known": 1,
"is_tmp_closed": 0
}
],
"session": {
"id": "abc999"
}
},
"msg": ""
}Response Explanation
success—truewith an emptymsgon success. When no nearby store carries the product — or, withshow_only_upc_stocking_dealers=1, when no nearby store stocks the requested UPC(s) — the API instead returnssuccess: falsewitherror_code1105and a not-foundmsg.data.product.upcs[]— Only variants whosecode(the scannable UPC) appears inall_upcs_carried, with their color and size attributes.idhere — likedata.product.id— is a Locally-internal record ID.data.all_upcs_carried[]— Every UPC variant of the product in stock at stores in the searched region, most-carried first; use it to drive variant pickers (see Create a Product Locator).data.markers[]— Nearby stores within the requested radius, ordered first by stock/BIL tier and then by distance within each tier (not by distance alone), capped atn_dealers(3 by default).idis the Locally store ID other endpoints accept (e.g.only_store_idonconversion/store_data).data.markers[].distance— Pre-formatted display string in the shopper's unit: miles for US and GB stores, kilometers elsewhere. Empty when the distance is 0 or 300+ miles.- Numeric distance — Each marker also carries the distance as a raw number alongside the
distancestring, suitable for sorting or custom formatting; it is populated even when the display string is empty. data.markers[].has_stock—1when the store has the product (or the exact variant) in stock,0when it merely carries the brand without live stock of this product.data.markers[].url— The store's own website when Locally knows it (empty string otherwise) — not a locally.com link.data.markers[].feature_constants[]— Paths to purchase the store offers: stablekeyvaluesDELIVERY_AVAILABLE,IN_STORE_PICKUP_AVAILABLE, orSHIP_TO_STORE_AVAILABLEwith a localized displayvalue.data.markers[].status_label— Store-hours status:Open/Closedwith matchingstatus_classsuccess/warning; both empty whenhours_knownis0.next_openfills only while closed, andis_tmp_closed1flags a temporary closure.data.session.id— Locally session identifier, returned on every Headless API response. Echo it back in theLocally-Api-Session-Idheader so the shopper's location and cart persist across calls.
200Successful
400Bad Request
401Unauthorized
402Request Failed
403Forbidden
404Not Found
429Too Many Requests
500Server Error

