Developer docs

Location Query API

Read your published locations as clean JSON. Radius search, keyword search, and tag filtering handled server-side. Build any frontend on top while your team manages locations in the dashboard.

Base URL: https://api.storepoint.co/public/v1/{token} Auth: public locator token Read-only
On this page

Most projects don't need this API. The drop-in widget covers search, filters, and maps with no code. This API is for building your own frontend on Storepoint data.

Read-only API for your published locations. It uses your public locator token and is safe to call from frontend code. To create, update, or delete locations programmatically, use the Location Management API with a private API key.

Overview

The Location Query API reads the location data your team manages in Storepoint. Your team keeps working in the dashboard, spreadsheet imports, Google Sheets sync, or the Location Management API, and you query the same data over REST.

What you can do

  • Query locations by geographic radius or retrieve all locations at once
  • Filter by tags using the same AND/OR logic configured in your dashboard
  • Search by keyword across name, address, description, and tags
  • Get your filter configuration to build a matching filter UI
  • Access custom field data and priority sorting rules

Common use cases

  • Custom locator UI: full design control beyond locator styling
  • Mobile apps: native iOS and Android location features
  • Additional pages: location detail pages, regional landing pages, "stores near me" sections
  • Kiosks and displays: in-store touchscreens, trade show displays
  • Integrations: location data for chatbots, voice assistants, or other systems

Quick Start

The Query API is off by default for each locator. Two steps take you from zero to your first response.

1. Enable the API

Open the Developer Portal in your Storepoint dashboard and switch on the Query API. Copy your public token from the same page. You can also restrict requests to your own domains there with the referrer allowlist.

2. Make your first request

JavaScript
const LOCATOR_TOKEN = 'your_locator_token'; // From the Developer Portal

fetch(`https://api.storepoint.co/public/v1/${LOCATOR_TOKEN}/locations?lat=40.7128&lng=-74.0060&radius=25`)
  .then(response => response.json())
  .then(data => {
    data.data.locations.forEach(location => {
      console.log(location.name, location.distance.value + ' miles');
    });
  });

New to Storepoint? Storepoint is a store locator your whole team can run. Start a free trial, add your locations, then query them here.

Authentication

Requests authenticate with your public locator token in the URL path. That is the whole handshake, plain GET requests work as-is.

Base URL
https://api.storepoint.co/public/v1/{locator_token}/

The token only reads the locations you've published in your locator, the same set your embedded widget shows. That makes it safe to use in frontend code. Enable the API first in the Developer Portal, where you can also restrict requests to your own domains with the referrer allowlist.

Keep your private API key out of frontend code. The private key is for server-side use with the Location Management API. If you expose it by accident, rotate it in your dashboard right away.

Endpoints

Three read-only endpoints cover the full API surface.

Endpoint Description
GET /locations Query locations with filtering, sorting, and pagination
GET /locations/{id} Get a single location by its public ID
GET /filters Get filter and tag configuration for building filter UIs

Query Locations

Retrieve locations with optional geographic filtering, tag filtering, and sorting.

GET /locations

Query parameters

Parameter Type Description
lat number Required*. Latitude of search center point (-90 to 90)
lng number Required*. Longitude of search center point (-180 to 180)
radius number Search radius. Default: your locator's configured radius, or 25 if unset
unit string miles or km. Default: miles
limit number Maximum results to return. Default: 20, maximum: 500
offset number Number of results to skip for pagination. Default: 0
tags array Filter by tags. Example: ?tags[]=retail&tags[]=flagship
tagLogic string any, all, or match. See Filtering by Tags. Default: any
search string Keyword search across name, address, description, and tags
sort string distance, name, or priority. See Sorting. Default: distance
all boolean Set to true to return all locations. Useful for pre-loading or static maps

* lat and lng are required unless all=true.

Example request

Request
GET /locations?lat=40.7128&lng=-74.0060&radius=25&unit=miles&limit=10

Get Single Location

Retrieve a specific location by its public ID.

GET /locations/{id}

The id is the location's public ID, returned in query results. Format: loc_ followed by alphanumeric characters.

Get Filters

Retrieve your filter and tag configuration to build custom filter UIs. Call this before loading locations to render your dropdowns or checkboxes.

GET /filters

Example response

Response
{
  "success": true,
  "data": {
    "filters": [
      {
        "id": "_default",
        "name": "Categories",
        "label": "Filter by Category",
        "singleSelect": false,
        "inline": false,
        "hidden": false,
        "hideInLocationDetails": false,
        "tags": [
          { "value": "retail", "label": "Retail", "color": "#3B82F6" },
          { "value": "wholesale", "label": "Wholesale" }
        ]
      },
      {
        "id": "features",
        "name": "Features",
        "label": "Filter by Features",
        "singleSelect": false,
        "inline": true,
        "hidden": false,
        "hideInLocationDetails": false,
        "tags": [
          { "value": "parking", "label": "Free Parking", "color": "#10B981" },
          { "value": "accessible", "label": "Wheelchair Accessible" }
        ]
      }
    ]
  }
}

Filter properties

Property Description
id Group identifier, used with tagLogic=match for AND across groups
singleSelect If true, only one tag can be selected at a time in this group
inline Suggested display style: inline buttons vs dropdown
hidden If true, this filter is hidden in the standard locator (you may still want to show it)
tags[].value The tag value to use in the ?tags[]= parameter
tags[].label Display label for the tag
tags[].color Optional hex color for styling
tags[].image Optional image URL for the tag

Response Format

All responses follow one structure.

Location query response
{
  "success": true,
  "data": {
    "locations": [
      {
        "id": "loc_abc123def456",
        "name": "Downtown Flagship Store",
        "coordinates": {
          "lat": 40.7128,
          "lng": -74.0060
        },
        "address": {
          "formatted": "123 Main Street, New York, NY 10001"
        },
        "contact": {
          "phone": "+1 212-555-1234",
          "email": "[email protected]",
          "website": "https://example.com"
        },
        "social": {
          "instagram": "storename",
          "facebook": "storename",
          "twitter": "storename"
        },
        "hours": {
          "monday": "9:00am - 6:00pm",
          "tuesday": "9:00am - 6:00pm",
          "wednesday": "9:00am - 6:00pm",
          "thursday": "9:00am - 8:00pm",
          "friday": "9:00am - 8:00pm",
          "saturday": "10:00am - 6:00pm",
          "sunday": "Closed"
        },
        "tags": {
          "_default": {
            "name": "Categories",
            "items": [
              { "value": "retail", "label": "Retail", "color": "#3B82F6" },
              { "value": "flagship", "label": "Flagship" }
            ]
          },
          "features": {
            "name": "Features",
            "items": [
              { "value": "parking", "label": "Free Parking", "color": "#10B981" }
            ]
          }
        },
        "customFields": [
          {
            "token": "abc123",
            "key": "book_appointment",
            "name": "Book Appointment",
            "type": "button",
            "value": "https://booking.example.com",
            "label": "Book Now",
            "color": "#FF5733"
          }
        ],
        "image": "https://cdn.example.com/store.jpg",
        "description": "Our flagship downtown location.",
        "distance": {
          "value": 2.5,
          "unit": "miles"
        }
      }
    ],
    "pagination": {
      "offset": 0,
      "limit": 20,
      "total": 150,
      "hasMore": true
    }
  },
  "meta": {
    "query": {
      "center": { "lat": 40.7128, "lng": -74.0060 },
      "radius": 25,
      "unit": "miles"
    }
  }
}

Location object

Field Description
id Unique public location ID
coordinates Latitude and longitude
address Address object with a formatted string
contact Phone, email, and website
social Social media handles
hours Operating hours by day, raw text as configured
tags Tags organized by group, each with display metadata
customFields Ordered array of custom fields with full metadata (type, label, color, icon)
distance Distance from the search point, present for radius queries only

Filtering by Tags

Filter locations with the tags[] parameter and control matching with tagLogic.

Value Behavior Example
any (default) Location matches if it has ANY of the specified tags (OR logic) ?tags[]=retail&tags[]=wholesale returns locations with retail OR wholesale
all Location must have ALL specified tags (AND logic) ?tags[]=retail&tags[]=parking&tagLogic=all returns locations with both retail AND parking
match AND across filter groups, OR within groups. Matches how multi-select filter UIs typically work If "retail" and "wholesale" are in Categories and "parking" is in Features, selecting retail + parking returns locations with (retail OR wholesale) AND parking

Sorting

Control result order with the sort parameter.

  • distance: closest locations first. The default, and only distance option, for radius queries.
  • name: alphabetical by name. The default, and only name option, for all=true queries.
  • priority: apply your configured priority sorting rules. Works with both query modes.

Priority sorting. If you've set priority rules in your dashboard (for example, "show flagship stores first within 10 miles"), use sort=priority to apply them. Useful for promoting certain location types in results.

Pagination

Use limit and offset to page through results.

Example
# First page (results 1-20)
GET /locations?lat=40.7&lng=-74.0&limit=20&offset=0

# Second page (results 21-40)
GET /locations?lat=40.7&lng=-74.0&limit=20&offset=20

The response includes pagination metadata with ready-made next and prev URLs.

Pagination object
{
  "pagination": {
    "offset": 20,
    "limit": 20,
    "total": 150,
    "hasMore": true,
    "next": "https://api.storepoint.co/public/v1/abc123/locations?lat=40.7&lng=-74.0&limit=20&offset=40",
    "prev": "https://api.storepoint.co/public/v1/abc123/locations?lat=40.7&lng=-74.0&limit=20"
  }
}

Pagination fields

Field Description
offset Current offset position
limit Number of results per page
total Total number of matching locations
hasMore Whether more results exist beyond this page
next Full URL for the next page, present when hasMore is true
prev Full URL for the previous page, present after the first page

Error Handling

Errors return one structure with a machine-readable code, a plain message, and a link back to the relevant docs.

Error response
{
  "success": false,
  "error": {
    "code": "MISSING_COORDINATES",
    "message": "Either provide lat and lng parameters for radius search, or set all=true to retrieve all locations",
    "docs": "https://storepoint.co/developers/location-query-api#query-locations"
  }
}

Error codes

Code Status Meaning
INVALID_TOKEN 404 Locator token not found or inactive
API_NOT_ENABLED 403 The Query API is switched off for this locator. Enable it in the Developer Portal
REFERRER_NOT_ALLOWED 403 The request came from a domain outside your referrer allowlist
MISSING_COORDINATES 400 lat and lng are required unless all=true
INVALID_COORDINATES 400 lat or lng out of valid range
INVALID_PARAMETER 400 Parameter validation failed
LOCATION_NOT_FOUND 404 Location ID not found
SECRET_KEY_EXPOSED 400 Private API key used in a public endpoint. Rotate your key in the dashboard

Code Examples

JavaScript (Fetch)

JavaScript
const LOCATOR_TOKEN = 'your_locator_token';
const BASE_URL = `https://api.storepoint.co/public/v1/${LOCATOR_TOKEN}`;

// Query locations near a point
async function findNearbyLocations(lat, lng, radius = 25) {
  const response = await fetch(
    `${BASE_URL}/locations?lat=${lat}&lng=${lng}&radius=${radius}`
  );
  const data = await response.json();

  if (data.success) {
    return data.data.locations;
  } else {
    throw new Error(data.error.message);
  }
}

// Get filter configuration for UI
async function getFilters() {
  const response = await fetch(`${BASE_URL}/filters`);
  const data = await response.json();
  return data.data.filters;
}

// Usage
const locations = await findNearbyLocations(40.7128, -74.0060, 25);
locations.forEach(loc => {
  console.log(`${loc.name} - ${loc.distance.value} ${loc.distance.unit}`);
});

Python (Requests)

Python
import requests

LOCATOR_TOKEN = 'your_locator_token'
BASE_URL = f'https://api.storepoint.co/public/v1/{LOCATOR_TOKEN}'

def find_nearby_locations(lat, lng, radius=25):
    response = requests.get(
        f'{BASE_URL}/locations',
        params={'lat': lat, 'lng': lng, 'radius': radius}
    )
    data = response.json()

    if data['success']:
        return data['data']['locations']
    else:
        raise Exception(data['error']['message'])

# Usage
locations = find_nearby_locations(40.7128, -74.0060, 25)
for loc in locations:
    print(f"{loc['name']} - {loc['distance']['value']} {loc['distance']['unit']}")

cURL

terminal
# Query locations
curl "https://api.storepoint.co/public/v1/YOUR_LOCATOR_TOKEN/locations?lat=40.7128&lng=-74.0060&radius=25"

# Get all locations
curl "https://api.storepoint.co/public/v1/YOUR_LOCATOR_TOKEN/locations?all=true"

# Get filters
curl "https://api.storepoint.co/public/v1/YOUR_LOCATOR_TOKEN/filters"

Rate Limits

  • Keep sustained traffic under 1,000 requests per minute per token
  • Responses are cached at the edge and refreshed automatically when your locations change. Browsers cache responses for 60 seconds.

If a specific use case needs higher limits, email us.

Choose the right approach for your project

Storepoint works at whatever level of code your project calls for. Mix and match freely.

  • Zero code. Use the Storepoint locator app out of the box. Manage locations via the dashboard, spreadsheet imports, or Google Sheets sync.
  • Customize the locator. Keep our locator UI and extend its behavior with the Widget JavaScript API. Track analytics events, trigger custom actions, integrate with your site.
  • Custom frontend, managed backend. Build your own UI with this Query API while your team manages locations in the dashboard.
  • Fully API-driven. Sync locations from your systems with the Location Management API, and power your custom frontend with this Query API.

Related resources