Advice Local API
The Warpath API gives agencies and brands programmatic control over local listing management, reputation, AI presence, and reporting — across 3.7 million+ managed locations.
Overview
The Advice Local API — internally named Warpath — is the programmatic backbone of the entire platform. Through it, you can create and manage business locations, activate products, push rich data to hundreds of directories, and pull the reporting metrics your clients care about. Everything that happens in the Advice Local dashboard can also be driven entirely through API calls, making it straightforward to embed local listing management into your own portals, CRMs, or automated workflows.
The API is RESTful: resources are nouns, HTTP verbs express intent, and every response comes back as JSON. There is one base URL for all operations:
https://p.lssdev.com
Regardless of whether a request succeeds or fails, the response always follows the same predictable envelope. This means your error-handling logic can be written once and reused across every endpoint — check success first, then branch on data or error.
true on success, false on any errornull on successnullAuthentication
Every request to the Warpath API must include your API key. Authentication is intentionally simple: there are no OAuth flows, no token exchanges, no sessions to manage. You place your key in a single custom header called x-api-token, and the API grants access scoped to your partner account. All clients, orders, and data belonging to your account are accessible using this single credential.
Your API key is issued when your partner account is set up. If you need to locate it, log in to the Advice Local dashboard and navigate to your account settings. Treat it like a password — if it is ever compromised, contact Advice Local support to have it rotated immediately.
| Header | Value | Required |
|---|---|---|
x-api-token | Your secret API key | Required |
Content-Type | application/json (or application/x-www-form-urlencoded for form posts) | Required |
Keep your API key secret. It provides full partner-level access to all clients, orders, and billing data.
Example
GET /legacyclients/3201926 HTTP/1.1
Host: p.lssdev.com
x-api-token: YOUR_API_KEY
Content-Type: application/json
Errors & Responses
The Warpath API uses standard HTTP status codes, and every response — including errors — wraps its payload in the same envelope described above. When something goes wrong, the success field will be false and the error field will contain a plain-language description of what happened. The data field will be null. This consistent shape means you never need to guess whether an empty body or a 2xx status with a failure message is possible — if the request failed, success is always false.
The most common errors to handle are 401 Unauthorized (your API key is missing or wrong) and 404 Not Found (the resource ID does not exist or does not belong to your partner account). Validation errors typically come back as 400 Bad Request with a description of which field was problematic.
// Error response
{
"status": 404,
"success": false,
"data": null,
"error": "Sorry, there was an error retrieving the requested resource."
}
| Status | Meaning |
|---|---|
200 | Success |
400 | Bad request — missing or invalid parameters |
401 | Unauthorized — invalid or missing API key |
404 | Resource not found |
500 | Server error — contact support |
Quickstart Flow
If you are building an integration from scratch, the quickest path to a fully live location follows five steps. Each step depends on the one before it, so it helps to understand the full sequence before you start writing code.
The first thing to do is pull the product catalog with GET /legacyproducts. Products represent the services Advice Local will activate for a location — listing distribution, rank tracking, reputation management, and so on. Each product has a numeric ID you will need when placing an order, so fetch and cache this list early. Product IDs do not change frequently, but it is good practice to refresh them periodically.
Next, create the business location using POST /legacyclients. This is where you submit the NAP data — Name, Address, Phone — along with the category, description, and any extended information. The API returns a client_id that becomes the anchor for every subsequent operation: orders, images, reports, and data queries all reference it.
With a client ID in hand, you can place an order. Orders associate one or more products with a client and charge the partner's card on file. Once the order is placed and marked isPaid: true, Advice Local begins the fulfillment process — pushing the business data out to the directories included in the ordered products.
Fulfillment is not instant. Depending on the directory, it can take anywhere from a few hours to a few days for a listing to go live. Use POST /legacyfulfillmentdata to poll the status of each directory. When a listing is live, the url field will contain the public link to the live listing.
Once fulfillment is underway, reporting data starts to populate. Use GET /legacyclients/{id}/report to retrieve the full baseline report, or pull individual score and insight endpoints for the specific metrics you want to surface.
GET /legacyproducts
POST /legacyclients
POST /legacyorders
POST /legacyfulfillmentdata
GET /legacyclients/{id}/report
Cards must be added through the Advice Local dashboard — they cannot be created via API. Retrieve your saved card IDs with GET /cards before placing orders.
Clients
In Advice Local's data model, a client represents a single physical business location. If you are managing a franchise with 50 locations, that means 50 client records — one per address. Each client gets a unique numeric id assigned at creation, and that ID is the key you will pass to every other endpoint in the API: orders reference it, images attach to it, reports are scoped to it, and fulfillment data is queried by it.
Clients move through a lifecycle. When first created, a client's status is Inactive. Once an order is placed and fulfilled, it becomes Active. If the account is suspended or paused it will reflect those states too. The status field is read-only — it is managed by the platform based on subscription and billing state, not set directly via the API.
The quality and completeness of the data you submit here directly affects listing performance. Every field that you populate — category, hours, description, website, coordinates — gives the Data Amplifier Network more signals to push to directories and to use when optimizing for voice and AI-powered search. Incomplete records publish with incomplete data, which hurts NAP consistency scores. It is worth taking the time to get the full profile right at creation rather than patching it later.
The API only supports printable ASCII. All unicode characters — including smart quotes, accented characters, and emoji — will be stripped from client fields before the record is saved. Sanitize your input on the client side to avoid unexpected data loss.
Client Object Fields
| Field | Type | Max | Notes | |
|---|---|---|---|---|
id | integer | — | Readonly | Auto-assigned on create |
name | string | 128 | Required | Business name |
street | string | 128 | Required | |
city | string | 128 | Required | |
state | string | 64 | Required | US state code or Canadian province code |
zipcode | string | 32 | Required | |
phone | string | 32 | Required | |
description | string | — | Required | Business description |
country | string | — | Optional | US (default), CA, GB, AU, DE, NZ |
website | string | — | Optional | |
email | string | — | Optional | |
categoryGoogle | string | 255 | Optional | Single GCID — strip the gcid: prefix |
hoursObject | JSON | — | Optional | Structured hours — see Hours Format |
hoursSpecialObject | JSON | — | Optional | Holiday / exception hours |
LAT / LON | string | — | Optional | Geolocation override |
hide | boolean | — | Optional | Hides client address from directories |
extra | JSON | — | Optional | Voice, GMB, vertical data — see Extra Object |
status | string | — | Readonly | Active, Inactive, Paused, or Widget Lead |
publicKey | string | — | Readonly | Public identifier |
Create a Client
Creating a client is the first real operation in any integration. You submit the business's core NAP data — name, address, phone — along with a description and optionally a Google category, website, hours, and geolocation. The minimum required fields will create a valid record, but a richer submission means better directory coverage from day one.
The request body can be sent as either application/x-www-form-urlencoded or application/json. Form encoding is fine for simple field sets; JSON is easier when you need to include structured values like hoursObject or extra.
Request
POST /legacyclients HTTP/1.1
Host: p.lssdev.com
x-api-token: YOUR_API_KEY
Content-Type: application/x-www-form-urlencoded
name=Gina+Pizza&street=3142+W+Balboa+Blvd&city=Newport+Beach
&state=CA&zipcode=92663&phone=(949)+723-4462
&description=Authentic+Italian+pizza+since+1992
&categoryGoogle=restaurant
Response
{
"status": 200,
"success": true,
"error": null,
"data": {
"id": 3201926,
"status": "Inactive",
"name": "Gina Pizza",
"country": "US",
"publicKey": "e343f4531abf70d03706727af93006c8",
"partner": 7,
"createdAt": "2017-12-12T23:59:44.077Z"
}
}
Save the returned id — it is the client_id used in every subsequent API call for this location.
Get / List Clients
Fetching a single client by ID returns the full record exactly as it is stored — all fields, including read-only values like status, publicKey, and timestamps. This is useful when you need to read the current state of a location before performing an update, or when you want to verify that a recently submitted change was applied correctly.
The list endpoint returns all clients associated with your partner account, paginated. By default it returns 20 records sorted by ID ascending, but you can tailor the query significantly using the parameters below. For large accounts managing thousands of locations, pagination and filtering are essential — pulling the full list in a single request without a limit can produce very large payloads and slow response times.
The where parameter accepts a JSON-encoded filter object using a Waterline-style query syntax. You can filter by partial string match (contains), exact value, or comparison operators. For example, to find all active locations in California: where={"state":"CA"}&status=Active.
List Query Parameters
| Parameter | Default | Description |
|---|---|---|
limit | 20 | Max records per page |
skip | 0 | Records to skip (offset) |
sort | id ASC | E.g. name ASC or createdAt DESC |
where | — | JSON filter, e.g. {"name":{"contains":"pizza"}} |
status | — | Filter by status: Active, Inactive, Paused, Widget Lead |
city / state | — | Field-level filters |
country | US | US, GB, CA, AU, DE, or NZ |
isInactive | — | Boolean filter for inactive clients |
deleted | — | Include deleted clients |
keywords | — | Array of search keywords |
createdAt / updatedAt | — | ISO date-time filters |
callback | — | JSONP callback function name |
Paginated List Example
GET /legacyclients?limit=50&skip=0&sort=name%20ASC&status=Active HTTP/1.1
Host: p.lssdev.com
x-api-token: YOUR_API_KEY
Update a Client
Updating a client is a partial update by design — you only need to include the fields you want to change. The API will merge your payload into the existing record, leaving untouched fields exactly as they were. This makes it safe to update a single field like phone without needing to re-submit the entire client object.
This is particularly important for the extra field, which is a deeply nested JSON object. If you write to extra, always read the existing value first, merge your changes in memory, and then write the merged result back. Sending only a partial extra object will replace the entire field with just the keys you submitted, silently erasing any data that was already there.
Updates to core NAP fields — name, address, phone — will propagate to all connected directories on the next sync cycle. There is no need to manually trigger a re-push after an update; Advice Local detects the change and schedules propagation automatically.
PUT /legacyclients/3201926 HTTP/1.1
Host: p.lssdev.com
x-api-token: YOUR_API_KEY
Content-Type: application/json
{
"phone": "(949) 555-0100",
"website": "https://ginapizza.com"
}
Delete & Reactivate
Deleting a client stops the platform from managing that location. All active products associated with the client are automatically disabled — meaning directory listings will no longer be updated, rank tracking will stop, and reports will stop refreshing. The client record itself is preserved in a soft-deleted state so that its data and history remain accessible, but it will not appear in default list queries unless you pass deleted=true.
If a client was deleted by mistake, or if a previously inactive location needs to come back online, use the reactivate endpoint. This re-enables the client and attempts to restore billing and fulfillment for any products that were active at the time of deletion. It is a clean recovery path for scenarios like a seasonal business that closes and reopens.
// DELETE response
{
"status": 200,
"success": true,
"error": null
}
SSO & Dashboard URLs
These endpoints are designed for white-labeling scenarios where you want to expose the Advice Local reporting interface inside your own product without requiring your customers to maintain a separate Advice Local login.
The /sso endpoint generates a short-lived, pre-authenticated URL. When a user clicks it, they land directly in the client's report view without any login prompt. Because the token expires, you should generate a fresh SSO URL each time rather than storing it. This makes it ideal for embedding in transactional emails, portal pages that are rendered server-side, or anywhere the link is consumed immediately.
The /url endpoint returns a permanent link to the same dashboard. Unlike the SSO link, this URL does not contain a one-time token — it is suitable for bookmarking or embedding in places where the same URL will be reused repeatedly. In both cases, the link goes to a white-labeled domain configured for your partner account, so the end user sees your branding rather than Advice Local's.
The PDF report endpoint (/pdf) can take up to 120 seconds to respond. The returned data field is an S3 URL to the rendered PDF file.
// SSO response
{
"status": 200,
"success": true,
"data": "https://mysite.advicelocal.com/?page=site/clients/monthly-progress&client_id=3201926&lss_token=c1c55a63"
}
Additional PDF/report endpoints available:
Client Images
Visual assets play a significant role in how a business listing performs across directories. Advice Local supports uploading a logo, social cover images for Facebook, Google, and Twitter, and up to five gallery images that are pushed to directories supporting photo content. All images are stored in S3 and referenced by named keys — so when you retrieve the image list, each key returns both an original URL and a thumbnail URL.
Gallery images are uploaded to the untagged endpoint and are automatically slotted as gallery_image_1 through gallery_image_5. Named images — logo, cover photos — use the tagged endpoint where the tag becomes part of the URL path. To replace an existing image, simply upload a new one using the same tag; to remove it entirely, use the DELETE endpoint with the image name returned by the GET.
All image uploads should be sent as multipart/form-data with the file attached in the file field. The Google-specific image endpoints (/legacyclientimages/google/...) are managed separately and covered in the Google Images section.
Image Tags
| Tag | Description |
|---|---|
logo | Business logo |
facebook_cover | Facebook cover image |
google_cover | Google Business Profile cover |
twitter_cover | Twitter/X cover image |
| (none) | Gallery images — auto-named gallery_image_1 through gallery_image_5 |
// Upload logo — multipart/form-data
POST /legacyclientimages/3201926/logo HTTP/1.1
Host: p.lssdev.com
x-api-token: YOUR_API_KEY
Content-Type: multipart/form-data; boundary=----boundary
// Attach image file in form field "file"
Get Images Response
{
"status": 200,
"success": true,
"data": {
"logo": {
"original": "https://s3.amazonaws.com/.../logo.jpg",
"thumbnail": "https://s3.amazonaws.com/.../logo_thumb.jpg"
},
"gallery_image_1": {
"original": "https://s3.amazonaws.com/.../gallery_1.jpg",
"thumbnail": "https://s3.amazonaws.com/.../gallery_1_thumb.jpg"
}
}
}
Extra & GMB Data
The extra field is the extensibility layer of the client record. It is a free-form JSON object where Advice Local stores data that does not fit neatly into the core NAP fields — most importantly, Google Business Profile enrichments, voice search configuration, and industry-vertical data for healthcare and legal practices.
Because extra is a single JSON blob, you must treat it carefully during updates. The golden rule is: always read before you write. Fetch the current client record, extract the existing extra value, merge your new data into it in memory, and then PUT the merged object back. If you send a partial extra object, the API will replace the entire field with what you sent — silently deleting any keys that were already there.
The most commonly used sub-structures within extra are gmbData (for Google Business Profile enrichments), voiceTemplates and voiceQuestions (for AdVoice configuration), and verticals (for healthcare and legal data required by specialized directories).
GMB Extended Properties (extra.gmbData)
| Property | Type | Notes |
|---|---|---|
primaryCategory | Category object | {"categoryId":"gcid:restaurant","displayName":"Restaurant"} |
secondaryCategories | Category[] | Array of additional GCID categories |
products | Product[] | See Product format below |
specialHoursPeriods | Period[] | Holiday/exception hours |
appointmentLink | URL string | |
servicesArea | string[] | ZIP codes or city names |
servicesOffered | string[] | |
languages | string[] | |
gmbShortName | string | |
callTrackingNumber | number |
Product Format
{
"name": "Margherita Pizza",
"category": "Pizzas",
"summary": "Classic tomato sauce, fresh mozzarella, basil",
"price": 18,
"callToAction": {
"actionType": "ORDER",
"url": "https://ginapizza.com/order"
}
}
Valid actionType values: BOOK, ORDER, SHOP, LEARN_MORE, SIGN_UP, GET_OFFER, CALL
Voice Data (extra.voiceTemplates / extra.voiceQuestions)
AdVoice is Advice Local's voice search optimization feature. When configured, it generates a JSON-LD FAQ schema on the client's behalf that is submitted to voice assistants like Google Assistant, Siri, Bixby, and Alexa. The schema is built from two sources: questions that are automatically generated from the client's existing data (hours, location, payment methods), and custom questions you supply via voiceQuestions.
You first select an industry template using voiceTemplates — this tells the system which pre-built question categories are relevant. Only one template should be active at a time. You then provide the answers to the custom questions for that template using voiceQuestions, formatted as JSON-LD Question/Answer objects. The question strings must match the expected values exactly — they are used as lookup keys, not free-text.
{
"voiceTemplates": ["restaurants"],
"voiceQuestions": [
{
"@type": "Question",
"name": "What is your busiest day of the week?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Friday"
}
}
]
}
Template options: brick (brick-and-mortar retail), services, events, financial, healthcare, home (home services), legal, restaurants. Apply only one at a time.
Healthcare Vertical (extra.verticals["4130"])
Healthcare providers can submit extended clinical and credential data through the verticals["4130"] object. This data is required by several specialized health directories and improves the richness of the provider's listing. Fields include the NPI number, DEA number, insurance accepted, conditions treated, and medical training history. The updateAt timestamp (a Unix millisecond timestamp) should be set to the current time whenever you write this data, so that downstream systems know which version is most recent.
{
"extra": {
"verticals": {
"4130": {
"updateAt": 1718040420413,
"data": {
"conditions_treated": "Hypertension, Diabetes",
"insurance_accepted": "Blue Cross, Medicare",
"license_number": "TX12345",
"accepting_new_patients": "yes",
"npi": "1234567890"
}
}
}
}
}
Legal Vertical (extra.verticals["4136"])
{
"extra": {
"verticals": {
"4136": {
"updateAt": 1718059904266,
"data": {
"state_licensed_in": "Texas",
"specific_practices": "Family Law, Estate Planning",
"year_license_received": "2002"
}
}
}
}
}
Hours Format
Business hours are one of the most important NAP fields for local listings — directories that display hours drive customer decisions directly. Advice Local uses a structured JSON format for hours rather than free-text strings, which ensures that the data can be accurately interpreted and displayed regardless of how each directory formats hours on its own end.
Hours are submitted as an array of period objects inside hoursObject. Each period defines an opening day/time and a closing day/time. When a business has the same hours every day, you submit seven identical periods (one per day). When hours vary by day, each day gets its own period. Days are full uppercase strings (MONDAY, TUESDAY, etc.) and times use 24-hour HH:MM format.
// Regular weekly hours
{
"periods": [
{
"openDay": "MONDAY",
"openTime": "09:00",
"closeDay": "MONDAY",
"closeTime": "21:00"
},
{
"openDay": "FRIDAY",
"openTime": "09:00",
"closeDay": "SATURDAY", // spans midnight
"closeTime": "02:00"
}
]
}
For 24-hour operation use "openTime": "00:00" and "closeTime": "00:00". Split-day periods (two entries for the same day) are supported — directories that don't support split hours will receive the earliest open and latest close time.
Special / Holiday Hours (hoursSpecialObject)
{
"specialHourPeriods": [
{
"startDate": { "year": 2025, "month": 12, "day": 25 },
"endDate": { "year": 2025, "month": 12, "day": 25 },
"openTime": "12:00",
"closeTime": "17:00"
}
]
}
Orders
An order is the mechanism that activates one or more products for a client location. Think of it as the subscription record — it ties a billing card to a client and a set of products, and once placed and paid, it triggers Advice Local to begin fulfillment work on that location. Without an order, a client exists in the system but nothing is being done for them.
Orders are immutable after creation. You cannot add products to an existing order, remove individual products from it, or change the card it was charged to. If a location's service needs to change, the typical workflow is to place a new order with the updated product set. Orders can be deleted, but doing so is destructive and will disable the associated products — use that endpoint with caution.
Before you can place an order, you need two IDs: the client ID for the location, and the card_id for the billing card to charge. Payment cards must be added through the Advice Local dashboard — there is no API endpoint to create them. Use GET /cards to retrieve the IDs of cards already on file for your account.
Place an Order
Request Body
| Field | Description | |
|---|---|---|
client | Required | Client ID from POST /legacyclients |
products | Required | Array of product IDs from GET /legacyproducts |
card_id | Required | Card ID from GET /cards |
POST /legacyorders HTTP/1.1
Host: p.lssdev.com
x-api-token: YOUR_API_KEY
Content-Type: application/json
{
"client": 3201926,
"products": [101, 205],
"card_id": "card_1AbCdEfGhIjKlMn"
}
Response
{
"status": 200,
"success": true,
"data": {
"id": 88291,
"price": 49.00,
"discount": 0,
"isPaid": true,
"isVerified": true,
"isDrip": false,
"transactionId": "txn_abc123",
"products": [ /* ordered product objects */ ]
}
}
Get / List Orders
Fetching a single order by its ID returns the full order record including the transaction ID, charge ID, payment status, and the array of product objects that were activated. This is useful for verifying that a specific order was placed and paid successfully, or for displaying order history to a client.
The list endpoint returns all orders across your entire partner account. If you manage many locations, this can be a large dataset — use it for auditing or reconciliation purposes rather than real-time lookups. For checking what products are currently active for a specific client, the POST /legacyorderproducts endpoint is more targeted.
Ordered Products Data
This endpoint provides a flat view of all active (or disabled) products ordered within your partner account, optionally filtered by client. Where the orders endpoints show you the billing records, this endpoint shows you the operational state — which specific products are running for which clients, when they were activated, and whether they are currently enabled.
The isDisabled and disabledAt fields are particularly useful for building dashboards. A product with isDisabled: false is actively running. A product where isDisabled: true and disabledAt is set to any date other than 2017-10-01 was explicitly turned off — either the order was deleted or the product was individually disabled. The sentinel date 2017-10-01 is a special value that indicates the product was indirectly disabled because its parent client or the partner account became inactive.
Query Parameters
| Parameter | Description |
|---|---|
client | Filter by client ID |
disabled | true or false — filter by disabled status |
A disabledAt value of 2017-10-01 indicates the product was indirectly disabled (e.g. inactive client or partner). Any other date means it was explicitly disabled.
Delete an Order
Destructive and irreversible. Permanently removes the order and disables all associated products. Double-check the order ID before calling this endpoint.
Fulfillment Data
Once an order is placed, Advice Local begins distributing the business's data to each directory included in the purchased products. Fulfillment is the process of actually getting the listing live on each directory — and this endpoint lets you monitor that process in detail. You can call it at any time after an order is placed to see the current state of each individual directory submission.
The response returns one record per directory, showing whether the listing is live (status: "live"), still in progress (pending), or experiencing an issue (temporary_problem). When a listing goes live, the url field will be populated with the direct link to the listing page. The dateUrl field (available in API v4.15 and later) records the first date a URL was detected, which you can use to measure time-to-live across your client portfolio.
The type field distinguishes between directories that Advice Local manages via a direct API connection (api) and those managed manually by the fulfillment team (manual). Manual directories may have longer fulfillment timelines and might include notes from the team in the comment field.
POST /legacyfulfillmentdata?client=3201926 HTTP/1.1
Host: p.lssdev.com
x-api-token: YOUR_API_KEY
Response Fields
| Field | Description |
|---|---|
directory | Directory name (e.g. "Yelp", "Google") |
status | Fulfillment status (e.g. live, temporary_problem, pending) |
url | Live listing URL if available |
type | manual or api |
dateCreated | When listing data was first initialized |
dateUrl | Date a live URL was first detected (API v4.15+, Feb 2020) |
dateUpdated | Last modified timestamp |
comment | Notes from fulfillment team or automated process |
username / password | Credentials used or created for the listing account |
email | Account email (may differ from business email) |
statusInitial | Original status at time of submission |
Products
The products endpoint returns the catalog of services available to your partner account. Each product represents a specific offering — listing distribution to a particular set of directories, rank tracking, reputation management, AI presence optimization, and so on. Products are configured at the platform level by Advice Local and vary by partner account based on your agreement and the markets you serve.
You will need product IDs when placing orders, so this is typically one of the first calls you make when setting up an integration. The catalog does not change frequently, but it is worth refreshing it periodically to pick up any new products that have been made available to your account. Products flagged with isDisabled: true are not available for new orders, even if they appear in the list. The hasFulfillment flag tells you whether the product has directory fulfillment tracking, which determines whether /legacyfulfillmentdata will return data for it.
GET /legacyproducts HTTP/1.1
Host: p.lssdev.com
x-api-token: YOUR_API_KEY
Product Object Fields
| Field | Type | Description |
|---|---|---|
id | integer | Use this ID when placing orders |
name | string | Product display name |
description | string | Product description |
priceRetail / priceReseller | number | Pricing tiers |
maintenanceInterval | string | e.g. "Yearly" |
renewalInterval | string | e.g. "yearly" |
productType | string | e.g. "primary" |
isDisabled | boolean | Whether product is currently available |
hasFulfillment | boolean | Whether fulfillment tracking applies |
country | string | Country restriction if applicable |
Client Report
The client report is the most comprehensive data endpoint in the API. It returns everything Advice Local knows about a location's online visibility at the time of the last scan — aggregate scores for Google, Bing, and Yelp; per-directory status for every listing in the account; NAP consistency grades; voice assistant test results; and a breakdown of each local source's individual scores for claimed status, photos, reviews, hours accuracy, and website presence.
The report is structured in two layers. The data.overview section gives you the headline numbers — the same scores that appear on the dashboard summary view. The data.baseline section is the detailed breakdown: each local source (Google, Bing, Yelp) gets its own object with granular scoring, and each directory in the account gets an entry in the directories[] array showing whether it was found, what the listing URL is, and how well the NAP data matches.
Reports are generated asynchronously. After triggering a refresh with GET /legacyclients/{id}/refresh, the report endpoint will continue to return the previous report until the new scan completes. To check if a fresh score is ready, poll /legacyscores and check the isComplete field before pulling the full report.
GET /legacyclients/3201926/report HTTP/1.1
Host: p.lssdev.com
x-api-token: YOUR_API_KEY
Response Structure
| Path | Description |
|---|---|
data.overview.baselineOverview | Aggregate scores: visibilityScore, gmbScore, yelpScore, bingScore, napScore, voiceScore |
data.baseline.locals[] | Per-source data for Google, Bing, Yelp — score, claimed, hours, reviews, photos, NAP |
data.baseline.directories[] | Per-directory data: name, type, found, score, link, NAP breakdown |
data.baseline.voice[] | Voice assistant scores — Google Assistant, Siri, Bixby, Alexa, Cortana |
Directory types: directory, aggregator, ftp
Additional report aliases:
Scores
While the report endpoint always returns the most recent data, the scores endpoint maintains a historical log of score snapshots over time. This lets you build trend charts, detect regressions, and show clients their progress since onboarding. Each record in the scores table represents one completed scan cycle for a client.
The most common query pattern is to fetch the single most recent score for a location using sort=id DESC&limit=1. This is lighter than pulling the full report and is appropriate when you just need to know the current visibility number. For historical trend data, increase the limit and plot the score field over time using the createdAt or updatedAt timestamp.
Use the client, sort, and limit parameters to fetch the most recent score snapshot for a location.
GET /legacyscores?client=3201926&sort=id%20DESC&limit=1 HTTP/1.1
Host: p.lssdev.com
x-api-token: YOUR_API_KEY
After triggering a report refresh, wait a few minutes before querying scores to avoid receiving partial or stale data.
Response Fields
| Field | Description |
|---|---|
score | Overall visibility score |
isComplete | Whether scoring finished (wait if false) |
countRequested | Total listings checked |
countCompleted | Listings completed |
data.baseline.overview.visibilityScore | Overall visibility |
data.baseline.overview.gmbScore | Google Business Profile score |
data.baseline.overview.yelpScore | Yelp score |
data.baseline.overview.bingScore | Bing score |
data.baseline.scoreBreakdown.local.napConsistency | NAP consistency across local sources |
data.baseline.sources.google.scan.scores | Detailed Google: claimed, NAP, reviews, photos, hours, website |
Insight Data (Google Business Profile)
Google Business Profile Insights show you how searchers are finding and interacting with a business on Google — impressions, clicks, calls, direction requests, and photo views. Advice Local captures these metrics over time and stores them as snapshots accessible through this endpoint, giving you a historical dataset you can use to build trend charts and demonstrate ROI to clients.
Each record in the response represents one monthly snapshot, identified by recordedAt. The most meaningful metrics for client reporting are typically discovery_impressions (how many people found the business by searching for a category rather than the business name — a strong signal of local SEO performance), total_actions (the sum of all calls, direction requests, and website visits), and the individual action breakdowns that show where engagement is concentrated. The LA_score is Advice Local's composite score for the location at the time of the snapshot, giving you a single number to track alongside the raw GBP metrics.
Use the where parameter with a recordedAt filter to scope the response to the date range you need. For a 12-month trend view, pass limit=12 and filter to the past year.
GET /legacyinsightdata?client=3201926&where={"recordedAt":{">":"2025-01-01"}}&limit=12 HTTP/1.1
Host: p.lssdev.com
x-api-token: YOUR_API_KEY
Query Parameters
| Parameter | Description |
|---|---|
client | Client ID Required |
where | JSON filter, e.g. {"recordedAt":{">":"2025-01-01"}} |
limit | Records per page |
skip | Pagination offset |
Key Response Fields
| Field | Description |
|---|---|
LA_score | Advice Local composite score |
total_impressions | Total profile impressions |
discovery_impressions | Impressions from discovery search |
direct_impressions | Impressions from direct search |
total_actions | Total customer actions |
website_visits | Website click-throughs |
phone_calls_clicks | Phone call taps |
directions | Directions requests |
photo_views | Photo view count |
recordedAt | Snapshot date |
Voice Data
The voice data endpoint reports on how often real users have interacted with a location through voice assistants — Google Assistant, Siri, Alexa, Bixby, and others. This data is only available for locations that have the AdVoice product active and have had voice content configured in their extra field. If AdVoice is not active for a location, this endpoint will return empty or zero-count results.
All three parameters — client, startDate, and endDate — are required. The endpoint always returns aggregate totals for the full date range rather than a day-by-day breakdown, so if you need a time series you will need to make multiple requests with narrower windows. Dates should be formatted as YYYY-MM-DD.
GET /legacyvoicedata?client=3201926&startDate=2025-01-01&endDate=2025-03-31 HTTP/1.1
Host: p.lssdev.com
x-api-token: YOUR_API_KEY
Response Fields
| Field | Description |
|---|---|
users_total | Total unique users across all assistants |
sessions_total | Total sessions |
requests_total | Total voice requests |
users[] | Per-assistant user counts |
requests[] | Per-assistant request counts |
Reviews
Reputation is one of the most visible signals in local search, and this endpoint surfaces all of the review data Advice Local has aggregated for a location across every monitored directory. The response is structured in layers: high-level totals and averages at the top, then per-source summaries, then individual review records at the bottom.
The sentiment object categorizes reviews on a five-point scale from positive to negative, giving you a quick read on how customers feel about the business overall. The score and recency objects let you spot trends — for instance, a high score.total combined with a low score.months_1 suggests recent reviews have been more negative than historical ones. The individual data[] array contains every review with full text, so you can build a reputation monitoring widget or send review alerts directly from this data.
Review data is only available for locations with active orders. Calling this endpoint for a client without an active order will return an empty or error response.
GET /legacyclients/3201926/reviews HTTP/1.1
Host: p.lssdev.com
x-api-token: YOUR_API_KEY
Response Structure
| Field | Description |
|---|---|
reviews | Total review count |
score.total | Overall average score |
score.months_1 / months_6 | Rolling 1-month and 6-month averages |
recency.week_1 | Reviews in the last week |
sentiment.positive | Positive sentiment count |
sentiment.negative | Negative sentiment count |
sources[] | Per-directory: name, score, count, logo URL |
data[] | Individual reviews: provider, reviewer, score, comment, replied, reviewedAt, url |
summaries[] | Per-directory aggregate: rating, reviews, maxRating, updatedAt |
Keywords & Geo-Grid
The keyword and geo-grid system is one of the most powerful tools in the platform for demonstrating local search performance to clients. Rather than showing a single rank number for a keyword, Advice Local scans Google Maps at a grid of geographic coordinates centered on the business location. Each grid point returns the actual rank the business holds for that keyword at that specific latitude/longitude. The result is a heat map of local search dominance — you can see not just whether a business ranks, but exactly how far their ranking influence extends geographically.
This is particularly compelling for service-area businesses or franchises that need to understand how well they dominate in adjacent neighborhoods. A plumber in downtown Austin might rank #1 for "emergency plumber" within two miles but fall out of the top 10 in the suburbs — the grid makes that visible at a glance.
Keywords are tracked per client. When you add a keyword, a new tracking campaign is created and the first scan runs automatically. Each subsequent scan updates the grid[] array with fresh rank data and appends a snapshot to history[], giving you a growing archive of how rankings have changed over time. You do not need to trigger scans manually — they run on a schedule once set up.
// Add a keyword to track
POST /legacykeywords/3201926 HTTP/1.1
Host: p.lssdev.com
x-api-token: YOUR_API_KEY
Content-Type: application/json
{ "keyword": "pizza delivery newport beach" }
Keywords don't need to match the client's city — you can track neighboring cities or alternative search terms to understand rank spread.
Response Fields
| Field | Description |
|---|---|
keyword | Tracked keyword string |
grid_id | Grid identifier |
grid_distance | Distance between grid points |
grid[] | Array of {LAT, LON, rank, point} — current scan data |
history[] | Historical snapshots with date and nested grid[] |
Direct Grid Scan Endpoints
Rollup Report
The rollup report operates at the partner level rather than the client level — it aggregates scores across all locations in your account into a single summary. This is the data you need for executive dashboards, quarterly business reviews, and any reporting that needs to answer the question "how are all of our locations doing on average?"
Note that this endpoint lives on a different host: praxis.lssdev.com rather than p.lssdev.com. Your x-api-token header works the same way, and you will need your numeric partner ID in the URL path. The response gives you three key structures: avgs (average scores across all locations), totals (sum totals for each metric), and count (the number of locations included in the calculation). A low average alongside a high count means your portfolio is large but performance is mixed — a pattern that usually points to a subset of locations needing attention.
GET https://praxis.lssdev.com/api/v2/partner/7/rollup/get-scores/ HTTP/1.1
x-api-token: YOUR_API_KEY
Content-Type: application/json
// Response structure
{
"avgs": {
"baseline_accurate": 5,
"monthly_google": 49,
"monthly_bing": 61,
"monthly_yelp": 72
},
"count": 211,
"totals": {
"baseline_accurate": 1004,
"monthly_google": 10408
}
}
Partner: Cards
Before you can place any orders through the API, you need a payment card on file. Cards are managed through the Advice Local dashboard rather than the API — this is intentional, as it keeps raw card data out of the API surface and delegates PCI-sensitive operations to the secure dashboard flow. Once a card is added in the dashboard, it is tokenized and stored against your partner account, and you can retrieve its token via the API.
The GET /cards response returns a list of card objects. Each object contains an id field — this is the opaque token string you will pass as card_id when placing orders. The token never expires on its own, but if a card is deleted from the dashboard or expires, orders placed with that ID will fail. It is good practice to store the card ID in your own data layer alongside the user-facing description (e.g. "Visa ending 4242") so your users can identify which card they are using.
GET /cards HTTP/1.1
Host: p.lssdev.com
x-api-token: YOUR_API_KEY
// Response
{
"status": 200,
"success": true,
"data": {
"object": "list",
"data": [
{ "id": "card_1AbCdEfGhIjKlMn", /* use this id when placing orders */ }
]
}
}
Groups
Groups are a lightweight organizational layer on top of your client portfolio. A group is simply a named collection of client IDs — there is no billing significance or product association attached to a group. Their primary use is to make it easier to work with subsets of locations: you might create a group for each brand you manage, each geographic region, each tier of service, or each account manager's portfolio.
When you fetch a group with ?populate=clients, the full client records for each member are embedded in the response. This can be convenient when you need to display a group's locations in a UI, but be aware that for groups with many members this will produce a very large response — each client record includes all of its fields. For groups with more than a few dozen locations, it is usually better to fetch the group (which includes a count and list of IDs) and then query the clients endpoint separately with filtering.
Populate Clients
Append ?populate=clients to expand each group object with its full client list. Note: this can return large payloads.
GET /legacygroups?populate=clients HTTP/1.1
Host: p.lssdev.com
x-api-token: YOUR_API_KEY
Create a Group
POST /legacygroups HTTP/1.1
Host: p.lssdev.com
x-api-token: YOUR_API_KEY
Content-Type: application/json
{ "name": "California Locations" }
Assign Clients to Group
POST /legacygroups/42 HTTP/1.1
Host: p.lssdev.com
x-api-token: YOUR_API_KEY
Content-Type: application/json
{
"name": "California Locations",
"clients": [3201926, 3201927, 3201928]
}
Google Images
Google Business Profile images are managed through a separate set of endpoints from the general client image system. This distinction exists because GBP images have their own identity within the Google ecosystem — they are submitted directly to Google via the GBP API and carry a Google-assigned image_id that is different from the image name used in the general image system.
When you upload an image to GBP via this endpoint, Advice Local passes it through to Google on your behalf. The image_name you provide in the request body is a reference name for the image within your system. When you delete a GBP image, you need to pass the Google-assigned image_id in the URL path — this is the identifier that appears in the GBP API responses, not the name you used when uploading.
// Upload Google image
POST /legacyclientimages/google/3201926 HTTP/1.1
Host: p.lssdev.com
x-api-token: YOUR_API_KEY
Content-Type: application/json
{ "image_name": "storefront.jpg" }
// Delete Google image
DELETE /legacyclientimages/google/3201926/87891723141223213241232134 HTTP/1.1
Host: p.lssdev.com
x-api-token: YOUR_API_KEY
Client Labels
Labels are freeform tags you can attach to clients, similar to tags in other systems. Unlike groups, which are named containers with explicit membership lists, labels are applied directly to individual client records and can be used to filter the client list. A location might have a label like premium, onboarding, needs-review, or any other tag that makes sense for your workflow. Labels are partner-scoped, so they are consistent across your entire account.
NAP & JSON-LD
These endpoints expose the structured data that Advice Local maintains for a client in formats ready for direct use in web pages and AI systems. The /nap endpoint returns the clean, canonical Name-Address-Phone data for a location — useful when you want to display a consistent business card in your own portal. The /jsonld endpoint returns the full schema.org LocalBusiness JSON-LD markup that can be dropped directly into a page's <script type="application/ld+json"> tag to improve search engine understanding of the business.
The /questionsld endpoint returns the FAQ JSON-LD generated from the client's voice questions — the same structured data that powers AdVoice responses. You can embed this on the business's website to enable rich result FAQ snippets in Google Search, providing a consistent presence across both voice and text search without any additional work on the business's part.
Appendix
This section collects reference material that applies across multiple endpoints: accepted state and province codes, supported countries, notes on the Google category taxonomy, and a complete index of every endpoint in the API.
US State Codes
Use standard two-letter state codes (e.g. CA, TX, NY, FL, WA). All 50 states plus DC are supported.
Canadian Province Codes
AB, BC, MB, NB, NL, NS, ON, PE, QC, SK, NT, NU, YT
Supported Countries
| Code | Country |
|---|---|
US | United States (default) |
CA | Canada |
GB | United Kingdom |
AU | Australia |
DE | Germany |
NZ | New Zealand |
Google Category IDs (GCIDs)
Google uses a curated taxonomy of business category identifiers called GCIDs to classify businesses on Google Maps and in search results. Getting the category right improves ranking for relevant searches because Google uses it to match businesses to queries. The full taxonomy CSV is available from Google and contains thousands of entries — from broad categories like gcid:restaurant to highly specific ones like gcid:neapolitan_pizza_restaurant.
When submitting a category to the Advice Local API, strip the gcid: prefix — only the slug portion goes in the categoryGoogle field. Only one primary category is supported at this level; additional categories can be submitted via extra.gmbData.secondaryCategories using the full category object format.
Categories come from Google's GCID taxonomy. When submitting a category to the API, strip the gcid: prefix:
// GCID taxonomy entry: gcid:italian_restaurant
// Send to API as:
"categoryGoogle": "italian_restaurant"
Complete Endpoint Index
| Method | Path | Description |
|---|---|---|
| GET | /legacyclients | List clients |
| POST | /legacyclients | Create client |
| GET | /legacyclients/{id} | Get client |
| PUT | /legacyclients/{id} | Update client |
| DELETE | /legacyclients/{id} | Delete client |
| POST | /legacyclients/{id}/reactivate | Reactivate client |
| GET | /legacyclients/{id}/sso | SSO link |
| GET | /legacyclients/{id}/url | Permanent URL |
| GET | /legacyclients/{id}/report | Full report |
| GET | /legacyclients/{id}/score | Visibility score |
| GET | /legacyclients/{id}/reviews | Review data |
| GET | /legacyclients/{id}/pdf | PDF report |
| GET | /legacyclients/{id}/gridpdf | Grid PDF |
| GET | /legacyclients/{id}/aipdf | AI PDF report |
| GET | /legacyclients/{id}/nap | NAP data |
| GET | /legacyclients/{id}/jsonld | JSON-LD markup |
| GET | /legacyclients/{id}/questionsld | FAQ JSON-LD |
| GET | /legacyclients/{id}/status | Status |
| GET | /legacyclients/{id}/list | Directory list |
| GET | /legacyclients/{id}/listdetail | Listing detail |
| GET | /legacyclients/{id}/grid | Geo-grid data |
| GET | /legacyclients/{id}/refresh | Trigger refresh |
| GET | /legacyclients/{id}/notify | Trigger sync |
| GET | /legacyclients/labels | List labels |
| POST | /legacyclients/labels/{label} | Add label |
| DELETE | /legacyclients/labels/{label} | Remove label |
| POST | /legacyclientimages/{id} | Upload gallery image |
| POST | /legacyclientimages/{id}/{tag} | Upload tagged image |
| GET | /legacyclientimages/{id} | Get all images |
| DELETE | /legacyclientimages/{id}/{image} | Delete image |
| POST | /legacyclientimages/google/{id} | Upload Google image |
| DELETE | /legacyclientimages/google/{id}/{image_id} | Delete Google image |
| GET | /legacyproducts | List products |
| POST | /legacyorders | Create order |
| GET | /legacyorders/{id} | Get order |
| GET | /legacyorders | List orders |
| DELETE | /legacyorders/{id} | Delete order |
| POST | /legacyorderproducts | Ordered products |
| POST | /legacyfulfillmentdata | Fulfillment data |
| GET | /legacyscores | Score records |
| GET | /legacyinsightdata | GBP insight data |
| GET | /legacyvoicedata | Voice metrics |
| GET | /legacykeywords/{id} | Get keywords |
| POST | /legacykeywords/{id} | Add keyword |
| DELETE | /legacykeywords/{id}/{keyword} | Remove keyword |
| DELETE | /legacykeywords/{id} | Reset keywords |
| POST | /legacygrid/{id}/{keyword} | Create grid scan |
| GET | /legacygrid/{id}/{grid} | Get grid scan |
| GET | /legacygroups | List groups |
| POST | /legacygroups | Create group |
| POST | /legacygroups/{id} | Update group |
| GET | /cards | List cards |
| POST | /cards | Create card |
| DELETE | /cards/{id} | Delete card |