Local Dominator API - OpenAPI 3.1 (v1)

Download OpenAPI specification:

Local Dominator

Scan Grid Configuration

Heatmap scan endpoints — create one-off grid scans, read their results, and analyze them.

grid_size is the number of pins across the diameter (circle) or side (square), while distance is the distance in meters between each pin.

For example, grid_size: 10 and distance: 100 gives a ~900m diameter.

List scans

Authorizations:
BearerAuth
query Parameters
text
string

Filter scans by text(name, keywords, labels)

per_page
integer
Default: 10
Example: per_page=10
page
integer
Default: 0
Example: page=0
start_date
string <date>
Example: start_date=2024-01-01

Retrieve scans that occurred on or after the specified start date (in YYYY-MM-DD format).

end_date
string <date>
Example: end_date=2024-08-31

Retrieve scans that occurred on or before the specified end date (in YYYY-MM-DD format).

labels
Array of strings

An array of labels associated with the scan

Responses

Response samples

Content type
application/json
{ }

Perform a scan

Initiates a scan based on the specified parameters.

Authorizations:
BearerAuth
Request Body schema: application/json
required
latitude
required
number <float>

Latitude of the center point from where the scan will be performed.

longitude
required
number <float>

Longitude of the center point from where the scan will be performed.

shape
required
string
Enum: "circle" "square"

Shape of the scan area, either circle or square.

distance
required
integer <int32>

Distance in meters between adjacent pins in the scan grid. This does not define the total diameter directly.

google_place_id
required
string

The PlaceID in Google. For example, ChIJgUbEo8cfqokR5lP9_Wh_DaM.

grid_size
required
integer <int32> <= 21

Defines the number of points on each square side or diameter to perform the search from. Maximum value is 21.

search_terms
required
Array of strings

Array of strings representing the search terms to use during the scan.

webhook_url
string

A url where we will POST the results back once the scan is completed.

preschedule_analysis
boolean
Default: false

When set to true, automatically schedules analysis when the scan is completed.

resource_category
string
Default: "googleMaps"
Enum: "googleMaps" "googleLocalFinder"

The type of scan to perform. Use googleLocalFinder for Google Local Finder results. Defaults to googleMaps.

Responses

Request samples

Content type
application/json
{
  • "latitude": 40.712776,
  • "longitude": -74.005974,
  • "shape": "circle",
  • "distance": 1000,
  • "google_place_id": "ChIJgUbEo8cfqokR5lP9_Wh_DaM",
  • "grid_size": 13,
  • "search_terms": [
    ],
  • "preschedule_analysis": true,
  • "resource_category": "googleLocalFinder"
}

Response samples

Content type
application/json
{
  • "message": "Scan creation started.",
  • "scan_uuid": "xPH5x_SZcmcf8E7FROCNQ"
}

Retrieve scan details

Returns the details of the scan specified by scan_id.

Authorizations:
BearerAuth
path Parameters
scan_id
required
string

The ID of the scan

Responses

Response samples

Content type
application/json
[ ]

Delete a scan

Authorizations:
BearerAuth
path Parameters
scan_id
required
string

The ID of the scan

Responses

Scan results

The details of each business in every point in the scan.

Authorizations:
BearerAuth
path Parameters
scan_id
required
string

The ID of the scan

Responses

Response samples

Content type
application/json
[ ]

Analyze a scan

Initiates or retrieves post-run insights for a scan: ranking context, competitors, and optimization-oriented notes derived from the scan grid.

Authorizations:
BearerAuth
path Parameters
scan_id
required
string

The ID of the scan to analyze

Responses

Response samples

Content type
application/json
{
  • "scanId": "xPH5x_SZcmcf8E7FROCNQ",
  • "message": "Group was successfully analyzed",
  • "analysis": {
    }
}

Scheduled scan campaigns

Scheduled scans — recurring campaigns: list, create, update, or delete a campaign; trigger a run; or bulk-delete runs on a campaign by creation date.

A campaign holds cron scheduling, grid geometry, keywords, and notification settings. Each execution is a run (see Scheduled scan campaign runs).

List scheduled scan campaigns

Returns scheduled scans for the API key owner, with optional filters and pagination. Filter by schedule category, resource category, grid shape, last scan run date range, labels, and free-text search. start_date / end_date are aliases for date_from / date_to (filter on the calendar date of the most recent scan run).

Authorizations:
BearerAuth
query Parameters
text
string

Filter by place name, vicinity, or search term (substring match).

string or Array of strings

Conjunction filter: the campaign must have every label. Send one comma-separated labels value, or repeat ?labels=... (form style) — same as the list query schema in the API. The scan must still match on all of the given labels.

resource_category
string
Enum: "googleMaps" "googleLocalFinder"

Filter by Maps vs Local Finder (scheduled scan setting).

shape
string
Enum: "circle" "square"

Filter by grid shape.

schedule
string
Enum: "daily" "weekly" "biweekly" "monthly"

Filter by high-level schedule category (daily, weekly, biweekly, monthly).

date_from
string <date>

Lower bound on last scan run date (YYYY-MM-DD); scheduled scans that never had a run are included.

date_to
string <date>

Upper bound on last scan run date (YYYY-MM-DD); scheduled scans that never had a run are included.

start_date
string <date>

Same as date_from.

end_date
string <date>

Same as date_to.

order_property
string
Enum: "date" "place_name" "placeName" "search_term" "searchTerm" "average_rank" "averageRank" "grid_size" "size" "last_run_date" "lastScan" "lastRunDate" "creation_date" "creationDate" "next_run" "nextRunTimestamp"

Sortable field; maps to the same orderProperty as scheduled_scans list queries. Aliases (e.g. lastScan = last_run_date) are accepted for client convenience.

ascending
string
Enum: "true" "false"

Sort direction; default false (descending).

per_page
string^[0-9]+$

Page size as digits only (default 50 if omitted; parsed as a positive integer).

page
string^[0-9]+$

Zero-based page index as digits only (default 0 if omitted; parsed as a non-negative integer).

Responses

Response samples

Content type
application/json
{ }

Create scheduled scan campaign

Creates a scheduled scan. google_place_id identifies the place. scheduling is a five-field cron (minute, hour, day of month, month, day of week); invalid values return 400. The response includes the new id (UUID). 201 means the resource is available immediately in GET /v1/scheduled-scans/{scheduled_scan_id}; 202 means the request was accepted and the same response body shape applies, but the campaign may not be readable yet. For 202, use either GET /v1/scheduled-scans/{scheduled_scan_id} checks with the returned id, or webhook_url delivery if configured. Each execution of the campaign is a scan run.

Authorizations:
BearerAuth
Request Body schema: application/json
required
google_place_id
required
string

Google Place ID for the business location.

latitude
required
number

Grid center latitude.

longitude
required
number

Grid center longitude.

shape
required
string
Enum: "circle" "square"
distance
required
integer >= 1

Distance in meters between adjacent pins.

grid_size
required
integer [ 1 .. 21 ]
required
Array of strings or objects non-empty unique

Keywords for this campaign. Most clients send a list of plain strings (each keyword is active). You may instead send objects with term and optional status (active / inactive); when status is omitted on an object, it defaults to active. Duplicate terms (case-insensitive) are not allowed. Strings and objects may be mixed in one array.

scheduling
required
string

Five-field cron expression (minute, hour, day of month, month, day of week) for recurring runs. Must be accepted by the API; invalid values return 400.

notify
boolean

Email notifications when runs complete.

run_now
boolean

If true, triggers an immediate manual run after creation.

labels
Array of strings
skippable
boolean

Used for biweekly-style recurrence when combined with your scheduling expression.

preschedule_analysis
boolean

When true, analysis is scheduled when runs complete. When omitted, the server uses the default for new tasks (typically true); send false to disable.

alias
string

Optional display name for the scheduled scan.

resource_category
string
Enum: "googleMaps" "googleLocalFinder"

Optional. Which search surface recurring runs use.

webhook_url
string <uri> <= 2048 characters ^https?://

Optional. http or https absolute URL only (request validation: ^https?://, max 2048 chars). POST when each scan run completes successfully (same style as one-time POST /v1/scans webhook_url). Applies until changed or cleared via PATCH.

Responses

Request samples

Content type
application/json
{
  • "google_place_id": "ChIJ03jJ2Omr2YgRNkx36YLd3q4",
  • "latitude": 26.0481,
  • "longitude": -80.1819,
  • "shape": "circle",
  • "distance": 1,
  • "grid_size": 1,
  • "search_terms": [
    ],
  • "scheduling": "0 9 * * 1",
  • "notify": true,
  • "run_now": true,
  • "labels": [
    ],
  • "skippable": true,
  • "preschedule_analysis": true,
  • "alias": "string",
  • "resource_category": "googleMaps",
  • "webhook_url": "http://example.com"
}

Response samples

Content type
application/json
{
  • "message": "Scheduled scan created successfully.",
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}

Start a scheduled scan campaign run now

Starts a new scan run immediately (manual execution). Processing is asynchronous; 200 means the run was accepted.

Authorizations:
BearerAuth
path Parameters
scheduled_scan_id
required
string <uuid>

Opaque scheduled scan identifier (same id as in list/detail responses).

Responses

Response samples

Content type
application/json
{
  • "message": "Run started."
}

Get scheduled scan campaign and runs

Returns scheduled scan metadata and the list of scan runs (run_uuid per run). Optional date_range filters runs (default 3M). Campaign share_links reflect the latest completed (notified) run in the filtered window that has heatmap rows with shareable static URLs; run-level share_links use the same per-run resolution (no campaign_link on run objects).

Authorizations:
BearerAuth
path Parameters
scheduled_scan_id
required
string <uuid>

Opaque scheduled scan identifier (same id as in GET /v1/scheduled-scans list items).

query Parameters
date_range
string
Default: "3M"
Enum: "MAX" "1Y" "6M" "3M" "1M"

Limits which scan runs appear in runs (by run creation time relative to the campaign’s latest run), using the same window tokens as the dashboard task-runs dateRange filter. MAX = all runs. When omitted, 3M is used (last three months). image_link, dynamic_url, and campaign_link on the campaign object are derived from the newest notified run inside that filtered set that has resolvable per-row share URLs.

Responses

Response samples

Content type
application/json
{ }

Update scheduled scan campaign

Updates this scheduled scan (recurrence, grid, keywords, notifications, analysis option). Omitted fields stay unchanged. Same validation rules as create where applicable. resource_category and is_placed_manually cannot be changed — including either field returns 400. Deleted scheduled scans are not found (404).

Authorizations:
BearerAuth
path Parameters
scheduled_scan_id
required
string <uuid>

Opaque scheduled scan identifier (same id as in GET /v1/scheduled-scans list items).

Request Body schema: application/json
required
non-empty
Array of strings or objects (ScheduledScanPatchSearchTerm) non-empty

Same rules as search_terms on create: array of strings and/or { term, status? } objects; status is optional and defaults to active; duplicates are rejected.

scheduling
string

Five-field cron expression; must be accepted by the API (400 if invalid).

skippable
boolean

When true, biweekly scheduling uses selected_day_of_week / selected_hour / selected_minute to refine next_run_at. When false, omit those three fields unless you will set skippable to true; they do not affect next_run_at while false.

grid_size
integer [ 1 .. 21 ]
distance
integer >= 1
shape
string
Enum: "circle" "square"
latitude
number
longitude
number
notify
boolean
preschedule_analysis
boolean
webhook_url
string or null <uri>

null or "" clears the webhook. A non-empty string must be http or https and max 2048 characters (same as scheduled-scans-validation for PATCH). Receives a POST when each run completes.

selected_day_of_week
integer [ 0 .. 6 ]

Day of week (0 = Sunday … 6 = Saturday) for biweekly next_run_at anchoring when skippable is true. Ignored for next_run_at when skippable is false — omit in that case.

selected_hour
integer [ 0 .. 23 ]

Local hour (scheduled scan timezone) for biweekly next_run_at when skippable is true. Ignored when skippable is false — omit in that case.

selected_minute
integer [ 0 .. 59 ]

Local minute for biweekly next_run_at when skippable is true. Ignored when skippable is false — omit in that case.

Responses

Request samples

Content type
application/json
{
  • "search_terms": [
    ],
  • "scheduling": "0 9 * * 1",
  • "notify": true
}

Response samples

Content type
application/json
{
  • "message": "Scheduled scan updated successfully.",
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}

Delete scheduled scan campaign

Deletes this scheduled scan and its associated data. It no longer appears in GET /v1/scheduled-scans or GET …/scheduled-scans/{scheduled_scan_id}. Repeating DELETE returns 404.

Authorizations:
BearerAuth
path Parameters
scheduled_scan_id
required
string <uuid>

Opaque scheduled scan identifier (same id as in GET /v1/scheduled-scans list items).

Responses

Response samples

Content type
application/json
{
  • "message": "Scheduled scan deleted successfully."
}

Delete scheduled scan campaign runs by run creation date

Deletes scan runs for this scheduled scan, selected by when each run started (UTC). creation_date is a filter: only runs whose created_at falls on that calendar day (UTC YYYY-MM-DD) are removed. The calendar day is not a resource—only runs are deleted.

Authorizations:
BearerAuth
path Parameters
scheduled_scan_id
required
string <uuid>

Opaque scheduled scan identifier.

query Parameters
creation_date
required
string <date>

Filter: UTC calendar day (YYYY-MM-DD). Matches the date part of each scan run’s created_at.

Responses

Response samples

Content type
application/json
{
  • "message": "Scheduled scan runs deleted for the selected run-creation date.",
  • "creation_date": "2025-04-14",
  • "runs_deleted": 2
}

Scheduled scan campaign runs

Scheduled scansruns: each run is one execution of a campaign. Fetch scan rows or compressed grid results for a run, or delete a single run.

Run identifiers (run_uuid) come from the campaign detail response and run listings.

Get compressed results for a scheduled scan campaign run

Returns compressed grid results for this scan run (all keywords; camelCase keys and compressed_grid).

Authorizations:
BearerAuth
path Parameters
run_id
required
string <uuid>

Scan run identifier (run_uuid).

Responses

Response samples

Content type
application/json
[ ]

List scan rows for a scheduled scan campaign run

Returns one scan row per search term for this scan run (ranks, links, map fields). Each object is a single-keyword scan inside the run. Each row includes scheduled_scan_id, run_uuid, and run_analysis_map (per-keyword SEO report status, same key shape as run objects under GET /v1/scheduled-scans/{id}).

Authorizations:
BearerAuth
path Parameters
run_id
required
string <uuid>

Scan run identifier (run_uuid).

Responses

Response samples

Content type
application/json
[ ]

Delete a scheduled scan campaign run

Deletes this scan run (soft-delete). Does not delete the scheduled scan.

Authorizations:
BearerAuth
path Parameters
run_id
required
string <uuid>

Scan run identifier (run_uuid).

Responses

Response samples

Content type
application/json
{
  • "message": "Scheduled scan run deleted successfully."
}

Listings Manual Submissions API

Create a business-listings prospect scan across directories and, if the results warrant it, order a fix that resubmits correct data across 50 or 100 directories.

Create a listings scan (prospect)

Creates a business record and kicks off an asynchronous listings scan across directories. Free — no credits are charged.

The scan typically takes 10–30 seconds. Poll GET /v1/listings/prospect/{search_id} until status is completed.

Rate-limited to 10 requests per hour per API key.

Authorizations:
BearerAuth
Request Body schema: application/json
required
business_name
required
string
address
required
string
city
string
state
string
zip
string
phone
string
website
string <uri>
country
string
Default: "US"

Responses

Request samples

Content type
application/json
{
  • "business_name": "Acme Inc",
  • "address": "123 Main St",
  • "city": "New York",
  • "state": "NY",
  • "zip": "10001",
  • "phone": "+1234567890",
  • "website": "https://acme.com",
  • "country": "US"
}

Response samples

Content type
application/json
{
  • "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  • "order_number": "ABC123",
  • "status": "pending"
}

List your listings scans

Authorizations:
BearerAuth
query Parameters
page
integer
Default: 1
limit
integer <= 100
Default: 20

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "page": 1,
  • "limit": 20,
  • "total": 47
}

Get a prospect and its scan results

Authorizations:
BearerAuth
path Parameters
search_id
required
string

Prospect id returned from POST /v1/listings/prospect

Responses

Response samples

Content type
application/json
{
  • "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  • "business_name": "string",
  • "address": "string",
  • "status": "pending",
  • "total_listings": 42,
  • "correct_listings": 12,
  • "order_number": "ABC123",
  • "created_at": "2019-08-24T14:15:22Z",
  • "fix_requested": true,
  • "fix_plan": "50",
  • "payment_status": "unpaid",
  • "campaign_progress": "ordered",
  • "city": "string",
  • "state": "string",
  • "zip": "string",
  • "phone": "string",
  • "website": "string",
  • "country": "string",
  • "results": [
    ]
}

Order a listings fix for a prospect

Charges credits from the caller's wallet and submits a fix order for the given prospect.

  • Plan "50" costs 55,650 credits and fixes up to 50 directories.
  • Plan "100" costs 96,500 credits and fixes up to 100 directories.

If the upstream submission fails, the charge is automatically refunded via a compensating manualAdd transaction and the upstream error is returned.

Idempotent: a second call for the same search_id returns 409 and does not charge.

Authorizations:
BearerAuth
Request Body schema: application/json
required
search_id
required
string
plan
required
string
Enum: "50" "100"

Responses

Request samples

Content type
application/json
{
  • "search_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  • "plan": "50"
}

Response samples

Content type
application/json
{
  • "order_id": "string",
  • "order_number": "string",
  • "status": "ordered",
  • "plan": "50",
  • "credits_charged": 55650
}

Get fix order progress

Authorizations:
BearerAuth
path Parameters
search_id
required
string

Responses

Response samples

Content type
application/json
{
  • "search_id": "string",
  • "order_number": "string",
  • "campaign_progress": "ordered",
  • "plan": "50",
  • "progress": {
    }
}

AI Tracker Public API

Partner-facing AI Tracker endpoints available through the Public API gateway. Endpoints are authenticated by ld_... API keys and include server-side credit charging where applicable.

Get AI Tracker account summary

Authorizations:
BearerAuth

Responses

Response samples

Content type
application/json
{
  • "external_user_id": "string",
  • "display_name": "string",
  • "role": "string",
  • "is_team": true,
  • "created_at": "string",
  • "total_campaigns": 0,
  • "active_campaigns": 0,
  • "total_scans": 0,
  • "total_credits_consumed": 0
}

List AI Tracker campaigns

Authorizations:
BearerAuth

Responses

Response samples

Content type
application/json
{
  • "campaigns": [
    ]
}

Preview AI Tracker prompts (no billing)

Generates prompt previews for the given keywords. Does not create a campaign or charge credits. Same rate limits as campaign commit.

Authorizations:
BearerAuth
Request Body schema: application/json
required
name
required
string
domain
required
string
location
string
engines
Array of strings
Items Enum: "chatgpt" "gemini" "google_ai_mode" "perplexity" "claude" "grok"
keywords
required
Array of strings non-empty

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "domain": "string",
  • "location": "string",
  • "engines": [
    ],
  • "keywords": [
    ]
}

Response samples

Content type
application/json
{ }

Commit AI Tracker campaign (charges credits)

Two-step flow: commit after preview. On the Public API side, credits are reserved up to the per-run maximum, then adjusted to match actual prompts_count returned by the AI Tracker backend.

Authorizations:
BearerAuth
Request Body schema: application/json
required
name
required
string
domain
required
string
location
string
engines
Array of strings
Items Enum: "chatgpt" "gemini" "google_ai_mode" "perplexity" "claude" "grok"
required
Array of objects [ 1 .. 50 ] items

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "domain": "string",
  • "location": "string",
  • "engines": [
    ],
  • "prompts": [
    ]
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "name": "string",
  • "domain": "string",
  • "status": "string",
  • "prompts_count": 0,
  • "billable_prompts": 0,
  • "credits_per_prompt": 100,
  • "credits_charged": 0
}

Get AI Tracker campaign results

Authorizations:
BearerAuth
path Parameters
id
required
string
query Parameters
limit
integer <= 500
offset
integer

Responses

Response samples

Content type
application/json
{
  • "total": 0,
  • "limit": 0,
  • "offset": 0,
  • "results": [
    ]
}

Get AI Tracker campaign rankings

Authorizations:
BearerAuth
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "rankings": [
    ]
}

Preview prompts for new keywords on a campaign (no billing)

Authorizations:
BearerAuth
path Parameters
id
required
string
Request Body schema: application/json
required
keywords
required
Array of strings non-empty

Responses

Request samples

Content type
application/json
{
  • "keywords": [
    ]
}

Response samples

Content type
application/json
{ }

Commit new keywords/prompts on a campaign (charges credits)

Authorizations:
BearerAuth
path Parameters
id
required
string
Request Body schema: application/json
required
required
Array of objects [ 1 .. 50 ] items

Responses

Request samples

Content type
application/json
{
  • "prompts": [
    ]
}

Response samples

Content type
application/json
{
  • "billable_prompts": 0,
  • "credits_per_prompt": 0,
  • "credits_charged": 0
}

Trigger AI Tracker rerun (charges credits)

Authorizations:
BearerAuth
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "triggered": true,
  • "campaign_id": "string",
  • "scan_jobs_count": 0,
  • "status": "string",
  • "billable_prompts": 0,
  • "credits_per_prompt": 100,
  • "credits_charged": 0
}