Developer docs

Location Management API

Create, update, and delete locations over REST. Point your CRM, ERP, or POS at Storepoint and your locator stays current on its own. Send an address and we geocode it for you.

Base URL: https://api.storepoint.co/admin/v1 Auth: Bearer private API key Server-side only
On this page

Overview

The Location Management API gives you programmatic control over the location data behind your locator. Build a sync pipeline from your existing systems and updates flow through on their own. With it you can:

  • Retrieve paginated lists of locations
  • Get detailed information for a specific location
  • Create new locations
  • Update existing location data
  • Delete locations
  • Read your custom field configuration

This API writes data. Two ways to display it. Locations you sync here power the embedded widget as a drop-in UI, and the Location Query API when you build a custom frontend. Both read the same data.

Authentication

Every endpoint requires a private API key sent as a Bearer token in the Authorization header:

Authorization header
Authorization: Bearer sk_your_api_key

Generate a private API key in the Developer Portal in your Storepoint dashboard. Keys start with sk_. The same page lets you rotate or revoke keys at any time.

Keep this key secret. It grants full administrative access to your locator and locations. Use it from your server only. Keep it out of frontend code, public repositories, and client-side applications. If a key is ever exposed, rotate it from the dashboard right away.

Security best practices

  • Call this API from your backend. Frontend applications should use the Location Query API, which is built for the browser.
  • Store the API key in backend environment variables or a secrets manager.
  • Rotate your API key immediately if it is ever exposed.
  • Share key access with trusted administrators only.
  • Monitor API usage in the Developer Portal and watch for suspicious activity.

Endpoints

Six endpoints cover the full lifecycle: list, read, create, update, delete, and your custom field configuration.

Base URL

All endpoint paths below are relative to:

Base URL
https://api.storepoint.co/admin/v1

GET /locations

Retrieves a paginated list of all locations, published and draft, for the authenticated locator.

Query parameters

All parameters are optional.

Parameter Type Description
limit integer Results per page. Default 10, maximum 500.
page integer Page number. Default 1.
status string Filter by status: published or draft. Omit to get both.

Example request

cURL
curl "https://api.storepoint.co/admin/v1/locations?limit=50&page=1" \
  -H "Authorization: Bearer sk_your_api_key"

Example response

Response
{
    "success": true,
    "locations": [
        {
            "id": "loc_abc123",
            "name": "Store Name",
            "address": "123 Main St",
            "coordinates": {
                "lat": 12.345678,
                "lng": -12.345678
            },
            "description": "Store description",
            "tags": ["tag1", "tag2"],
            "contact": {
                "phone": "555-1234",
                "email": "[email protected]",
                "website": "https://example.com"
            },
            "social": {
                "instagram": "https://instagram.com/downtownstore",
                "facebook": "",
                "twitter": ""
            },
            "hours": {
                "monday": "9:00-17:00",
                "tuesday": "9:00-17:00",
                "wednesday": "9:00-17:00",
                "thursday": "9:00-17:00",
                "friday": "9:00-17:00",
                "saturday": "10:00-15:00",
                "sunday": "closed"
            },
            "custom_fields": {},
            "image_url": "https://example.com/image.jpg",
            "status": "published"
        }
    ],
    "pagination": {
        "page": 1,
        "limit": 10,
        "total": 100,
        "total_pages": 10,
        "next": "/admin/v1/locations?page=2",
        "previous": null
    }
}

GET /locations/{id}

Retrieves detailed information for a specific location. Returns both published and draft locations.

Example response

Response
{
    "success": true,
    "location": {
        "id": "loc_abc123",
        "name": "Store Name",
        "address": "123 Main St",
        "coordinates": {
            "lat": 12.345678,
            "lng": -12.345678
        },
        "description": "Store description",
        "tags": ["tag1", "tag2"],
        "contact": {
            "phone": "555-1234",
            "email": "[email protected]",
            "website": "https://example.com"
        },
        "social": {
            "instagram": "https://instagram.com/downtownstore",
            "facebook": "",
            "twitter": ""
        },
        "hours": {
            "monday": "9:00-17:00",
            "tuesday": "9:00-17:00",
            "wednesday": "9:00-17:00",
            "thursday": "9:00-17:00",
            "friday": "9:00-17:00",
            "saturday": "10:00-15:00",
            "sunday": "closed"
        },
        "custom_fields": {},
        "image_url": "https://example.com/image.jpg",
        "status": "published"
    }
}

POST /locations

Creates a new location. Locations are published by default unless status is set to draft.

Coordinates are optional. We geocode for you. Send an address and Storepoint converts it to coordinates automatically. Include a coordinates object when you already have exact coordinates and want to use those instead.

Body fields

Field Type Description
name string Location name.
address string Full address. Storepoint geocodes it automatically when coordinates is omitted.
coordinates object Optional. lat and lng in decimal degrees. When provided, your coordinates are used as-is.
description string Description shown on the location.
tags array Tags for filtering. Matched case-insensitively, returned in the case you send.
contact object phone, email, and website.
social object instagram, facebook, and twitter profile URLs. Always present in responses.
hours object Opening hours keyed by day. Any text string is accepted.
custom_fields object Custom field values keyed by field ID. See custom fields.
image_url string Location photo URL, including the protocol.
status string published or draft. Defaults to published.

Example request

This request sends an address with no coordinates. Storepoint geocodes it and the response includes the resulting coordinates.

Request
{
    "name": "Store Name",
    "address": "123 Main St",
    "description": "Store description",
    "tags": ["tag1", "tag2"],
    "contact": {
        "phone": "555-1234",
        "email": "[email protected]",
        "website": "https://example.com"
    },
    "hours": {
        "monday": "9:00-17:00",
        "tuesday": "9:00-17:00",
        "wednesday": "9:00-17:00",
        "thursday": "9:00-17:00",
        "friday": "9:00-17:00",
        "saturday": "10:00-15:00",
        "sunday": "closed"
    },
    "custom_fields": {
        "cf812sj12": "Free parking",
        "feu3hsw32": "yes",
        "hs2372a42": "Available"
    },
    "image_url": "https://example.com/store-photo.jpg",
    "status": "published"
}

Example response

Response
{
    "success": true,
    "location": {
        "id": "loc_abc123",
        "name": "Store Name",
        "address": "123 Main St",
        "coordinates": {
            "lat": 12.345678,
            "lng": -12.345678
        },
        "description": "Store description",
        "tags": ["tag1", "tag2"],
        "contact": {
            "phone": "555-1234",
            "email": "[email protected]",
            "website": "https://example.com"
        },
        "social": {
            "instagram": "https://instagram.com/downtownstore",
            "facebook": "",
            "twitter": ""
        },
        "hours": {
            "monday": "9:00-17:00",
            "tuesday": "9:00-17:00",
            "wednesday": "9:00-17:00",
            "thursday": "9:00-17:00",
            "friday": "9:00-17:00",
            "saturday": "10:00-15:00",
            "sunday": "closed"
        },
        "custom_fields": {
            "cf812sj12": "Free parking",
            "feu3hsw32": "yes",
            "hs2372a42": "Available"
        },
        "image_url": "https://example.com/store-photo.jpg",
        "status": "published"
    }
}

POST /locations/{id}

Updates an existing location. All fields are optional. Only the fields you send are updated. Works with both published and draft locations.

When you update the address, Storepoint re-geocodes it automatically. Send a coordinates object to set coordinates yourself instead.

Example request

Request
{
    "name": "Updated Store Name",
    "address": "123 Main St",
    "description": "Updated description",
    "tags": ["updated_tag"],
    "contact": {
        "phone": "555-5678",
        "email": "[email protected]",
        "website": "https://updated.com"
    },
    "hours": {
        "monday": "9:00-18:00",
        "tuesday": "9:00-18:00",
        "wednesday": "9:00-18:00",
        "thursday": "9:00-18:00",
        "friday": "9:00-18:00",
        "saturday": "10:00-16:00",
        "sunday": "closed"
    },
    "custom_fields": {
        "cf812sj12": "Updated parking info",
        "feu3hsw32": "no",
        "hs2372a42": "Not available"
    },
    "image_url": "https://example.com/updated-photo.jpg",
    "status": "published"
}

Example response

Response
{
    "success": true,
    "location": {
        "id": "loc_abc123",
        "name": "Updated Store Name",
        "address": "123 Main St",
        "coordinates": {
            "lat": 12.345678,
            "lng": -12.345678
        },
        "description": "Updated store description",
        "tags": ["updated_tag"],
        "contact": {
            "phone": "555-5678",
            "email": "[email protected]",
            "website": "https://updated-example.com"
        },
        "social": {
            "instagram": "https://instagram.com/downtownstore",
            "facebook": "",
            "twitter": ""
        },
        "hours": {
            "monday": "9:00-18:00",
            "tuesday": "9:00-18:00",
            "wednesday": "9:00-18:00",
            "thursday": "9:00-18:00",
            "friday": "9:00-18:00",
            "saturday": "10:00-16:00",
            "sunday": "closed"
        },
        "custom_fields": {
            "cf812sj12": "Updated parking info",
            "feu3hsw32": "no",
            "hs2372a42": "Not available"
        },
        "image_url": "https://example.com/updated-store-photo.jpg",
        "status": "published"
    }
}

POST /locations/{id}/delete

Deletes a location. Works with both published and draft locations.

Example response

Response
{
    "success": true,
    "message": "Location deleted successfully"
}

GET /custom_fields

Retrieves the custom fields configured for your locator. Each field has an id. Use those IDs to identify or set custom fields when getting, creating, or updating locations.

Example response

Response
{
    "success": true,
    "custom_fields": [
        {
            "id": "cf812sj12",
            "name": "Field Name",
            "type": "text"
        }
    ]
}

Using custom fields. When creating or updating locations, use the field IDs as keys in the custom_fields object. For example: "custom_fields": { "cf812sj12": "Free street parking", "feu3hsw32": "yes" }

Error responses

All endpoints may return the following error responses.

Authentication error (401)

Returned when the API key is missing, invalid, inactive, or expired. The message explains which.

Response
{
    "error": "Authentication failed",
    "message": "Invalid or inactive token"
}

Invalid request (400)

Returned for bad request shapes: an invalid limit or page, a limit above 500 (limit_exceeded), a missing location ID, or an update with no valid fields.

Response
{
    "error": "invalid_request",
    "message": "No valid fields provided for update"
}

Geocoding error (422)

Returned when you send an address without coordinates and the address can't be geocoded. Fix the address or include a coordinates object.

Response
{
    "error": "geocoding_failed",
    "message": "Unable to geocode the provided address. Please provide coordinates or verify the address."
}

Validation error (422)

Response
{
    "error": "validation_error",
    "message": "Invalid input data",
    "details": {
        "field_name": ["Error message"]
    }
}

Not found error (404)

Response
{
    "error": "not_found",
    "message": "Location not found"
}

Server error (500)

Response
{
    "error": "error",
    "message": "Error message"
}

Technical notes

  • All location IDs are prefixed with loc_ followed by random lowercase alphanumeric characters.
  • Coordinates are optional. Send an address and Storepoint geocodes it automatically. When you provide coordinates, use decimal degrees.
  • Hours can be provided as any text string. Common formats like 24-hour time ranges (HH:MM-HH:MM) or closed are recommended for consistency but are open to whatever suits your data.
  • Tags are matched case-insensitively and returned in the case you send them. You can organize tags into filters and groups in the Tags & Filters area of your dashboard.
  • Custom field keys must match the field IDs returned by the custom fields endpoint.
  • All URLs (website, image_url, social profiles) must be full URLs including the protocol (https://).
  • Status: locations are either published (visible on your store locator) or draft (hidden from the public locator). New locations default to published if not specified. Legacy values hidden, inactive, and unpublished are accepted and treated as draft.