Get information for one or many stores and their in-stock data for a given UPC (Universal Product Code).
allVariants parameter
allVariants parameterBy default, this endpoint returns in-stock data for the single UPC (Universal Product Code) you provide. Set the optional allVariants parameter to True to return availability for all UPCs associated with the same product.
| Parameter | Type | Required | Description |
|---|---|---|---|
allVariants | boolean | No | When set to True, returns availability for all UPCs associated with the product, not just the requested UPC. Defaults to False. |
When allVariants=True is set, the response includes availability data for each variant UPC linked to the product, allowing you to retrieve store-level in-stock data across all of a product's variants in a single request.
variant_upc parameter
variant_upc parameterThe optional variant_upc parameter accepts one UPC (or a comma-separated list of UPCs). Each UPC is resolved to its owning product's style group, and the endpoint returns the full variant-group payload (including all_upcs_carried and variant_data) identical to what a style= request would return.
| Parameter | Type | Required | Description |
|---|---|---|---|
variant_upc | string | No | One UPC, or a comma-separated list of UPCs. Each UPC is resolved to the owning product's style group, and the full variant-group payload (all_upcs_carried, variant_data) is returned, matching a style= request. |
Although variant_upc accepts a comma-separated list, the intent is singular: each supplied UPC is resolved independently to its owning product's style group. Use it when you have a UPC but want the complete variant-group response.
Because variant_upc resolves through the owning product's style group, it is cross-brand safe — no company_id or company_slug mapping is required to use it.
Conflict behavior
If variant_upc is sent alongside upc or style, the request is treated as a conflict. Send variant_upc on its own, without upc or style, to retrieve the variant-group payload.
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 | No | The ID of the company. Required unless company_slug is provided. For style-based queries on products owned by another brand (e.g. a retailer reselling a third-party product), this must be the product owner's company_id, not the requesting partner's. |
company_slug | string | No | Alternative to company_id. The brand's slug (lowercase, alphanumeric, spaces replaced with hyphens — derived from the brand name). When provided without company_id, the company_id is resolved server-side. Useful for cross-brand style lookups where the storefront doesn't track numeric company_ids. |
dealers_company_id | integer | No | The ID of the company. Set to include authorized dealers. |
only_store_id | integer | No | The ID of the store. |
upc | string | No | The UPC code to retrieve stores and in-stock data for. |
style | string | No | The brand's style identifier as stored in Locally (typically the style_number from the brand's product feed — often a model name or SKU root, not a partner's internal model ID). Resolves to a product within the company_id (or company_slug) scope. For cross-brand / reseller scenarios, the company must be the product owner, not the requesting partner — otherwise no product will match and inventory will come back empty. If you don't know the owner, use upc instead. |
map_distance_unit | string | Yes | The distance unit for the geographical region. One of: mi, km. |
map_distance_diag | integer | Yes | The diagonal distance of the geographical region. Specify 1 if only_store_id is specified. |
map_center_lat | string | No | Required if only_store_id is not specified. The latitude of the geographical region center. |
map_center_lng | string | No | Required if only_store_id is not specified. The longitude of the geographical region center. |
invalidate_cache | string | No | Results are cached by default for stateful (session) requests. Set to 'true' to invalidate the cache. |
filters | string | No | Comma delimited list of statuses to filter by. Valid statuses are IN_STOCK, PTP_BOPIS, PTP_ROPIS, PTP_SDD and PTP_STS. |
allVariants | boolean | No | When set to True, returns availability for all UPCs associated with the product, not just the requested UPC. Defaults to False. See the section above. |
variant_upc | string | No | One UPC, or a comma-separated list of UPCs; each resolves to the owning product's style group and returns the full variant-group payload. Do not combine with upc or style. See the section above. |
Example Request
curl --get 'https://www.locally.com/headless/api/1.0/conversion/store_data' \
--header 'Locally-Api-Token: {{API_TOKEN}}' \
--data-urlencode 'company_id={{COMPANY_ID}}' \
--data-urlencode 'upc={{UPC}}' \
--data-urlencode 'map_center_lat=41.8756719' \
--data-urlencode 'map_center_lng=-87.6243469' \
--data-urlencode 'map_distance_unit=mi' \
--data-urlencode 'map_distance_diag=200'const params = new URLSearchParams({
company_id: '{{COMPANY_ID}}',
upc: '{{UPC}}',
map_center_lat: '41.8756719',
map_center_lng: '-87.6243469',
map_distance_unit: 'mi',
map_distance_diag: '200'
});
const response = await fetch(`https://www.locally.com/headless/api/1.0/conversion/store_data?${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/conversion/store_data',
headers={'Locally-Api-Token': '{{API_TOKEN}}'},
params={
'company_id': '{{COMPANY_ID}}',
'upc': '{{UPC}}',
'map_center_lat': '41.8756719',
'map_center_lng': '-87.6243469',
'map_distance_unit': 'mi',
'map_distance_diag': 200,
},
)
data = response.json()Provide either upc or style — not both. For style lookups, company_id (or company_slug) must identify the product-owning brand. To query a single store, pass only_store_id with map_distance_diag=1 and omit map_center_lat and map_center_lng.
Example Response
{
"success": true,
"data": {
"all_upcs_carried": [
"000000000000"
],
"markers": [
{
"id": 37175,
"name": "ACME Outfitters Chicago",
"lat": "41.91136867",
"lng": "-87.67771437",
"address": "15 ACME Ave",
"city": "Chicago",
"state": "IL",
"zip": "60647",
"phone": "(312) 555-0142",
"country": "US",
"company_id": 999,
"image": "image.jpg",
"vendor_id": "",
"user_distance": 0,
"stock_status": 3,
"stocking_product": 1,
"stocking_variant": 1,
"acquisition_options": {
"bopis": 1,
"ropis": 1
},
"disclaimer": "Item is in Stock!",
"dow": 0,
"display_dow": [
{
"bil_hrs": "7am-8pm",
"label": "Monday",
"day_index": 0
}
],
"today_hours": "7am-8pm",
"hours_known": 1,
"is_open": 1,
"next_open": "",
"is_closing_soon": 0,
"phone_link": "tel:+13125550142",
"is_tmp_closed": 0,
"status_class": "success",
"status_label": "Open",
"qoh": 10,
"stock_status_constants": [
{
"key": "PRODUCT_YES_VARIANT_YES_BIL_YES",
"value": "Item is in Stock!"
}
],
"feature_constants": [
{
"key": "DELIVERY_AVAILABLE",
"value": "Same-day Local Delivery Available"
},
{
"key": "IN_STORE_PICKUP_AVAILABLE",
"value": "Store Pickup Available"
}
],
"web_address": "https://www.acmeco.com"
}
],
"total_marker_count": 100,
"session": {
"id": "abc999"
}
},
"msg": ""
}Response Explanation
success— Boolean outcome of the call. Whenfalse, the response also carries a top-levelerror_codeand explanatorymsg— always checksuccess, not just the HTTP status.data.all_upcs_carried— Every UPC variant of the product available in the searched region (or at the single store whenonly_store_idis set) — the style-group counterpart to your singleupc.data.markers[].id— Locally's store ID. Reuse it asonly_store_idhere, as theidpath segment in Get location data, and to match shipping options to stores.data.markers[].stock_status— Stocking enum:0inventory not shared,1brand only,2product but not this variant,3requested UPC in stock;stocking_product/stocking_variantare the equivalent1/0flags.data.markers[].qoh— Quantity on hand at this store for the requested UPC (0when unknown). At or below the store's low-quantity threshold,disclaimerswitches to its low-stock label.data.markers[].user_distance— Distance from the shopper's session location (falls back to the map center), always in miles regardless ofmap_distance_unit.data.markers[].acquisition_options— Paths to purchase for the requested UPC —bopis(buy online, pick up in store),ropis(reserve, pick up in store),sdd(same-day delivery),sts(ship to store); affiliate-powered stores reportaff_bopisinstead ofbopis.data.markers[].stock_status_constants[].key— Machine-readable stock state, e.g.PRODUCT_YES_VARIANT_YES_BIL_YES(in stock),PRODUCT_YES_VARIANT_NO_BIL_YES(other variants only),SHARE_NO(inventory not shared),STS_YES(ship to store);valueis the localized shopper-facing label.data.markers[].feature_constants[].key— Store service flags with localizedvalue:DELIVERY_AVAILABLE,IN_STORE_PICKUP_AVAILABLE, orSHIP_TO_STORE_AVAILABLE. Thefiltersrequest parameter matches against these plusIN_STOCKandPTP_*statuses.data.total_marker_count— Total stores matched after filtering.markersitself is one page — the 10 nearest by default, adjustable withmarker_offset/marker_limit.data.session.id— Locally session ID, returned on every response. Replay it via theLocally-Api-Session-Idheader to persist the shopper's session between calls; expired IDs are transparently replaced with fresh ones.msg— Human-readable error text; empty string on success. In production, unexpected server errors are masked asApp server errorwith alookupreference — see Handling Errors in Production.
200Successful
400Bad Request
401Unauthorized
402Request Failed
403Forbidden
404Not Found
429Too Many Requests
500Server Error

