Developers
Build on your locator from the server or the page.
On the server, account-scoped keys read and write locations, answer nearest-location queries and subscribe to signed webhooks. In the browser, the embedded element takes method calls from your page and dispatches events when visitors act. An MCP server puts the same account within reach of Claude, ChatGPT and other AI assistants.
AI assistants
MCP server
Manage your locator from Claude, ChatGPT, Cursor, or any MCP client. Add locations, restyle the widget and get your embed code by chatting.
Read the docsREST
Location API
Read, create, update and archive locations over HTTP with a bearer key, for systems that own the data.
Read the docsREST
Query API
Ask what is near a point and get visible locations back nearest-first, ranked the way the widget ranks them, for a front end of your own.
Read the docsPush
Webhooks
Signed HTTP calls to your URL when a location is created, updated or deleted, or a visitor sends an enquiry. Retried for two days.
Read the docsBrowser
Widget JavaScript API
Methods on the embedded element: run a search, set filters, open a location or read the state from your own page script.
Read the docsBrowser
Widget events
The events the embedded locator dispatches on the page, for analytics and for wiring the widget into the rest of your site.
Read the docsPick the surface by the job
- Keep locations in step with a system you own
- Write with the Location API and register a webhook, so a change made in the dashboard reaches your system without polling. Location API
- Build your own store-finder page or app
- Call the Query API with a read-only key. Hidden locations stay hidden, and results come back in the order the widget would show them. Query API
- Put a search box in your header or a find-near-me button on a product page
- Call methods on the embedded element from your own script. For a search box on a different page, a plain form and URL parameters are enough. Widget JavaScript API
- Send locator activity to your analytics
- Listen for the widget's browser events and push the ones you need into Google Tag Manager or your own tooling. Widget events
- Pass enquiries to a CRM, a sheet or Slack without code
- Use Zapier, through the Handled Locator app for Zapier or Zapier's own webhook steps. Both run on the same webhooks and API. Zapier
- Keep locations in a spreadsheet or CMS
- Connect Google Sheets, Airtable, Webflow CMS or HubSpot as a sync source from the dashboard. No key and no code. Sync sources
- Change locations or styling by describing the change
- Connect the MCP server to Claude, ChatGPT or another client. Configuration changes are proposed with the exact differences before anything goes live. MCP server
Server side
Location and Query APIs
JSON over HTTPS at /api/v1, with the key sent as a bearer token. Send an address without coordinates and Handled geocodes it; if the lookup fails the location is still created and flagged in the dashboard. The Query API ranks with the same function the widget uses, so a page you build and the locator agree on what is nearest. Hidden locations stay hidden unless you ask for them, and online stockists are left out of distance queries because they have no coordinates.
GET /api/v1/locationsList locations, newest first, with limit, offset, visibility and search.
GET /api/v1/locations/:idRead one location.
POST /api/v1/locationsCreate a location. An address without coordinates is geocoded.
PATCH /api/v1/locations/:idChange only the fields you send. A null clears a field; an absent one is left alone.
DELETE /api/v1/locations/:idTake a location off the locator. Soft, so its analytics history survives.
GET /api/v1/queryVisible locations near a point or matching a tag or text, nearest-first with a distance.
Push
Webhooks
Register an HTTPS endpoint and Handled posts the full record to it, signed, when something changes. The signature is an HMAC-SHA256 of the timestamp and the raw body under the endpoint’s secret. Answer with a 2xx quickly and do the work afterwards: a delivery without one is retried for roughly two days, each delivery arrives at least once, and order is not guaranteed. Endpoints can be managed over the API, which is how an integration subscribes itself.
location.createdA location was added, restored from the bin, or created by an import or sync.
location.updatedAny field on a location changed, including tags, custom fields, visibility and photo.
location.deletedA location was moved to the bin. It can be restored, which fires location.created.
lead.createdA visitor sent an enquiry through the locator's form, after it was routed to a dealer.
In the browser
Widget JavaScript API
The <biz-locator> element the embed creates has methods your page can call. Calls made before the locator has loaded are queued and replayed in order, so your script never has to wait. Links can carry the same state without any script, and an embed can be locked to a subset of locations with a tag list.
search()Set the keyword search. No geocoding.
searchNear()Search near a place name, geocoded as if typed, or near exact coordinates.
setFilters()Replace the active filters by tag name, slug or id, and report which matched.
clearFilters()Remove every filter.
openLocation()Open one location the way a click on its card would.
closeLocation()Close the open detail pane or popup.
locate()Ask for the visitor's position and search near it.
reset()Return to the starting state: no search, no filters.
getState()Read the current query, place, radius, filters and result count.
setLanguage()Show the interface in one of the account's languages.
getLocations()The locations currently listed, in order, with distance when there is a search point.
In the browser
Widget events
The element dispatches versioned events that bubble out of its shadow root, so a listener on the element or on the document receives them. Payloads carry the mode, counts and location ids, and deliberately omit what the visitor typed, the place it resolved to, their coordinates and any contact details. A search or selection made through a method fires the same events as a visitor’s.
handled:readyLocations and settings have loaded.
handled:searchA text or near-a-place search ran, with its mode and result count.
handled:no-resultsA search or filter state produced nothing.
handled:location-selectedA visitor, or your script, selected a card, marker or online location.
handled:directions-clickedA visitor opened directions.
handled:action-clickedA visitor used phone, email, website or a linked custom field.
One key, every server surface
The REST API, the Query API, webhook management and the MCP server take the same key and enforce the same rules: your account, your plan’s location allowance, and read-only keys that cannot write. An account owner creates keys under Settings, then API & developer tools. A key is shown once and stored only as a hash, starts with hl_live_, is rate limited per minute with separate read and write budgets, and can be revoked at any time. Claude and ChatGPT need no key: they connect to the MCP server by signing in.
- MCP endpoint
https://app.handledlocal.com/api/mcp- Authorization header
Authorization: Bearer hl_live_your_key
The MCP server is included on every plan, including the 7-day trial. The REST API, the Query API and webhooks are Pro and Business features. See pricing.
What these surfaces do not do
- Categories are created in the dashboard. The API's tag filter matches categories that already exist.
- Widget settings, branding and labels are not part of the REST API. The dashboard and the MCP server change them.
- Visitor searches, map moves and clicks stay in the browser as events. They are never sent as webhooks.
- Handled does not write back into your CRM or other systems. A change reaches them only through a job you write against the webhooks and the API.
- One account serves one locator, so there is no method for mounting a second, differently configured widget on a page.