Search for products

Search for products by company, category, department, and filters.

Request Parameters

🏷️ header · unmarked parameters are query params

ParameterTypeRequiredDescription
Locally-Api-Token 🏷️stringYesLocally API token must be passed in the header to authenticate the API consumer.
campaign_idintegerNoCampaign ID.
company_idintegerNoCompany ID.
categorystringNoCategory.
deptstringNoDepartment.
cstringNoComma-separated list of category IDs to search across (e.g. c=87,214,305).
filtersstringNoFilters.

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.

Searching Across Multiple Categories

Use the c query parameter to search across more than one category at once. Pass a comma-separated list of numeric category id values (the id fields returned in the top_level_categories, level_2_categories, and lower-level category facets), for example c=87,214,305.

  • Format — Numeric category IDs only, joined by commas with no spaces (e.g. c=87,214). A single ID is also valid (c=87).
  • Search behavior — c broadens the result set: products matching any of the listed category IDs are returned (an OR across categories). This differs from the slug-based category/dept parameters, which narrow results by drilling into a single category and department.
  • Combining with filters — Once results are scoped by c, the filters parameter continues to filter within that combined result set. Use c to define which categories to search; use filters to narrow what comes back.
  • c may be combined with company_id, campaign_id, and paging parameters like page in the same request.

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 — true with an empty msg on success; on failure success is false and a msg plus numeric error_code are returned (e.g. 1102 when the token can't access the requested company_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 in currency, not cents. min_price/max_price span the prices found across local stores (falling back to MSRP); unit_msrp is the manufacturer's suggested price.
  • data.search_results.products[].price_range — Bucket index of price along the breakpoints 0, 25, 50, 75, 100, 150, 200, 300, 500, 750, 1000 — 5 means 100–150. Powers the price facet.
  • data.search_results.products[].stock_status — 1 when at least one local store has the product in stock; 0 when the product is indexed for search without any local stock.
  • data.search_results.products[].url — Site-relative path built from Locally's product id and a name slug; prefix it with https://www.locally.com. Category link values, base_url, and local_url are relative in the same way.
  • data.search_results.top_level_categories[].slug — Facet slugs feed follow-up searches: pass a top-level slug as category and a level_2_categories[].slug as dept to drill down. The numeric id values on these facets are what you pass to the c parameter to search across several categories at once.
  • data.total_hits — Total number of matching products across all pages, not the count in this response.
  • data.n_pages — total_hits divided by n_results_per_page (30 by default), rounded up. Fetch further pages with the zero-based page query parameter.
  • data.session.id — Locally session identifier, returned on every Headless API response. Echo it back in the Locally-Api-Session-Id header so the shopper's location and cart persist across calls.
Query Params
Headers
Responses
200

Successful

400

Bad Request

401

Unauthorized

402

Request Failed

Language
LoadingLoading…
Response
Click Try It! to start a request and see the response here!