Back to Developer Home

Location Query API

Query your Storepoint location data to build custom experiences: bespoke store locator UIs, mobile apps, kiosks, or any integration. Your team manages locations in the dashboard while developers query the data via this API.

Most customers don't need this

Storepoint's store locator app for websites works beautifully out of the box with no code required. This API is for developers who want to build custom location experiences in addition to, or instead of, the standard locator.

Read-Only API for Your Published Locations

This API queries the locations you've published in your Storepoint locator. It uses your public locator token and can safely be called from frontend code. For managing locations programmatically (create, update, delete), use the Location Management API with a private API key instead.

Overview

This API gives developers direct access to the location data managed in Storepoint. Use it to build custom location experiences while your team continues managing locations via the dashboard, imports, Google Sheets sync, or the Location Management API.

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/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 - Powering location data in chatbots, voice assistants, or other systems

Quick Start

Already have locations in Storepoint? Here's how to query them:

JavaScript
const LOCATOR_TOKEN = 'your_locator_token'; // Find this in your Storepoint dashboard

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');
    });
  });

Where to Find Your Locator Token

Your locator token is in your Storepoint dashboard under Developer Tools. It's the same token used in your locator embed code.

New to Storepoint?

Storepoint is the easiest way to add a store locator to your website. Start a free trial to add your locations, then use this API to query them in your custom frontend.

Authentication

The Location Query API uses your public locator token in the URL path. No API key header is required.

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

This API only accesses the locations you've published in your Storepoint locator, the same locations visible in your embedded locator. Since it's read-only and only returns your published locations, the locator token can safely be used in frontend code.

Never use your private API key in frontend code. The private key is for server-side use only with the Location Management API. If you accidentally expose it, rotate it immediately in your Storepoint dashboard.

Endpoints

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/tag configuration for building filter UIs

Query Locations

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

Endpoint
GET /locations

Query Parameters

lat number required*

Latitude of search center point (-90 to 90)

lng number required*

Longitude of search center point (-180 to 180)

radius number optional

Search radius. Default: your locator's configured radius, or 25 if not set.

unit string optional

miles or km. Default: miles

limit number optional

Maximum results to return. Default: 20, Maximum: 500

offset number optional

Number of results to skip for pagination. Default: 0

tags array optional

Filter by tags. Example: ?tags[]=retail&tags[]=flagship

tagLogic string optional

any, all, or match. See Filtering by Tags. Default: any

search string optional

Keyword search across name, address, description, and tags

sort string optional

distance, name, or priority. See Sorting. Default: distance

all boolean optional

Set to true to return all locations without requiring lat/lng. 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.

Endpoint
GET /locations/{id}

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

Get Filters

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

Endpoint
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

  • 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 ?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 a consistent structure:

Location Query Response
{
  "success": true,
  "data": {
    "locations": [
      {
        "id": "loc_abc123def456",
        "name": "Downtown Flagship Store",
        "coordinates": {
          "lat": 40.7128,
          "lng": -74.0060
        },
        "address": {
          "street": "123 Main Street",
          "city": "New York",
          "state": "NY",
          "postalCode": "10001",
          "country": "USA",
          "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

  • id - Unique public location ID
  • coordinates - Latitude and longitude
  • address - Structured address with parsed components and 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 search point (only present for radius queries)

Filtering by Tags

Filter locations by tags using the tags[] parameter. Control matching logic with tagLogic:

tagLogic=any (default)

Location matches if it has ANY of the specified tags (OR logic)

Example: ?tags[]=retail&tags[]=wholesale returns locations with retail OR wholesale

tagLogic=all

Location must have ALL specified tags (AND logic)

Example: ?tags[]=retail&tags[]=parking&tagLogic=all returns locations with both retail AND parking

tagLogic=match

AND across filter groups, OR within groups. This matches how multi-select filter UIs typically work.

Example: If "retail" and "wholesale" are in the Categories group, and "parking" is in Features, selecting retail + parking returns locations with (retail OR wholesale from Categories) AND (parking from Features)

Sorting

Control result order with the sort parameter:

  • distance (default for radius queries) - Closest locations first
  • name (default for all=true) - Alphabetical by name
  • priority - Apply your configured priority sorting rules

Priority Sorting

If you've configured priority rules in your Storepoint dashboard (e.g., "show flagship stores first within 10 miles"), use sort=priority to apply them. This is useful for promoting certain location types in search results.

Pagination

Use limit and offset for pagination:

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 convenient next/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

  • 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 to fetch the next page (only present if hasMore is true)
  • prev - Full URL to fetch the previous page (only present if not on first page)

Error Handling

Errors return a consistent structure with helpful messages:

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

  • INVALID_TOKEN (404) - Locator token not found or inactive
  • MISSING_COORDINATES (400) - lat/lng required unless all=true
  • INVALID_COORDINATES (400) - lat/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 public endpoint (rotate your key!)

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

Bash
# 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

The API has generous rate limits designed for production use:

  • 1,000 requests per minute per locator token
  • Responses are cached for 60 seconds at the CDN level

If you need higher limits for a specific use case, contact us.

Choose the Right Approach for Your Needs

Storepoint is designed to be flexible. You can use our platform in whatever way works best for your team:

No coding required

Use the Storepoint locator app out of the box. Manage locations via the dashboard, spreadsheet imports, or third-party syncs. Your team can do everything without developer involvement.

Customize the locator

Use our locator app for the UI, but extend its behavior with the Widget JavaScript API. Track analytics events, trigger custom actions, or integrate with your site's functionality.

Custom frontend, managed backend

Build your own UI with this Query API. Your team manages locations in Storepoint's dashboard, your developers query the data to power a completely custom frontend experience.

Fully API-driven

Use the Location Management API to sync locations from your systems, and this Query API to power your custom frontend. Full automation, full control.

Related Resources