post
https://www.locally.com/headless/api/1.0/product/search
Search for products by company, category, department, and filters.
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. |
campaign_id | integer | No | Campaign ID. |
company_id | integer | No | Company ID. |
category | string | No | Category. |
dept | string | No | Department. |
filters | string | No | Filters. |
Example Request
curl 'https://www.locally.com/headless/api/1.0/product/search' \
--request POST \
--header 'Locally-Api-Token: {{API_TOKEN}}' \
--url-query 'company_id={{COMPANY_ID}}' \
--url-query 'category=footwear' \
--url-query 'dept=running-shoes'const params = new URLSearchParams({
company_id: '{{COMPANY_ID}}',
category: 'footwear',
dept: 'running-shoes'
});
const response = await fetch(`https://www.locally.com/headless/api/1.0/product/search?${params}`, {
method: 'POST',
headers: {
'Locally-Api-Token': '{{API_TOKEN}}'
}
});
const data = await response.json();import requests
response = requests.post(
"https://www.locally.com/headless/api/1.0/product/search",
headers={"Locally-Api-Token": "{{API_TOKEN}}"},
params={
"company_id": "{{COMPANY_ID}}",
"category": "footwear",
"dept": "running-shoes",
},
)
data = response.json()All parameters are sent in the query string — the POST body is unused. category and dept take the category and department slugs returned in the top_level_categories and level_2_categories facets of a previous search response.
Example Response
{
"success": true,
"data": {
"search_results": {
"products": [
{
"style_number": "TR2-M",
"company_id": 999,
"id": 1234567,
"name": "Trail Runner 2",
"image": "image.jpg",
"company_name": "ACME Outfitters",
"price": 129.99,
"min_price": 129.99,
"max_price": 149.99,
"price_range": 5,
"unit_msrp": 129.99,
"currency": "USD",
"stock_status": 1,
"url": "/product/1234567/acme-outfitters-trail-runner-2"
},
{
"style_number": "RR1-W",
"company_id": 999,
"id": 1234568,
"name": "Road Racer 1",
"image": "image.jpg",
"company_name": "ACME Outfitters",
"price": 89.99,
"min_price": 89.99,
"max_price": 89.99,
"price_range": 4,
"unit_msrp": 89.99,
"currency": "USD",
"stock_status": 1,
"url": "/product/1234568/acme-outfitters-road-racer-1"
}
],
"top_level_categories": [
{
"id": 87,
"name": "Footwear",
"slug": "footwear",
"link": "/search/acme-outfitters/footwear"
}
],
"level_2_categories": [
{
"id": 214,
"name": "Running Shoes",
"slug": "running-shoes",
"link": "/search/acme-outfitters/footwear/running-shoes"
}
],
"level_3_categories": [],
"level_4_categories": [],
"vendors": [
{
"id": 999,
"name": "ACME Outfitters",
"city": "Chicago",
"state": "IL",
"slug": "acme-outfitters",
"url": "/search/acme-outfitters"
}
],
"base_url": "/search/acme-outfitters/footwear/running-shoes"
},
"page_title": "ACME Outfitters Footwear Running Shoes",
"total_hits": 42,
"sort_link_prepend": "/headless/api/1.0/product/search?company_id=999&category=footwear&dept=running-shoes&sort=",
"n_visible_filters": 3,
"n_results_per_page": 30,
"n_pages": 2,
"local_url": "/search/acme-outfitters/footwear/running-shoes/all-local-stores",
"meta_description": "Products, brands and stores matching \"ACME Outfitters Footwear Running Shoes\"",
"session": {
"id": "abc999"
}
},
"msg": ""
}Response Explanation
success—truewith an emptymsgon success; on failuresuccessisfalseand amsgplus numericerror_codeare returned (e.g.1102when the token can't access the requestedcompany_id).data.search_results.products[]— One row per matching product. In-stock matches are scoped to the session's location (roughly a 50-mile radius by default), and rows without a resolvable price are omitted.data.search_results.products[].price— All price fields are decimal amounts incurrency, not cents.min_price/max_pricespan the prices found across local stores (falling back to MSRP);unit_msrpis the manufacturer's suggested price.data.search_results.products[].price_range— Bucket index ofpricealong the breakpoints 0, 25, 50, 75, 100, 150, 200, 300, 500, 750, 1000 —5means 100–150. Powers the price facet.data.search_results.products[].stock_status—1when at least one local store has the product in stock;0when the product is indexed for search without any local stock.data.search_results.products[].url— Site-relative path built from Locally's productidand a name slug; prefix it withhttps://www.locally.com. Categorylinkvalues,base_url, andlocal_urlare relative in the same way.data.search_results.top_level_categories[].slug— Facet slugs feed follow-up searches: pass a top-level slug ascategoryand alevel_2_categories[].slugasdeptto drill down.data.total_hits— Total number of matching products across all pages, not the count in this response.data.n_pages—total_hitsdivided byn_results_per_page(30 by default), rounded up. Fetch further pages with the zero-basedpagequery parameter.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

