Skip to main content
GET
List businesses

Authorizations

Authorization
string
header
required

An agent key (rpk_...) created in Settings → API & MCP, sent as Authorization: Bearer rpk_.... Bearer only: a cookie session can never drive this API. An OAuth 2.1 access token obtained from the same host works identically and lands on the same ceiling.

Headers

X-Workspace-Id
string

Which workspace to read. Omit it and you get the account’s home workspace, which on an agency account is often not where the live businesses are. A workspace this credential cannot read is refused with 403 rather than quietly answered from the default.

Query Parameters

q
string

JSON filter object, for example {"needs_response":true}.

sort_by
string

Field to sort on.

limit
integer

Maximum rows to return.

skip
integer

Rows to skip, for paging.

Response

Matching businesses.

id
string

Unique id.

google_place_id
string
google_account_id
string
google_location_id
string
facebook_page_id
string

Set when this BusinessLocation was created from a Facebook Page connected in Settings. Mutually exclusive with google_location_id in practice — a chain's GBP listing and its Facebook Page get separate BusinessLocation rows.

youtube_channel_id
string

External YouTube channel id (UC…) bound to this location. Set from the Connections panel on BusinessDetail. The reply resolver joins this against OAuthIntegration.provider_account_id to pick which connected channel posts the comment.

reddit_account_id
string

Reddit account fullname (t2_…) bound to this location. Same role as youtube_channel_id — the reply resolver joins this against OAuthIntegration.provider_account_id to pick which connected Reddit account authors the comment.

reddit_username
string

Denormalised display name for the bound Reddit account. The stable identifier is reddit_account_id (t2_…); this is just for UI affordances since usernames can change.

source
enum<string>
Available options:
google,
facebook
added_via
enum<string>

How this business was added, which decides how its reviews are read.

Available options:
gbp_oauth,
places,
website,
dfs_keyword
business_name
string
business_category
string
address_line1
string
address_line2
string
city
string
state
string
postal_code
string
country
string
phone
string
website
string
google_maps_url
string
latitude
number
longitude
number
cover_photo_url
string
logo_url
string
average_rating
number
total_reviews
integer
is_verified
boolean
is_active
boolean
is_prospect
boolean

Created by generateProspectAudit for a business the agency is pitching, not a client. Always paired with is_active=false. Filtered out of every business picker/list via useBusinessLocations' default exclusion; surfaces only on the Prospect Audits page. Conversion path: clear the flag (or just activate the location) when the prospect signs.

billing_exempt
boolean

Comp/internal location — excluded from plan capacity math and over-capacity checks.

trial_state
enum<string>

Per-location trial discriminator for agency-onboarded clients added BEYOND paid capacity. 'trialing' = free now, excluded from capacity, will auto-convert at trial_end; 'converted' = trial billed and now counts as a normal paid location; 'ended' = trial canceled/expired without converting (the row is deactivated but kept, which blocks a repeat trial). Distinct from billing_exempt (comp = forever-free, never counts). Absent on rows that never trialed.

Available options:
trialing,
converted,
ended
trial_started_at
string

Set once when a trial is first started. Its presence (keyed on stable location identity) is the anti-abuse signal — a location that has ever trialed can't trial again.

trial_end
string

Conversion deadline. The trialScheduler converts the location at/after this instant.

trial_converted_at
string
trial_ended_at
string

Set when a trial ends without converting (scheduler expiry or user cancel-during-trial). Feeds the 'Free trial ended on ' note on the business card and its trial_ended notification. Absent on rows ended before this field existed — falls back to trial_end for display.

trial_charge_amount
number

Add-on rate captured at trial start, for display only ('converts to $X/mo on '). Conversion always recomputes the real charge from live Stripe.

trial_charge_interval
enum<string>
Available options:
month,
year
last_synced_at
string
last_full_review_sync_at
string

When the GBP v4 reviews endpoint was last paged to completion for this location. The scheduler's blanket sync is incremental (1 call/location/tick); this drives the daily forced full sweep, which is the only thing that catches an owner reply typed into Google's own UI — a reply does not move the review's updateTime, so it never floats back to page 1.

review_count_recheck_after
string

Set when a full re-page failed to resolve a totalReviewCount vs stored-row-count disagreement — i.e. Google counts reviews its own list endpoint won't return. Suppresses the reconciliation guard until this time so a permanently-off-by-N location can't force a full page-through on every 15-min tick. Cleared by any successful reconciliation or manual Sync.

ai_insights
object
ai_insights_updated_at
string
ai_insights_review_count
integer
is_online_only
boolean

True for businesses with no physical location. Auto-inferred during enrichment from address fields + business_category. Manually overridable from /businesses/:id (PR-23). Online-only businesses always search globally; a tracker's explicit geo_scope still applies analysis-time filtering when the profile has country/state/city or serves_areas on file.

is_online_only_overridden
boolean

True if a user manually set is_online_only. Enrichment will not overwrite the value when this is true.

enrichment
object

Structured business profile derived from website scrape + extended GBP fetch + LLM extraction. Populated by businessEnrichment.js. Empty until enrichment runs successfully.

enrichment_overrides
object

Per-field user edits that shadow the auto-generated enrichment. Stored separately from enrichment so a manual refresh doesn't clobber them. When an override key is present, getEffectiveEnrichment uses it in place of the enrichment value. Keys: about (string), services (string[]), attributes (string[]).

manual_notes
string

Free-form context the user wants the AI to know about this business. Appended to the mention-analysis prompt alongside the enrichment summary. No auto-generated counterpart — pure user input.

enrichment_updated_at
string
enrichment_source
enum<string>
Available options:
first-add,
manual-refresh
enrichment_status
enum<string>

'partial' = website scrape failed but GBP succeeded (or vice versa); the profile is still useful.

Available options:
pending,
success,
partial,
failed
enrichment_error
string
auto_response_enabled
boolean

Per-business opt-in for the AI review-reply worker. When the agency has configured rules in auto_response_settings, only locations with this flag set to true will get auto-replies queued. Default false — owners must opt in each business explicitly so a chain isn't bulk-enrolled.