Skip to content

OpenGMB MCP tools reference

This reference lists all 238 tools the OpenGMB MCP server offers, grouped by area. It is generated from the same list the server serves, so it cannot drift. Each tool shows whether it reads or writes, the permission it needs, who has that permission, and its inputs.

Last updated 2026-10-24

Get started

Which tools need which access?

Read

Works with any token, including a read only one. A read only token is refused on every write tool, even with a dry run.

Write, proposal (needs Read & write)

The call stores a proposal that expires after 15 minutes and changes nothing until it is applied with mcp_proposals_apply.

Write, own approval steps (needs Read & write)

The tool runs when called and has its own draft, approval and publish steps. Pass dryRun set to true for a preview that creates nothing.

Client approver tokens

A client approver's write token can only approve or reject replies. A client viewer can only have read only tokens.

Which resources can an agent open?

  • review-queue (opengmb://reviews/queue): Replies pending approval, blocked or conflicted, and posts pending approval or blocked. Needs the review:approve permission.
  • google-pending-updates (opengmb://google/pending-updates): Open profile changes: edits made outside OpenGMB and updates Google suggested. Needs the location:read permission.
  • audit-recent (opengmb://audit/recent): The last 100 audit rows. Needs the audit:read permission.

workspaces tools

workspaces_list

Read: works with any token

Needs the workspace:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

List the workspaces the caller can see in their organization, ordered by name, each with defaultPostLanguage (the language new posts start in), timeZone (IANA, the zone the client's times are shown and scheduled in), timeZoneSource and dateFormat.

workspaces_create

Write, proposal: needs a Read & write token

Needs the workspace:create permission. Roles with it: owner, admin, manager.

Create a workspace (shown as a client in the app) in the caller's organization. Names are unique per organization, ignoring upper and lower case.

name required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

workspaces_rename

Write, proposal: needs a Read & write token

Needs the workspace:manage permission. Roles with it: owner, admin.

Rename a workspace (shown as a client in the app). Names are unique per organization, ignoring upper and lower case; changing only the casing of its own name is allowed. Needs workspace:manage (owner, admin).

workspaceId required
name required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

workspaces_delete

Write, proposal: needs a Read & write token

Needs the workspace:manage permission. Roles with it: owner, admin.

Delete a workspace (a client in the app). Refused with CONFLICT while the client has any location, and while anything else still belongs to it (people, posts, reports, templates); remove those first. Its reply settings are deleted with it. Needs workspace:manage (owner, admin).

workspaceId required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

workspaces_erase_data

Write, proposal: needs a Read & write token

Needs the workspace:erase permission. Roles with it: owner.

Permanently delete one client (workspace) and everything OpenGMB stores for it: locations, reviews, replies, posts, profile history, media records, reports, templates, people's access and invitations, in one transaction. confirmName must equal the client's name exactly. Does NOT delete anything on Google (posts, replies, profile edits already published stay there), does not delete people's accounts or the agency's Google connection, and keeps the audit log (append-only; it is the proof of this erasure). Leaves one tombstone audit row with the client id and row counts, no personal data. Export first: this cannot be undone. Needs workspace:erase (owner only).

workspaceId required
confirmName required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

workspaces_export_data

Read: works with any token

Needs the workspace:manage permission. Roles with it: owner, admin.

Export everything OpenGMB stores for one client (workspace) as one JSON document: locations, reviews, replies, assignments and notes, posts and edits, profile snapshots and changes, media records, reports, templates, people and invitations, and the audit rows about the client. Never includes secrets (Google tokens, API token hashes, passwords, two-factor secrets, invitation and share-link token hashes) or anything held only on Google. Refused above 1,000,000 rows. Each export is recorded in the audit log (counts only). Needs workspace:manage (owner, admin).

workspaceId required

workspaces_setPostLanguage

Write, proposal: needs a Read & write token

Needs the review:configure permission. Roles with it: owner, admin.

Set the language new posts in a workspace start in: posts.createDraft uses it when no language is given, and each post can still pick its own. language: one of en, es, fr, de, it, pt, nl, vi, zh, ko, ja, ar, hi, gu (BCP 47). Existing posts keep their language. Needs review:configure (owner, admin).

workspaceId required
language required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

workspaces_setTimeSettings

Write, proposal: needs a Read & write token

Needs the review:configure permission. Roles with it: owner, admin.

Set a workspace's time zone and date format. timeZone: an IANA zone such as Asia/Kolkata, America/Chicago or Australia/Sydney. dateFormat: one of YYYY-MM-DD, DD/MM/YYYY, MM/DD/YYYY. Times in the app, scheduled posts, recurring posts, report schedules and digests use the zone; stored times do not change. Pass only the fields to change. Needs review:configure (owner, admin).

workspaceId required
timeZone optional
dateFormat optional
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

audit tools

audit_list

Read: works with any token

Needs the audit:read permission. Roles with it: owner, admin.

List audit log entries for the caller's organization, newest first, with the acting user's name (null for system rows) and each row's before/after. Optional filters, applied before limit: surface (ui, mcp, worker, cli) and actorUserId. Pass beforeId (the smallest id seen) with the same filters to page.

limit optional
beforeId optional
surface optional
actorUserId optional

audit_verify

Read: works with any token

Needs the audit:read permission. Roles with it: owner, admin.

Verify the caller's organization audit chain: recompute every row hash and link, and compare the chain head (last id, hash, row count) with the signed checkpoint. checkpoint is ok, missing (rows exist but no checkpoint yet), invalid_signature, or mismatch (rows were deleted or truncated).

audit_export

Read: works with any token

Needs the audit:read permission. Roles with it: owner, admin.

Export the caller's organization audit log as CSV or JSON, ordered by id ascending. from is inclusive and to is exclusive, both ISO datetimes compared in UTC at millisecond precision. limit defaults to 5000 (max 5000); when truncated is true, pass nextAfterId as afterId to continue. before/after are canonical JSON. The result includes the current signed checkpoint, so a copy of the signed chain head leaves the system with each export. Each export is itself recorded as an audit.export audit row.

format required
from optional
to optional
limit optional
afterId optional

apiTokens tools

apiTokens_list

Read: works with any token

Needs the api_token:manage_own permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

List API tokens in the caller's organization, newest first, including revoked ones. Members see their own tokens; owners and admins see everyone's. Never returns token secrets.

apiTokens_create

Write, proposal: needs a Read & write token

Needs the api_token:manage_own permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Create an API token for the caller. The plaintext token is returned once and cannot be recovered. scopes: ["read"] makes a read-only token (cannot run any write tool; resources stay readable), ["read","write"] (the default) a read and write token; client_viewer tokens are always read-only. Not available to callers authenticated by an API token.

name required
scopes optional
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

apiTokens_revoke

Write, own approval steps: needs a Read & write token

Needs the api_token:manage_own permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Revoke an API token by id. Members may revoke their own tokens; owners and admins may revoke any token in the organization.

id required
dryRun optional
Preview only: returns a preview and changes nothing.

apiTokens_current

Read: works with any token

Needs the api_token:manage_own permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Who is calling: the caller's organization, user email and role, plus the API token's id, name and scopes (token is null for a web session). Use it to test a connection.

webhooks tools

webhooks_list

Read: works with any token

Needs the webhook:manage permission. Roles with it: owner, admin.

List the organization's outgoing webhooks (owners and admins only), newest first, each with its status, why it was turned off if it was, and its most recent delivery. Never returns signing secrets.

webhooks_subscribe

Write, own approval steps: needs a Read & write token

Needs the webhook:manage permission. Roles with it: owner, admin.

Create an outgoing webhook that POSTs a signed JSON event to an https URL (port 443, public hosts only) when a new review arrives (event "review.created"). Owners and admins only; an API token needs the write scope. Executes directly (no proposal step); dryRun previews and checks the URL. The signing secret (starts "whsec_") is returned once and cannot be recovered: store it now. Optional workspaceId limits it to one client. At most 10 active webhooks per organization.

url required
events optional
workspaceId optional
description optional
dryRun optional
Preview only: returns a preview and changes nothing.

webhooks_unsubscribe

Write, own approval steps: needs a Read & write token

Needs the webhook:manage permission. Roles with it: owner, admin.

Delete an outgoing webhook by id, with its delivery history. Owners and admins only. Executes directly; dryRun previews.

id required
dryRun optional
Preview only: returns a preview and changes nothing.

webhooks_setStatus

Write, proposal: needs a Read & write token

Needs the webhook:manage permission. Roles with it: owner, admin.

Turn an outgoing webhook "active" or "disabled" by id. Turning it on again clears its failure count. Owners and admins only. At most 10 webhooks can be active.

id required
status required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

webhooks_deliveries

Read: works with any token

Needs the webhook:manage permission. Roles with it: owner, admin.

List the last 50 deliveries of one outgoing webhook, newest first: status, HTTP status code, attempts and times. Never returns the payload or the signing secret. Deliveries are kept for 30 days.

id required

webhooks_sendTest

Write, own approval steps: needs a Read & write token

Needs the webhook:manage permission. Roles with it: owner, admin.

Queue one sample "review.created" event (marked test: true) to an active outgoing webhook, signed like a real one. Owners and admins only. Executes directly; check the result with webhooks.deliveries.

id required
dryRun optional
Preview only: returns a preview and changes nothing.

billing tools

billing_get

Read: works with any token

Needs the billing:read permission. Roles with it: owner, admin.

Read this account's billing: state (trial, active, read-only), credit balance in USD, each credit grant with its expiry, recent usage and the top-up sizes. Hosted OpenGMB only; on a self-hosted server the state is 'off'. Never returns keys or payment details. Needs billing:read (owner, admin).

billing_topups_create

Write, proposal: needs a Read & write token

Needs the billing:manage permission. Roles with it: owner.

Start a prepaid top-up: creates a payment order for one of the configured top-up sizes (optionIndex into billing.get topUpOptionsUsd). The amount is decided by the server. Web only: not available to API tokens or MCP. Needs billing:manage (owner).

optionIndex required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

billing_topups_confirm

Write, proposal: needs a Read & write token

Needs the billing:manage permission. Roles with it: owner.

Confirm a top-up after checkout: verifies the payment signature against the order stored for this account, checks with the provider that it is paid for the right amount, then adds the credit once. If the provider has not marked it paid yet, nothing is added and the webhook finishes the job. Web only: not available to API tokens or MCP. Needs billing:manage (owner).

razorpayOrderId required
razorpayPaymentId required
razorpaySignature required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

billing_subscription_start

Write, proposal: needs a Read & write token

Needs the billing:manage permission. Roles with it: owner.

Start the monthly plan: creates a subscription for this account with the configured plan (the price and the included credit come from config, never from the caller) and returns what checkout needs. Nothing is charged until the owner pays in checkout. Refused when the plan is already active, a renewal is overdue, or the account is not billed. Web only: not available to API tokens or MCP. Needs billing:manage (owner).

dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

billing_subscription_confirm

Write, proposal: needs a Read & write token

Needs the billing:manage permission. Roles with it: owner.

Confirm the monthly plan after checkout: verifies the payment signature against the subscription stored for this account, asks the provider whether it is active, then activates it and adds the month's included credit once. If the provider has not activated it yet, nothing is added and the webhook finishes the job. Web only: not available to API tokens or MCP. Needs billing:manage (owner).

razorpaySubscriptionId required
razorpayPaymentId required
razorpaySignature required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

billing_subscription_cancel

Write, proposal: needs a Read & write token

Needs the billing:manage permission. Roles with it: owner.

Cancel the monthly plan at the end of the month already paid for. Access and the included credit last until then; nothing is refunded and nothing is charged again. Web only: not available to API tokens or MCP. Needs billing:manage (owner).

dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

googleConnections tools

googleConnections_list

Read: works with any token

Needs the google:read permission. Roles with it: owner, admin, manager.

List the Google accounts connected to the caller's organization for Business Profile access, newest first. Never returns token material. configured is false when the server has no Google OAuth credentials, in which case connecting is unavailable.

googleConnections_connect

Write, proposal: needs a Read & write token

Needs the google:manage permission. Roles with it: owner, admin.

Start connecting a Google account. Returns an authUrl that must be opened in a browser where the SAME user is signed in to OpenGMB; it expires at expiresAt (10 minutes) and works once. The connection is created when Google redirects back to OpenGMB.

dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

googleConnections_disconnect

Write, proposal: needs a Read & write token

Needs the google:manage permission. Roles with it: owner, admin.

Disconnect a Google account: revoke its refresh token at Google (best effort), then delete the connection. If Google could not be reached, the connection is still removed locally, revokedAtGoogle is false and warning says to remove access at https://myaccount.google.com/permissions.

id required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

notifications tools

notifications_list

Read: works with any token

Needs the notification:own permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

List the caller's own in-app notifications, newest first, with the total unreadCount. Only the caller's notifications in their organization are ever returned. Titles name the location, never review text.

unreadOnly optional
limit optional

notifications_markRead

Write, proposal: needs a Read & write token

Needs the notification:own permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Mark the caller's own notifications as read: pass ids (1-100 notification ids) or all: true. Ids that belong to someone else or do not exist are silently ignored; updated counts only notifications that were unread and the caller's.

ids optional
all optional
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

locations tools

locations_list

Read: works with any token

Needs the location:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

List locations the caller can see, newest first, with their groups. needsRelink is true when Google was disconnected and the location must be re-imported to re-link it. Optional filters: workspaceId, groupId, status (active|inactive). Optional locationIds (up to 500) for specific locations. Client roles only see their own workspaces.

workspaceId optional
groupId optional
status optional
locationIds optional

locations_listAvailable

Read: works with any token

Needs the location:manage permission. Roles with it: owner, admin, manager.

List the Google accounts and locations reachable through one of the organization's Google connections, each marked alreadyImported (with the workspace when it is in this organization; activeInAnotherOrg when another organization holds it active). Calls Google, so it runs outside any database transaction. Follows up to 20 pages of 100 per account; truncated is true if there were more.

connectionId required

locations_import

Write, proposal: needs a Read & write token

Needs the location:manage permission. Roles with it: owner, admin, manager.

Import Google locations into a workspace. Asynchronous: records the request and queues a worker job that fetches the details from Google itself (client-supplied details are never trusted) and creates the locations. Returns importId; poll locations.importStatus for per-location results (imported, already_imported, relinked, exists_inactive, conflict, not_found). A location already active in this workspace whose Google connection was removed is re-linked to the importing connection (relinked). A location already active in another organization or workspace is reported as conflict.

connectionId required
workspaceId required
locations required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

locations_importStatus

Read: works with any token

Needs the location:manage permission. Roles with it: owner, admin, manager.

Status of a locations.import request: pending, done (with per-location results) or failed (with a reason).

importId required

locations_setStatus

Write, proposal: needs a Read & write token

Needs the location:manage permission. Roles with it: owner, admin, manager.

Activate or deactivate up to 100 locations. Returns a result per location: updated, unchanged, conflict (activating a location whose Google location is active elsewhere, in any organization) or not_found. Inactive locations are excluded from sync, webhook processing, the inbox and the bulk tool.

locationIds required
status required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

locations_stats

Read: works with any token

Needs the location:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Per-location counts from OpenGMB's own tables, no Google call: synced reviews (total, average star rating, unreplied = reviews that need you: no visible reply and none waiting for approval or publish, or a reply that is blocked or failed, with the workspace reply policy applied, any age; waitingToPublish = approved reply not yet on Google), open profile changes (the alerts the change watch raised: snapshot diffs and Google-suggested edits) and whether a suspension case is open or appealed. Same order as locations.list (by name). Filters: workspaceId, locationIds (up to 500). Inactive locations are included. Client roles only see their own workspaces; ids outside the caller's scope are left out.

workspaceId optional
locationIds optional

locations_healthcheck

Read: works with any token

Needs the location:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Healthcheck of one location: a checklist of listing quality (description, categories, hours, phone, website, photos, posts, reviews, verification, place action links, attributes, services) with a score and a fix link for each failing check. Reads the profile, photos, posts, verification, place action links and attributes live from Google (outside any transaction) and reviews from our synced copy. Each check has an importance (necessary, important, nice), a status (pass, fail, unknown = the Google read failed, left out of the score) and a plain-language detail. score = passed / (passed + failed). Thresholds are our own choices (photo count, post age, rating ...), see config/healthcheck.ts. A check someone skipped (locations.healthcheckSkip) has status skipped and is left out of the score. Read only.

locationId required

locations_healthcheckSummary

Read: works with any token

Needs the location:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Runs the healthcheck (see locations.healthcheck) for each active, Google-linked location in the caller's scope, one after another, and returns per location its score and how many necessary checks fail, worst score first. Each location also lists its failing checks (id, title, importance; necessary first) and checkedAt. Optional workspaceId. Runs one page of 25 locations (our choice: each costs about 7 Google reads), by name; `offset` (default 0) is where the page starts and `total` is how many locations are in scope, so offset + locations.length < total means more pages follow. Optional locationIds (up to 500) or groupId narrows what is paged (a location or group scope). Client roles only see their own workspaces. Read only.

workspaceId optional
locationIds optional
groupId optional
offset optional

locations_healthcheckSkip

Write, proposal: needs a Read & write token

Needs the location:manage permission. Roles with it: owner, admin, manager.

Skip one health check for one location (skipped true) or undo it (false). A skipped check shows as skipped and is left out of the location's score everywhere (healthcheck, healthcheckSummary, overview) until undone. checkId is one of: description, primary_category, additional_categories, regular_hours, special_hours, phone, website, website_utm, service_items, photo_count, recent_photo, logo_photo, cover_photo, recent_post, unreplied_reviews, average_rating, new_reviews, verification, place_action_link, attributes. Idempotent. Writes nothing to Google.

locationId required
checkId required
skipped required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

locations_overview

Read: works with any token

Needs the location:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

One location's front page: its header facts (workspace, address, status, needsRelink), review/alert/suspension counts (as locations.stats), the last post OpenGMB published, change sets waiting for approval or apply that target it, the open suspension case with evidence progress, sync state, the 5 most recent events (changes found, change sets proposed, posts and replies published) and, for an active Google-linked location, one pass of the healthcheck's Google reads (about 7 calls, outside any transaction) giving the live health score, verification standing, primary category, today's hours and whether it is open now (both read in the workspace's time zone), phone, website, photos and booking links. Each Google part is null when its read failed; google is null for inactive or unlinked locations. Read only.

locationId required

locationGroups tools

locationGroups_list

Read: works with any token

Needs the location:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

List location groups the caller can see (optionally one workspace), with member location ids. Groups are per workspace.

workspaceId optional

locationGroups_create

Write, proposal: needs a Read & write token

Needs the location:manage permission. Roles with it: owner, admin, manager.

Create a location group in a workspace. Names are unique per workspace.

workspaceId required
name required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

locationGroups_rename

Write, proposal: needs a Read & write token

Needs the location:manage permission. Roles with it: owner, admin, manager.

Rename a location group. Names are unique per workspace.

groupId required
name required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

locationGroups_delete

Write, proposal: needs a Read & write token

Needs the location:manage permission. Roles with it: owner, admin, manager.

Delete a location group. Its locations are not deleted.

groupId required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

locationGroups_setMembers

Write, proposal: needs a Read & write token

Needs the location:manage permission. Roles with it: owner, admin, manager.

Replace a group's members with exactly these locations (empty clears it). Every location must be in the group's workspace, otherwise INVALID_INPUT and nothing changes.

groupId required
locationIds required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

reviews tools

reviews_sync

Write, proposal: needs a Read & write token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Request a review sync from Google for the active locations of a workspace (or just locationIds in it). Asynchronous: records one review_syncs row per location, audits it and queues a worker job per location in the same transaction; poll reviews.syncStatus with the returned syncIds. Inactive or unknown locations are listed in skipped. Replies made directly in Google are picked up too.

workspaceId required
locationIds optional
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

reviews_syncStatus

Read: works with any token

Needs the review:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Status of review syncs started with reviews.sync: pending, done (with counts fetched/inserted/updated) or failed (with an error). Only syncs for locations in the caller's workspaces are returned; unknown ids are omitted.

syncIds required

reviews_list

Read: works with any token

Needs the review:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

List Google reviews for active locations the caller can see. Order: sort newest (default; create time, then id), oldest, rating_high (5 stars first) or rating_low (1 star first); unrated reviews come last in both rating sorts and ties go newest first. Search: q finds reviews whose text or reviewer name contains the phrase (case-insensitive, matched literally, so % and _ are ordinary characters; an anonymous reviewer's name is not searched). Filters: workspaceId, locationIds, groupId, ratings (1-5), replied (true = Google shows a reply; false = the review needs you: no visible reply and no reply waiting for approval or publish, or a reply that is blocked or failed, with the workspace reply policy applied), from (inclusive) and to (exclusive) as ISO datetimes on the review's create time (UTC), topic (one of the ids reviews.classifyTopics uses: staff, wait_time, price_value, cleanliness, results_quality, communication, booking, location_parking, other) and sentiment (positive, negative or mixed: that topic's sentiment when topic is set, otherwise the review's overall sentiment); these two only match reviews already classified and not edited since. limit 1-100 (default 25); pass nextCursor as cursor for the next page. Client roles only see their own workspaces.

workspaceId optional
locationIds optional
groupId optional
ratings optional
replied optional
from optional
to optional
q optional
topic optional
sentiment optional
sort optional
cursor optional
limit optional
assignedToMe optional
overdue optional

reviews_export

Read: works with any token

Needs the review:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Export reviews as a CSV spreadsheet (UTF-8 with BOM, CRLF lines), newest first unless sort says otherwise, with the same filters, search (q), sort and visibility as reviews.list (workspaceId, locationIds, groupId, ratings, replied, from, to, q, sort; no paging). Columns: review date (UTC), location, stars, reviewer (Anonymous when hidden), review text, reply text, reply date, Google reply state, needs reply (yes/no, the same rule as the replied=false filter). Optional columns picks which columns to write (date, location, stars, reviewer, review, reply, replyDate, replyState, needsReply); they are written in that order; omitted means all nine. Leave out reviewer and review to export counts and ratings only. Capped at a fixed row maximum: truncated is true when more matched, so narrow the filters. Review text can contain patient details: the export is audited (reviews.exported) with filters and row count only, never the text.

workspaceId optional
locationIds optional
groupId optional
ratings optional
replied optional
from optional
to optional
q optional
topic optional
sentiment optional
sort optional
columns optional

reviews_get

Read: works with any token

Needs the review:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Get one review by id, with its current Google reply. Only reviews at active locations in the caller's workspaces are visible; anything else is NOT_FOUND.

id required

reviews_list_unreplied

Read: works with any token

Needs the review:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Bulk list of reviews with no visible Google reply (none, or one Google rejected), across every active location the caller can see, newest first (create time, then id). Optional filters: workspaceId, locationIds, ratings (1-5). Each item carries replyAllowed and skipReason (from the reply policy, e.g. reviews that must not be answered, or a reply already in progress) and openReply (the open draft or pending reply, if any) so you do not draft replies that will be blocked or refused; skipped items are left out unless includeSkipped is true. limit 1-200 (default 100); pass nextCursor as cursor for the next page. totalReturned is the number of items in this response, not a total.

workspaceId optional
locationIds optional
ratings optional
includeSkipped optional
cursor optional
limit optional

reviews_assign

Write, proposal: needs a Read & write token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Assign a review to a team member (an organization-wide owner, admin or manager; client roles cannot be assigned), with an optional due date (ISO datetime; omitted clears it) and an optional internal note added in the same step. Assigning again replaces the assignee and due date. assigneeUserId null removes the assignment. The assignee gets an in-app notification (and the daily email digest when email is configured) unless they assigned it to themselves. The notification names the location only, never the review or the note. Internal only: nothing here reaches Google or a reply. Needs review:draft.

reviewId required
assigneeUserId required
dueAt optional
note optional
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

reviews_assignees

Read: works with any token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Team members a review in this workspace can be assigned to: the organization-wide members (owner, admin, manager). Client roles are never listed. Needs review:draft.

workspaceId required

reviews_assignments

Read: works with any token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Who each of up to 100 reviews is assigned to, with the due date, whether it is overdue (due date passed and the review still needs a reply) and how many internal notes it has. Reviews with neither an assignment nor a note are left out. Only reviews the caller can see are considered. Needs review:draft: client roles never see assignments.

reviewIds required

reviews_analytics

Read: works with any token

Needs the review:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Review analytics by plain arithmetic over synced reviews, no AI: for the window from (inclusive) to (exclusive), ISO datetimes, at most 800 days, and the equally long window right before it. Returns totals (count, average rating to one decimal, reply rate 0 to 1, median hours from review to reply using Google's reply update time, number needing a reply: no reply or a reply Google rejected), new reviews and average rating per UTC month, the star distribution, and per location totals with a rating trend. Filters: workspaceId, locationIds, groupId. Active locations in the caller's workspaces only. Returns no review text, reviewer names or reply text. truncated is true when a window held more than 50,000 reviews.

workspaceId optional
locationIds optional
groupId optional
from required
to required

reviews_classifyTopics

Write, proposal: needs a Read & write token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Classify a client's reviews by topic and sentiment with AI (topics: staff, wait_time, price_value, cleanliness, results_quality, communication, booking, location_parking, other; sentiment positive, negative or mixed, per topic and overall). Takes reviews that have text and no current classification, newest first, up to 200 per run (remaining says how many still wait; run again). Several reviews go in one AI call. A review that was already classified and has not been edited is never classified or paid for again; an edited review is classified again. A review the AI answered badly twice is marked unclassified and is retried by the next run. Metered and capped like drafts: stopped 'cap' means a monthly AI limit was reached (what was done is kept), 'error' means the AI service failed. Only topics and sentiment are stored, never the review text, and review text is never logged. Optional locationIds narrows to those locations of the client. NOT_CONFIGURED when this server has no AI key. Needs review:draft (owner, admin, manager).

workspaceId required
locationIds optional
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

reviews_topicTrends

Read: works with any token

Needs the review:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Review topics over the last 12 weeks (UTC weeks starting Monday, by the review's create time), from reviews already classified by reviews.classifyTopics (nothing here calls AI). For the whole scope: per topic the number of mentions (total) and how many were positive, negative or mixed, with positiveShare and negativeShare (0 to 1, null when no mentions), and the same counts for each week. Per location: the same per-topic counts over the window. Also classifiedReviews and the overall sentiment counts. Reviews edited since they were classified are left out until classified again. Filters: workspaceId, locationIds, groupId. Active locations in the caller's clients only. Counts only: no review text or reviewer names. truncated is true when more than 50000 reviews matched.

workspaceId optional
locationIds optional
groupId optional

reviewNotes tools

reviewNotes_add

Write, proposal: needs a Read & write token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Add an internal note to a review (up to 2000 characters). Notes are for the team only: they are never sent to Google, never part of a reply, and client roles cannot see them. The audit entry records that a note was added, not its text. Needs review:draft.

reviewId required
body required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

reviewNotes_list

Read: works with any token

Needs the review:draft permission. Roles with it: owner, admin, manager.

The internal notes on a review, oldest first, with who wrote each. Team only (needs review:draft): client roles never see notes.

reviewId required

reviewRequests tools

reviewRequests_create

Write, proposal: needs a Read & write token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Create a draft email campaign that asks customers of one location to leave a Google review. Every recipient gets the same message and the same link to Google's review form; there is no rating question and no routing of unhappy customers. Refuses a location that has no review link yet (create it with reviewLinks.save first, it holds the Google place id). subject and body may use {name} and {business}; omitted, a plain default is used. At most one reminder, reminderDays (1 to 14, default 3) after the first email, only to people who have not clicked. Nothing is sent until reviewRequests.start. Needs review:draft (owner, admin, manager).

locationId required
name required
subject optional
body optional
reminderEnabled optional
reminderDays optional
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

reviewRequests_update

Write, proposal: needs a Read & write token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Change a DRAFT review request campaign: name, subject, body, reminder on or off, reminder days (1 to 14). A started campaign cannot be edited (cancel it and make a new one). Needs review:draft.

campaignId required
name optional
subject optional
body optional
reminderEnabled optional
reminderDays optional
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

reviewRequests_addRecipients

Write, proposal: needs a Read & write token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Add customers (email and optional name) to a draft or running campaign, one or a few at a time. confirmPermission must be true: the caller confirms they have permission to email these customers (recorded in the audit log, counts only, never the addresses). Addresses are lower-cased; duplicates, invalid addresses and addresses that opted out of this client earlier are not emailed and are counted in the answer. Needs review:draft.

campaignId required
recipients required
confirmPermission required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

reviewRequests_importCsv

Write, proposal: needs a Read & write token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Add customers from CSV text to a draft or running campaign. The first row may be a header with an "email" column and a "name" or "first name" column; without a header column 1 is the email and column 2 the name. At most 500 rows per import. confirmPermission must be true (recorded in the audit log, counts only). Same rules as addRecipients. Needs review:draft.

campaignId required
csv required
confirmPermission required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

reviewRequests_start

Write, proposal: needs a Read & write token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Start a draft campaign. Refused unless email sending is set up, the public app URL is configured, the location still has its review link, there is at least one recipient waiting, and the subject and message pass the wording check (no ratings, stars, surveys or 'how was your visit') and the universal and post guardrail packs. Sending then happens in the background: the worker paces it (a daily limit for the whole server, only 08:00 to 21:00 in the client's time zone). Needs review:draft.

campaignId required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

reviewRequests_cancel

Write, proposal: needs a Read & write token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Cancel a campaign: no further first emails or reminders go out. Emails already sent stay sent. Needs review:draft.

campaignId required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

reviewRequests_list

Read: works with any token

Needs the review:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Review request email campaigns, newest first, each with its results: recipients, sent, clicked, opted out, reminder sent, skipped, failed, waiting. Optionally for one location. Counts only, no customer addresses. Delivery confirmation is not tracked. Needs review:read (client roles can view results).

locationId optional
limit optional

reviewRequests_get

Read: works with any token

Needs the review:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

One review request campaign with its results (counts only). Needs review:read.

campaignId required

reviewRequests_recipients

Read: works with any token

Needs the review:draft permission. Roles with it: owner, admin, manager.

The customers of a campaign with their status (email addresses and names: personal data). Needs review:draft, so client roles do not see it.

campaignId required
limit optional
offset optional

locationPages tools

locationPages_get

Read: works with any token

Needs the location:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

The public landing page of one location: whether it is published, its slug and its path (/l/<slug> on the app's address). The page is off until someone publishes it and shows only data OpenGMB already holds. page is null when it was never published. Read only. Needs location:read.

locationId required

locationPages_set

Write, proposal: needs a Read & write token

Needs the location:manage permission. Roles with it: owner, admin, manager.

Publish or unpublish the public landing page of an active location (published true or false). The first publish creates the page and its public slug; unpublishing keeps the slug and makes the address return 404 and stay out of search. The page shows the profile (name, categories, description, hours, address, phone, website, services), recent reviews with a comment (the review widget's rules apply), recent Google posts and the agency branding. Does not write to Google. Needs location:manage (owner, admin, manager).

locationId required
published required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

reviewReplies tools

reviewReplies_check

Read: works with any token

Needs the review:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Dry-run the reply guardrails for a candidate reply to a review. Writes nothing and stores nothing. Returns { ok, violations, packs }: ok is false when any violation has severity block (blocks cannot be overridden); warn violations need acknowledgeWarnings on submit/publish. Each violation has ruleId, packId, severity, status (active or pending_counsel_review), message and match offsets into the reply. Use it to check an AI-drafted reply before reviewReplies.createDraft.

reviewId required
body required

reviewReplies_list

Read: works with any token

Needs the review:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

All reply revisions of one review, newest revision first, with each revision's status, guardrail result and what the caller may do next (can.edit/submit/approve/reject/publish). The review block says whether the caller can start a draft (canDraft: no open revision), delete the Google reply, and whether a Google reply exists. Poll this after reviewReplies.publish.

reviewId required

reviewReplies_listQueue

Read: works with any token

Needs the review:approve permission. Roles with it: owner, admin, manager, client_approver.

Approval and attention queue: replies in one status (pending_approval, blocked, failed, approved or conflict) across the workspaces the caller can see (or one workspaceId), at active locations, oldest update first. Each item carries the reply (with guardrail result and can.* flags) and the review it answers. limit 1-100 (default 25); pass nextCursor as cursor for the next page.

workspaceId optional
status required
cursor optional
limit optional

reviewReplies_createDraft

Write, own approval steps: needs a Read & write token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Create a draft reply to a review. A review has at most one open revision (draft, pending_approval, approved, blocked or failed): if one exists this is CONFLICT and the message names its id (use reviewReplies.updateDraft). If the review already has a Google reply this opens a new revision that, once published, replaces it. The draft remembers Google's reply as it is now: if someone changes that reply on Google before publishing, the publish is refused with status conflict (nothing is written to Google) and you open a new revision from Google's current reply. The draft is not sent anywhere: call reviewReplies.submit, which runs the guardrails.

reviewId required
body required
dryRun optional
Preview only: returns a preview and changes nothing.

reviewReplies_updateDraft

Write, own approval steps: needs a Read & write token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Replace the text of a reply that is a draft or blocked (a blocked reply goes back to draft, with its guardrail result cleared). Replies that are pending approval, approved, failed or published cannot be edited: reject it, or open a new revision for a published one.

id required
body required
dryRun optional
Preview only: returns a preview and changes nothing.

reviewReplies_submit

Write, own approval steps: needs a Read & write token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Submit a draft reply: runs the guardrails. Any block-severity violation sets status blocked and returns the violations (not an error). Warnings only: the reply stays a draft and the result has outcome needs_acknowledgement and code WARNINGS_REQUIRE_ACKNOWLEDGEMENT; call again with acknowledgeWarnings true to proceed. Otherwise the workspace approval rule decides: approved (auto-approve; never for 1-3 star reviews) or pending_approval; if the workspace also auto-publishes, a publish job is queued. Guardrails run again just before anything is sent to Google.

id required
acknowledgeWarnings optional
dryRun optional
Preview only: returns a preview and changes nothing.

reviewReplies_approve

Write, own approval steps: needs a Read & write token

Needs the review:approve permission. Roles with it: owner, admin, manager, client_approver.

Approve a reply that is pending approval (pending_approval -> approved). Approving does not publish: call reviewReplies.publish. Client approvers can approve replies in their own workspaces only.

id required
dryRun optional
Preview only: returns a preview and changes nothing.

reviewReplies_reject

Write, own approval steps: needs a Read & write token

Needs the review:approve permission. Roles with it: owner, admin, manager, client_approver.

Reject a reply that is pending approval: it goes back to draft with the reason shown to the author (pending_approval -> draft). The author edits and resubmits.

id required
reason required
dryRun optional
Preview only: returns a preview and changes nothing.

reviewReplies_publish

Write, own approval steps: needs a Read & write token

Needs the review:publish permission. Roles with it: owner, admin, manager.

Queue publishing of an approved (or failed) reply to Google. Asynchronous and does not call Google: it records the request, audits it and queues a worker job in the same transaction, returning { queued: true }. The worker runs the guardrails again and then sends the reply; poll reviewReplies.list until the status is published, failed (failureReason), blocked or conflict (someone changed the reply on Google after the draft; nothing was written, open a new revision). acknowledgeWarnings true accepts warn-severity violations that appear at publish time. A failed reply is retried by calling this again.

id required
acknowledgeWarnings optional
dryRun optional
Preview only: returns a preview and changes nothing.

reviewReplies_deletePublished

Write, own approval steps: needs a Read & write token

Needs the review:publish permission. Roles with it: owner, admin, manager.

Queue removal of the review's Google reply (a reply published here or made in Google). Asynchronous: audits the request and queues a worker job in the same transaction, returning { queued: true }. When the job finishes the review has no reply and the published revision is deleted. CONFLICT if the review has no Google reply.

reviewId required
dryRun optional
Preview only: returns a preview and changes nothing.

workspaceSettings tools

workspaceSettings_get

Read: works with any token

Needs the review:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Get a workspace's reply settings: profile (general, healthcare, legal), guardrail packs, whether positive (4-5 star) reviews are skipped, generic-templates-only, staff names (used by the H2.staff guardrail) and approval rules (autoApproveMinStars 4, 5 or null; autoPublish) and h2Severity (block or warn: whether the HIPAA H2.* rules block or only warn). A workspace that was never configured returns the defaults. 1-3 star replies are always manual and never auto-published.

workspaceId required

workspaceSettings_update

Write, proposal: needs a Read & write token

Needs the review:configure permission. Roles with it: owner, admin.

Update a workspace's reply settings; only the fields you pass change. Changing profile first applies that profile's defaults (healthcare: hipaa pack on, skipPositiveReviews on, generic templates only; legal: legal_ethics pack on; general: none), then the other fields in the same call override them. packs may contain hipaa and legal_ethics (universal always runs); the profile's required pack cannot be removed. staffNames: up to 200 names of 2-80 characters. autoApproveMinStars: 4, 5 or null (off); autoPublish: publish automatically once approved. h2Severity: block (default) or warn, for all HIPAA H2.* rules together (reviewer/provider/staff names, clinical terms, dates, echoed review text); only has an effect while the hipaa pack is on, and warnings still need acknowledgeWarnings. 1-3 star replies are always manual and never auto-published. Needs review:configure (owner, admin).

workspaceId required
profile optional
packs optional
skipPositiveReviews optional
staffNames optional
autoApproveMinStars optional
autoPublish optional
h2Severity optional
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

replyTemplates tools

replyTemplates_list

Read: works with any token

Needs the review:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

List a workspace's reply templates, ordered by name. generic is true when the body uses no reviewer-specific variable ({reviewer_first_name}); healthcare workspaces can only render generic templates. Variables: {reviewer_first_name}, {location_name}, {phone}.

workspaceId required

replyTemplates_create

Write, proposal: needs a Read & write token

Needs the review:configure permission. Roles with it: owner, admin.

Create a reply template in a workspace. Names are unique per workspace. The body may use only {reviewer_first_name}, {location_name}, {phone}; any other {variable} is INVALID_INPUT. generic is computed from the body. Needs review:configure (owner, admin).

workspaceId required
name required
body required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

replyTemplates_update

Write, proposal: needs a Read & write token

Needs the review:configure permission. Roles with it: owner, admin.

Rename a reply template and/or change its body (same variable rules as replyTemplates.create: only {reviewer_first_name}, {location_name}, {phone}). generic is recomputed. Needs review:configure (owner, admin).

id required
name optional
body optional
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

replyTemplates_delete

Write, proposal: needs a Read & write token

Needs the review:configure permission. Roles with it: owner, admin.

Delete a reply template. Needs review:configure (owner, admin).

id required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

replyTemplates_render

Read: works with any token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Render a reply template for a review and return the text only (nothing is saved or published; use it as a draft body, guardrails still apply). {reviewer_first_name} is the first word of the reviewer's name (error "reviewer name unavailable" for anonymous reviewers), {location_name} the location's title, {phone} its phone number (error naming the variable if missing). In a workspace with generic-templates-only (healthcare profile), non-generic templates are FORBIDDEN. The template and review must be in the same workspace.

templateId required
reviewId required

postImages tools

postImages_list

Read: works with any token

Needs the review:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

List a workspace's post image library (JPG or PNG, up to 5 MB each, newest first, at most 500). Each image has a public `url`: pass it as a post's media sourceUrl (posts.createDraft / posts.updateDraft, one image per post) to attach it. `usedIn` lists the posts that use it with their status; canDelete is false while a pending, approved, scheduled or publishing post uses it. Images are uploaded in the web app; agents cannot upload or delete.

workspaceId required

postImages_rename

Write, proposal: needs a Read & write token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Rename an image in the post image library (a display name only; the public URL does not change). Needs review:draft (owner, admin, manager).

id required
name required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

postImages_delete

Write, own approval steps: needs a Read & write token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Delete an image from the post image library. Refused (CONFLICT) while a pending, approved, scheduled or publishing post uses it. Posts already on Google keep their copy; a draft that uses it will show a missing image. Not available to agents (FORBIDDEN over MCP). Needs review:draft.

id required
dryRun optional
Preview only: returns a preview and changes nothing.

postImages_renderBranded

Write, proposal: needs a Read & write token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Make a branded post image: take a photo from the client's post image library (photoImageId from postImages.list), draw the client's uploaded logo (if it has one) and a headline plus optional second line over it in a fixed white layout ('band' along the bottom, or 'frame'), and save the result to the same library as a 1200x900 JPEG. Returns the new image; put its url in a post's media sourceUrl. The same inputs always give the same image. Latin-script (English) text only. Needs review:draft.

workspaceId required
photoImageId required
layout required
headline required
subline optional
useLogo optional
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

postTemplates tools

postTemplates_list

Read: works with any token

Needs the review:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

List a workspace's post templates (name order). A template holds a post type (STANDARD, EVENT or OFFER), language, text, call to action, event title, offer fields and one library image; it has no locations, send time or event dates. To post from one, read it and call posts.createDraft with its content (a post made from a template is an ordinary draft).

workspaceId required

postTemplates_get

Read: works with any token

Needs the review:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Get one post template by id.

id required

postTemplates_create

Write, proposal: needs a Read & write token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Create a post template in a workspace. Names are unique per workspace (CONFLICT otherwise). imageId must be an image from postImages.list. Needs review:draft (owner, admin, manager).

workspaceId required
name required
topicType required
language required
summary optional
cta optional
eventTitle optional
offer optional
imageId optional
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

postTemplates_update

Write, proposal: needs a Read & write token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Replace a post template's content (send every field; imageId null removes the image). Posts already made from it are not changed. Needs review:draft.

id required
name required
topicType required
language required
summary optional
cta optional
eventTitle optional
offer optional
imageId optional
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

postTemplates_delete

Write, proposal: needs a Read & write token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Delete a post template. Posts already made from it are not affected. Needs review:draft.

id required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

posts tools

posts_check

Read: works with any token

Needs the review:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Dry-run the post guardrails for a candidate Google Business Profile post. Writes nothing. Returns { ok, violations, packs }: ok is false when any violation has severity block (blocks cannot be overridden); warn violations need acknowledgeWarnings on posts.submit. Rules (pack post): no phone numbers in text (use a CALL button, which uses the location's phone), summary at most 1,500 characters, at most 1 image, call to action rules (URL required except for CALL, none for CALL), ALERT restrictions, EVENT/OFFER need an event title and dates. Healthcare workspaces also apply H1 (care relationship wording), provider and staff names; legal workspaces apply LE3/LE4. Pass locationIds to check with those locations' names and phones.

workspaceId required
locationIds optional
topicType required
alertType optional
summary optional
cta optional
event optional
offer optional
media optional

posts_list

Read: works with any token

Needs the review:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Posts the caller can see, newest first. Filters: workspaceId, status, topicType, q (case-insensitive text in the summary), locationId (posts that target it), from (inclusive) and to (exclusive) ISO datetimes applied to the scheduled time (or the creation time when unscheduled). sort oldest_submitted lists the earliest submission first (unsubmitted last) instead of newest first. limit 1-100 (default 50). Each post carries its per-location targets. Use status pending_approval for the approval queue. googleOnly lists posts that are live on Google but were made outside OpenGMB (same filters, except status: only with no status or published); an OpenGMB post that is also on Google appears in posts only.

workspaceId optional
status optional
topicType optional
q optional
sort optional
locationId optional
from optional
to optional
limit optional

posts_googleList

Read: works with any token

Needs the location:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

List the posts currently on a location's Google Business Profile, live from Google, including ones made outside this app (in the Google UI or another tool). Newest first as Google returns them. managedHere marks posts this app published. Read only; calls Google, so it runs outside any database transaction.

locationId required

posts_syncGoogle

Read: works with any token

Needs the location:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Refresh OpenGMB's copy of one location's Google posts now, so All posts, the Calendar, Home, Performance and the Overview include posts made outside OpenGMB without waiting for the review sync (every 2 hours). Reads the posts from Google and stores them (a cache: Google is not changed, nothing is audited). Returns how many Google listed (fetched), how many stored copies of posts no longer on Google were dropped (removed), and truncated when Google had more pages than we read. Calls Google, so it runs outside any database transaction.

locationId required

posts_get

Read: works with any token

Needs the review:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

One post with its content, status, guardrail result, what the caller may do next (can.*) and the per-location results of every send (targets: status, googlePostName, publishedAt, error reason code).

id required

posts_calendar

Read: works with any token

Needs the review:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Calendar entries between from (inclusive) and to (exclusive), at most 366 days apart: scheduled sends, projected future occurrences of recurring posts (expanded only inside the window, respecting until/count), and past sends (published, failed or skipped, grouped per post and occurrence with per-status location counts), plus posts made outside OpenGMB that are live on Google (kind google, on their Google date). Optional workspaceId, and optional locationIds (up to 500) or groupId to keep only entries that touch those locations. Entry times are ISO instants. truncated is true if the entry cap (1000) was hit.

from required
to required
workspaceId optional
locationIds optional
groupId optional

posts_createDraft

Write, own approval steps: needs a Read & write token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Create a draft Google Business Profile post for one or more locations of a workspace. topicType STANDARD (summary, optional CTA and one image), EVENT (event title + start/end dates, times optional), OFFER (event plus optional couponCode, redeemOnlineUrl, termsConditions; Google ignores a CTA on offers) or ALERT (alertType COVID_19; Google has disabled new COVID_19 alerts). callToAction actionType BOOK, ORDER, SHOP, LEARN_MORE, SIGN_UP (all need an https url) or CALL (no url; uses the location's phone). media: one image by URL (uploads are not built yet). Do not put phone numbers in the summary. The draft is not sent anywhere: call posts.submit, which runs the guardrails. Content problems do not fail this call; posts.check shows them. language: the post's language, a BCP 47 code (en, es, fr, de, it, pt, nl, vi, zh, ko, ja, ar, hi, gu); omitted = the workspace's default post language (workspaces.list defaultPostLanguage). Sent to Google as languageCode. A bilingual post is two posts. scheduledFor (optional, ISO datetime with offset, not in the past) is the send time picked in Compose: it is only remembered on the draft and shown to the approver, nothing is sent until posts.schedule.

workspaceId required
locationIds required
language optional
scheduledFor optional
topicType required
alertType optional
summary optional
cta optional
event optional
offer optional
media optional
dryRun optional
Preview only: returns a preview and changes nothing.

posts_bulkPreview

Read: works with any token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Dry-run a bulk post import. csv is the text of a CSV file with a header row (get the columns from the Import page's template): location (name or id), type (STANDARD default, EVENT, OFFER), summary, optional cta_type, cta_url, scheduled (YYYY-MM-DD HH:MM in the client's time zone, remembered on the draft only), image_url, event_title, event_start_date, event_end_date, event_start_time, event_end_time, coupon_code, redeem_url, terms. Variables {name}, {city}, {phone}, {address}, {website} in any text are filled from each row's location; an unknown variable or one with no stored value for that location is a row error (never left blank). At most 500 rows. Writes nothing. Returns per-row errors (the row cannot be created) and warnings (guardrail findings: the draft would exist but could not be submitted, for example a phone number written into the text). fileErrors means the file itself cannot be read and no rows are listed.

workspaceId required
csv required

posts_bulkCreateDrafts

Write, own approval steps: needs a Read & write token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Create one DRAFT post per row of a CSV (same format and variables as posts.bulkPreview, at most 500 rows). ALL OR NOTHING: the file is re-validated here, and if the file or any row has an error nothing is created (INVALID_INPUT lists the first problems; run posts.bulkPreview and fix them). Each draft is made exactly as posts.createDraft makes it (one location, the workspace's default language, audit row per draft), so it still needs posts.submit, approval and posts.schedule: nothing is submitted, scheduled or sent. Guardrail findings do not stop a draft (posts.check shows them; submit blocks).

workspaceId required
csv required
dryRun optional
Preview only: returns a preview and changes nothing.

posts_updateDraft

Write, own approval steps: needs a Read & write token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Change a post that is a draft or blocked (a blocked post goes back to draft, with its guardrail result cleared). Send only the fields to change; a field sent as null (cta, event, offer, alertType) is cleared; media replaces the list; locationIds replaces the target locations. Posts that are pending approval, approved, scheduled or published cannot be edited: reject or cancel first. language changes the post's language. scheduledFor changes the remembered send time (null clears it; not in the past); omitted keeps it.

id required
locationIds optional
language optional
scheduledFor optional
topicType optional
alertType optional
summary optional
cta optional
event optional
offer optional
media optional
dryRun optional
Preview only: returns a preview and changes nothing.

posts_submit

Write, own approval steps: needs a Read & write token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Submit a draft post: runs the guardrails for every target location. Any block-severity violation sets status blocked and returns the violations (not an error). Warnings only: the post stays a draft with outcome needs_acknowledgement and code WARNINGS_REQUIRE_ACKNOWLEDGEMENT; call again with acknowledgeWarnings true. Otherwise the post becomes pending_approval: posts always need a person with approval rights (there is no auto-approve). Guardrails run again, per location, just before the post is sent to Google.

id required
acknowledgeWarnings optional
dryRun optional
Preview only: returns a preview and changes nothing.

posts_approve

Write, own approval steps: needs a Read & write token

Needs the review:approve permission. Roles with it: owner, admin, manager, client_approver.

Approve a post that is pending approval (pending_approval -> approved). Approving does not send it: call posts.schedule. Client approvers can approve posts in their own workspaces only.

id required
dryRun optional
Preview only: returns a preview and changes nothing.

posts_reject

Write, own approval steps: needs a Read & write token

Needs the review:approve permission. Roles with it: owner, admin, manager, client_approver.

Reject a post that is pending approval: it goes back to draft with the reason shown to the author (pending_approval -> draft). The author edits and resubmits.

id required
reason required
dryRun optional
Preview only: returns a preview and changes nothing.

posts_schedule

Write, own approval steps: needs a Read & write token

Needs the review:publish permission. Roles with it: owner, admin, manager.

Schedule an approved post. Google's native scheduling is not used: Synectus keeps the schedule and a worker sweeps every minute, sending posts that are due (so a send can be up to about a minute late). Omit scheduledFor to send now (the worker is queued in this call, nothing is sent to Google inside it). scheduledFor is an ISO datetime with offset (an instant), not in the past. recurrence { freq weekly|monthly, interval (default 1), and until (inclusive, ISO) and/or count (total sends including the first) } repeats it; one of until or count is required; a series keeps the same local clock time in the workspace's time zone (workspaces.list timeZone) across daylight-saving changes. locationIds optionally replaces the target locations. The worker runs the guardrails again for each location right before sending; one location failing does not stop the others. Poll posts.get for per-location results.

id required
scheduledFor optional
recurrence optional
locationIds optional
dryRun optional
Preview only: returns a preview and changes nothing.

posts_cancel

Write, own approval steps: needs a Read & write token

Needs the review:publish permission. Roles with it: owner, admin, manager.

Cancel a post that has not been sent: draft, blocked, pending_approval, approved or scheduled (a recurring series stops; posts already published stay on Google, use posts.deletePublished to remove them). A post that is being sent right now (publishing) cannot be cancelled: CONFLICT.

id required
dryRun optional
Preview only: returns a preview and changes nothing.

posts_deletePublished

Write, own approval steps: needs a Read & write token

Needs the review:publish permission. Roles with it: owner, admin, manager.

Queue removal of the Google posts this post published (at all its locations, or only locationIds). Asynchronous: audits the request and queues a worker job in the same transaction, returning { queued: true }. When the job finishes those per-location results are deleted (Google 404 counts as deleted). CONFLICT if there is nothing published to delete.

id required
locationIds optional
dryRun optional
Preview only: returns a preview and changes nothing.

posts_proposeEdit

Write, own approval steps: needs a Read & write token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Propose a change to a post that is already published on Google (post status published). Nothing is sent to Google until a person with approval rights approves it (posts.approveEdit); then the worker patches the live post at each location with Google's localPosts.patch, naming only the changed fields in the updateMask. Send only the fields to change: summary, cta, event, offer, media (a null or empty field is cleared on Google). The topic type and language cannot change; a different type is a new post. The guardrails run now for every location the post is live at (a block-severity violation stores nothing and returns outcome blocked; warnings need acknowledgeWarnings) and again per location right before the patch. One open edit per post. CONFLICT if the post is not published, has no live Google post, or already has an open edit. Posts made on Google outside OpenGMB cannot be edited here. Google writes stay off unless GOOGLE_BUSINESS_WRITES is live: the edit then fails per location with google_writes_disabled.

id required
summary optional
cta optional
event optional
offer optional
media optional
acknowledgeWarnings optional
dryRun optional
Preview only: returns a preview and changes nothing.

posts_approveEdit

Write, own approval steps: needs a Read & write token

Needs the review:approve permission. Roles with it: owner, admin, manager, client_approver.

Approve a proposed edit of a published post (pending_approval -> applying). This is the step that lets the change reach Google: it queues a worker job that patches the live post at each location, running the guardrails again per location first. Poll posts.editGet for the per-location results. Client approvers can approve edits in their own workspaces only.

id required
dryRun optional
Preview only: returns a preview and changes nothing.

posts_rejectEdit

Write, own approval steps: needs a Read & write token

Needs the review:approve permission. Roles with it: owner, admin, manager, client_approver.

Reject a proposed edit of a published post, with the reason shown to the author (pending_approval -> rejected). The live post is untouched; propose a new edit to try again.

id required
reason required
dryRun optional
Preview only: returns a preview and changes nothing.

posts_cancelEdit

Write, own approval steps: needs a Read & write token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Withdraw a proposed edit that is still waiting for approval (pending_approval -> cancelled). The live post is untouched.

id required
dryRun optional
Preview only: returns a preview and changes nothing.

posts_editGet

Read: works with any token

Needs the review:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

The latest proposed edit of a published post (any status), with the per-location results once it was approved, and whether the caller may propose a new one (canPropose: the post is published, has a live Google post and no open edit, and the caller may draft).

id required

geogrid tools

geogrid_configs_list

Read: works with any token

Needs the geogrid:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

List geo-grid configurations the caller can see (a business, keywords, grid size and radius, data source, schedule). Optional filters: workspaceId, locationId. kind defaults to 'tracker'; pass 'quick_scan' for quick scans of businesses that are not managed locations (their locationId is null). Each config carries driverLabel and isMapsRank: the 'places_relevance' source is labelled 'Relevance check (not Maps rank)' and its positions are NOT Google Maps rank. Needs geogrid:read.

workspaceId optional
locationId optional
kind optional

geogrid_configs_create

Write, proposal: needs a Read & write token

Needs the geogrid:manage permission. Roles with it: owner, admin, manager.

Create a geo-grid configuration for a location. centerLat/centerLng are required; geogrid.locationCenter reads them (and the place id) from the location's Google profile. gridSize is odd, 3 to 13; radiusM is the distance from the centre to the edge (100 to 50000). targetName defaults to the location's title; targetPlaceId (Google place id) is required for driverId 'places_relevance', which is a relevance check, NOT Maps rank. driverId 'dataforseo_standard' is the Maps-rank source and costs money (see geogrid.preview). Needs geogrid:manage (owner, admin, manager).

locationId required
keywords required
gridSize required
radiusM required
centerLat required
centerLng required
targetName optional
targetPlaceId optional
driverId optional
schedule optional
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

geogrid_locationCenter

Read: works with any token

Needs the geogrid:manage permission. Roles with it: owner, admin, manager.

Where a new tracker for a location should be centred, read from the location's Google profile: centerLat, centerLng (null when Google has no coordinates for it) and placeId (Google's place id, null when it cannot be read). note says why a value is missing (not linked to Google, no connection, Google could not be read) so the caller can ask the person to type it. Read only; does not change the location. Needs geogrid:manage (owner, admin, manager).

locationId required

geogrid_configs_update

Write, proposal: needs a Read & write token

Needs the geogrid:manage permission. Roles with it: owner, admin, manager.

Change a geo-grid configuration (any of keywords, favoriteKeywords, gridSize, radiusM, centerLat, centerLng, targetName, targetPlaceId, driverId, schedule, active). favoriteKeywords is the full list of starred keywords (a subset of keywords, matched case-insensitively); removing a keyword drops its star. Past runs keep the settings they ran with. Schedules (daily, weekly, monthly) enqueue runs automatically and are subject to the org's monthly budget. Needs geogrid:manage.

id required
keywords optional
favoriteKeywords optional
gridSize optional
radiusM optional
centerLat optional
centerLng optional
targetName optional
targetPlaceId optional
driverId optional
schedule optional
active optional
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

geogrid_configs_delete

Write, proposal: needs a Read & write token

Needs the geogrid:manage permission. Roles with it: owner, admin, manager.

Delete a geo-grid configuration together with its runs and results. Spend already charged still counts toward this month's budget only while the runs exist, so prefer setting active=false to keep history. Needs geogrid:manage.

id required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

geogrid_preview

Read: works with any token

Needs the geogrid:cost permission. Roles with it: owner, admin, manager.

Cost preview before running: estimate = points (gridSize squared) x keywordCount x the driver's per-task price x (1 + the org's markup). Pass speed ('standard' or 'fast', default the org's default speed) to price one speed; `speeds` always lists every speed side by side (standard: normal queue, about 5 min, $0.0006/task; fast: DataForSEO high priority, about 1 min, $0.0012/task). Returns the estimate, this UTC month's spend so far (queued and running runs count at their estimate), the monthly budget, what remains, and wouldExceed. The relevance check (places_relevance) is free and not Maps rank. Needs geogrid:cost (owner, admin, manager; hidden from client roles).

driverId required
gridSize required
keywordCount required
speed optional

geogrid_run

Write, proposal: needs a Read & write token

Needs the geogrid:manage permission. Roles with it: owner, admin, manager.

Run a geo-grid now: queues one run per keyword of the configuration (results arrive asynchronously; poll geogrid.runs.get). Fails with FORBIDDEN 'BUDGET_EXCEEDED' if the total estimate does not fit in the org's remaining monthly budget, or 'PLATFORM_CAP_EXCEEDED' when the service-wide daily DataForSEO limit is used up (the org's owners and admins are notified either way); call geogrid.preview first. Optional speed ('standard' or 'fast', default the org's default speed) picks the DataForSEO queue: fast is high priority, about 1 min, twice the price. Needs geogrid:manage.

configId required
speed optional
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

geogrid_quickScans_create

Write, proposal: needs a Read & write token

Needs the geogrid:manage permission. Roles with it: owner, admin, manager.

Quick scan of any business (for example a prospect) that is not a managed location: one keyword over a grid around centerLat/centerLng, matched by its Google place id (placeId, required; business search is not available on this server, so the id is pasted). Creates a quick-scan configuration (kind 'quick_scan', no location, schedule manual) in workspaceId and queues its first run in the same step; uses the same budget, prices and own-key rules as trackers and fails with FORBIDDEN 'BUDGET_EXCEEDED' (nothing created) when the estimate does not fit (see geogrid.preview). Re-run with geogrid.run, read with geogrid.runs.list kind 'quick_scan' and geogrid.runs.get, remove with geogrid.configs.delete. Needs geogrid:manage (owner, admin, manager).

workspaceId required
businessName required
placeId required
keyword required
speed optional
gridSize required
radiusM required
centerLat required
centerLng required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

geogrid_runs_list

Read: works with any token

Needs the geogrid:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

List geo-grid runs, newest first, each with average rank (not found counts as 21), top-3 share and found share. Use it as history: filter by configId to see one configuration over time. limit defaults to 50 (max 200). Runs from the relevance check carry isMapsRank=false. kind (default 'tracker') picks trackers or quick scans. costEstimateUsd, costChargedUsd and providerCostUsd are null unless the role has geogrid:cost. dataSource is fixture, sandbox or live: only live runs are real Google Maps data. Needs geogrid:read.

configId optional
workspaceId optional
kind optional
limit optional

geogrid_runs_get

Read: works with any token

Needs the geogrid:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

One geo-grid run with every point (row 0 is north, col 0 is west; rank null = not found in the top 20 or not collected yet) and its analytics: average rank (not found counts as 21), top-3 share, found share. Each point has pending (not collected yet); before the worker starts, points are the planned grid, all pending. progress counts collected points. If isMapsRank is false the numbers are a relevance check, NOT Google Maps rank, and must be presented as such. The run's cost fields are null unless the role has geogrid:cost. Needs geogrid:read.

runId required

geogrid_competitors

Read: works with any token

Needs the geogrid:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Competitor table for a run: every business seen at the grid points with appearances, average rank among those appearances, best rank, address, rating and Google review count (address and review count are null for runs stored before they were collected), most frequent first. Give runId, or configId for that configuration's latest finished run. includeTarget=true adds the tracked business itself as the first row (isTarget). Relevance-check runs list place ids only (no business names). Needs geogrid:read.

runId optional
configId optional
includeTarget optional

geogrid_settings_get

Read: works with any token

Needs the geogrid:cost permission. Roles with it: owner, admin, manager.

The organization's geo-grid billing settings: monthly budget (USD), markup percent on the data-source price, this month's spend, and the available data sources with their per-task price and its source. Defaults apply until an owner or admin changes them. Needs geogrid:cost (owner, admin, manager; hidden from client roles).

geogrid_settings_update

Write, proposal: needs a Read & write token

Needs the google:manage permission. Roles with it: owner, admin.

Set the organization's monthly geo-grid budget (USD), markup percent and/or defaultSpeed ('standard' or 'fast'; used by scheduled runs and pre-selected on manual runs). Needs google:manage (owner, admin): the same org-level billing-style gate as Google connections, chosen over a new permission to keep the matrix small.

monthlyBudgetUsd optional
markupPercent optional
defaultSpeed optional
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

geogrid_byoKey_get

Read: works with any token

Needs the google:manage permission. Roles with it: owner, admin.

Whether this organization has its own DataForSEO API key (bring your own key) and the masked login. Never returns the password. With a key, geo-grid Maps-rank runs use it, are billed at cost with no markup, and do not count against the monthly resold-spend budget. Needs google:manage (owner, admin).

geogrid_byoKey_set

Write, own approval steps: needs a Read & write token

Needs the google:manage permission. Roles with it: owner, admin.

Store (or replace) the organization's DataForSEO API login and API password (from the API Access page of the DataForSEO dashboard; not the account password). The password is encrypted at rest and never returned or audited. Replacing the key clears the last-verified time; call geogrid.byoKey.verify afterwards. Needs google:manage (owner, admin).

login required
password required
dryRun optional
Preview only: returns a preview and changes nothing.

geogrid_byoKey_delete

Write, proposal: needs a Read & write token

Needs the google:manage permission. Roles with it: owner, admin.

Remove the organization's DataForSEO key. Later runs go back to our key with the markup and the monthly budget. Runs already requested with the customer key fail instead of using ours. Needs google:manage (owner, admin).

dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

geogrid_byoKey_verify

Write, proposal: needs a Read & write token

Needs the google:manage permission. Roles with it: owner, admin.

Check the stored DataForSEO key with the driver's credential check (a free DataForSEO user_data call when the server has a live rank source, otherwise an offline fixture). Returns ok or failed with a message and records the last-verified time on success. Needs google:manage (owner, admin).

dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

geogrid_usage

Read: works with any token

Needs the geogrid:cost permission. Roles with it: owner, admin, manager.

Geo-grid usage and cost per UTC month for runs created from `from` to `to` (inclusive dates, YYYY-MM-DD, at most about 26 months). Per month: runs, points (tasks submitted), tasks (finished, billable), cost_at_dataforseo (tasks x DataForSEO's per-task price), charged (what we charged: BYO runs at cost with no markup, resold runs with the markup), split into byo and resold. BYO runs are not part of the monthly budget. Needs geogrid:cost (owner, admin, manager; hidden from client roles).

from required
to required

performance tools

performance_summary

Read: works with any token

Needs the report:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Business Profile performance for a workspace (workspaceId) or specific locations (locationIds) over from..to (YYYY-MM-DD, inclusive): totals per metric and per KPI (impressions split Maps/Search, calls, website clicks, direction requests), each compared with the equal-length period just before it (delta and deltaPct, null when the earlier period was 0), and a daily series per KPI. Data is what the nightly snapshot captured; days Google omitted count as 0 and hasData is false when nothing was captured. Needs report:read.

workspaceId optional
locationIds optional
from required
to required

performance_keywords

Read: works with any token

Needs the report:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Top Google search keywords (unique users who searched and saw the business) for a workspace or locations over the last `months` complete calendar months (default 3, ending at the previous month, or at endMonth YYYY-MM). Google hides small counts: such a month adds nothing to value and sets isLowerBound, with hiddenBelow the sum of thresholds (the real figure was below it). Needs report:read.

workspaceId optional
locationIds optional
months optional
endMonth optional
limit optional

performance_backfill

Write, proposal: needs a Read & write token

Needs the report:manage permission. Roles with it: owner, admin, manager.

Queue a re-fetch of a location's full Business Profile performance history (the last 18 months Google serves) and its monthly search keywords. Asynchronous: audits the request and queues a worker job in the same transaction. Existing stored days are overwritten with Google's current values; nothing is deleted. The location must be active and linked to Google. Needs report:manage.

locationId required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

performance_byLocation

Read: works with any token

Needs the report:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Per-location calls, website clicks and direction requests for a workspace (workspaceId) or locations (locationIds) over from..to (YYYY-MM-DD, inclusive), each compared with the equal-length period just before, plus `actions` (the three added together), the location's status, needsRelink (Google was disconnected) and lastDataDate (newest stored day). Ordered by title. Needs report:read.

workspaceId optional
locationIds optional
from required
to required

performance_activity

Read: works with any token

Needs the review:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Reviews and posts for a workspace (workspaceId) or locations (locationIds) over from..to (YYYY-MM-DD, inclusive, UTC): newReviews (created in the range), averageRating (of those, one decimal, null when none is rated), unreplied (of those, reviews that still need a reply, by the shared reply-stage rule) and postsPublished (distinct posts published in the range). Counts only, never review text. Needs review:read.

workspaceId optional
locationIds optional
from required
to required

reports tools

reports_definitions_list

Read: works with any token

Needs the report:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

List report definitions the caller can see (optionally one workspace): name, scope (whole workspace or chosen locations), period (last_month, last_30_days, custom), monthly email schedule, recipients and branding. Needs report:read.

workspaceId optional

reports_definitions_create

Write, proposal: needs a Read & write token

Needs the report:manage permission. Roles with it: owner, admin, manager.

Create a report definition for a workspace. scope 'workspace' covers every location in it (locationIds empty); scope 'locations' needs locationIds from that workspace. period: last_month, last_30_days, or custom (customFrom/customTo, YYYY-MM-DD). schedule 'monthly' emails recipients a 30-day link to last month's PDF on the 1st (needs at least one recipient). branding: agencyName and colour (#RRGGBB) shown on the PDF. Reports contain performance numbers and keywords only, never review text. scope 'group' needs groupId (a location group in that workspace; its members are read when each run is generated). language: en (default) or es, for the PDF's labels. comment: optional text for the reader, at most 500 characters, printed last; curly quotes and dashes are normalised and characters the PDF cannot print are refused. kind: performance (default) or reviews. A reviews report holds review counts, ratings, reply rate and time to reply by location, never review text or reviewer names; kind cannot be changed later. Needs report:manage.

workspaceId required
kind optional
name required
scope required
locationIds required
groupId optional
language optional
comment optional
period required
customFrom required
customTo required
schedule required
recipients required
branding required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

reports_definitions_update

Write, proposal: needs a Read & write token

Needs the report:manage permission. Roles with it: owner, admin, manager.

Change a report definition (send only the fields to change). The same rules as create apply to the result. Needs report:manage.

name optional
scope optional
locationIds optional
groupId optional
language optional
comment optional
period optional
customFrom optional
customTo optional
schedule optional
recipients optional
branding optional
id required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

reports_definitions_delete

Write, proposal: needs a Read & write token

Needs the report:manage permission. Roles with it: owner, admin, manager.

Delete a report definition together with its runs and share links (links stop working). Needs report:manage.

id required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

reports_generate

Write, proposal: needs a Read & write token

Needs the report:manage permission. Roles with it: owner, admin, manager.

Generate the PDF for a report definition now. Asynchronous: records a run for the definition's current period, audits it and queues a worker job in the same transaction; poll reports.runs.get until status is 'done', then use reports.download or reports.share. Needs report:manage.

definitionId required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

reports_runs_list

Read: works with any token

Needs the report:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

List report runs (newest first), optionally for one definition. Metadata only (period, status, size); use reports.download for the PDF. requestedByName is the person who generated a manual run (null for scheduled runs). Needs report:read.

definitionId optional
limit optional

reports_runs_get

Read: works with any token

Needs the report:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

One report run's metadata plus its share links (id, expiry, revoked or not; never the token). requestedByName is the person who generated a manual run (null for scheduled runs). Needs report:read.

runId required

reports_download

Read: works with any token

Needs the report:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Download a finished report as a PDF, base64-encoded (filename, contentType, sizeBytes, base64). Refuses PDFs over 1048576 bytes: use reports.share to get a link instead. Needs report:read.

runId required

reports_share

Write, proposal: needs a Read & write token

Needs the report:manage permission. Roles with it: owner, admin, manager.

Create a public share link for a finished report: anyone with the URL can download the PDF without logging in until it expires (expiresInDays 1-30, default 7) or is revoked. The URL is returned ONCE and cannot be recovered; only its hash is stored. Every access is audited. Needs report:manage.

runId required
expiresInDays optional
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

reports_share_revoke

Write, proposal: needs a Read & write token

Needs the report:manage permission. Roles with it: owner, admin, manager.

Revoke a share link by its id (from reports.runs.get); the URL stops working immediately. Needs report:manage.

linkId required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

profile tools

profile_get

Read: works with any token

Needs the location:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Read a location's editable Business Profile live from Google (the mock, today): title, description, categories (primary + additional ids), regularHours, specialHours, serviceItems, serviceArea, websiteUri, openingDate, phoneNumbers, storeCode, storefrontAddress, plus attributes (each `attributes/{id}` with its value type). Values are normalised: unset fields are null; hours periods are sorted. Calls Google, so it runs outside any database transaction. Also returns display: Google's category display names by id, (the store code and address are in profile.fields.storeCode and storefrontAddress). display.regionCode and display.languageCode are the locale to pass to profile.categories.* and profile.attributes.metadata.

locationId required

profile_preview

Read: works with any token

Needs the profile:edit permission. Roles with it: owner, admin, manager.

Dry run of a profile edit across one or more locations of one workspace. Reads each location's current profile live from Google (outside any transaction), diffs it against `fields`, and returns per location { changes, updateMask, attributeMask, guardrail, noChange, current }. Only fields that differ are in the updateMask. `fields` sets whole values: title, description (max 750 characters, no links), categories { primaryCategory { name }, additionalCategories [{ name }] } (Google category ids such as categories/gcid:dentist), regularHours { periods [{ openDay MONDAY..SUNDAY, openTime {hours, minutes}, closeDay, closeTime }] } (24 hours open is 00:00 to 24:00), specialHours { specialHourPeriods [{ startDate {year,month,day}, endDate, openTime, closeTime, closed }] }, serviceItems, serviceArea, websiteUri, openingDate {year,month,day}, phoneNumbers { primaryPhone, additionalPhones }, storeCode (null clears) and storefrontAddress { regionCode, postalCode, administrativeArea, locality, addressLines (max 5) } (the whole address; changing it adds the warning PR.address-reverification, because Google may send the location back to verification), and attributes { 'attributes/has_wifi': { values: [true] } | null (null deletes) }. null clears websiteUri, regularHours, specialHours, serviceArea, openingDate. Guardrails (pack profile + U7) run on the values to be written. Writes nothing. To propose, pass the same `fields` (and `addServiceItems`) and each location's `current` as snapshots to profile.propose. `addServiceItems` appends services to each location's CURRENT list (an item with the same name and category is skipped, everything else is kept as it is); it cannot be combined with `fields.serviceItems`, which replaces the whole list. With addServiceItems, `fields` may be empty. `skipUnofferedServices: true` (used by Copy services) also sets aside, per location, free-form items whose category is not one of the location's, structured items whose service type none of the location's categories offers (or that could not be verified), and everything when the merged list would pass 300 items; each location's `serviceAdd` says which (`send`, `alreadyThere`, `skipped` with a reason, as indexes into addServiceItems). Google documents no category rule or item limit, so this is conservative: flag rather than send. An existing item with the same name and category keeps its own price and description. profile.propose takes the preview's `serviceAdd.send` as `serviceAddSend`. `addCategories` adds categories ([{ name }], Google ids such as categories/gcid:dentist) to each location's CURRENT additional categories: the primary and every category already there are kept, and one already there is skipped. It cannot be combined with `fields.categories`, which replaces both. A location without a primary category errors in the preview. With `addServiceItems` + `skipUnofferedServices`, each location's services are checked against its categories AFTER the edit (the additions, or `fields.categories` when that replaces them).

locationIds required
fields required
addServiceItems optional
addCategories optional
skipUnofferedServices optional

profile_propose

Write, own approval steps: needs a Read & write token

Needs the profile:edit permission. Roles with it: owner, admin, manager.

Record a profile change set: ONE edit (`fields`) for 1-100 locations of one workspace, with the preview snapshot each diff is based on. Pass `snapshots` = the `current` of each location from profile.preview. Per location the diff and minimal updateMask are recomputed here; locations where nothing changes become no_change targets (at least one location must change). Guardrails run on every changing location: any block-severity violation sets status blocked (returned, not an error; propose again with corrected fields); otherwise the change set is pending_approval (warnings do not block). Nothing is sent to Google. The snapshot is the baseline for the conflict check: if Google's value of a changed field differs from it when applying, that location fails with error `conflict` and nothing is written there. Needs profile:edit; approval needs review:approve. `addServiceItems` appends services to each location's CURRENT list (an item with the same name and category is skipped, everything else is kept as it is); it cannot be combined with `fields.serviceItems`, which replaces the whole list. With addServiceItems, `fields` may be empty. `skipUnofferedServices: true` (used by Copy services) also sets aside, per location, free-form items whose category is not one of the location's, structured items whose service type none of the location's categories offers (or that could not be verified), and everything when the merged list would pass 300 items; each location's `serviceAdd` says which (`send`, `alreadyThere`, `skipped` with a reason, as indexes into addServiceItems). Google documents no category rule or item limit, so this is conservative: flag rather than send. An existing item with the same name and category keeps its own price and description. profile.propose takes the preview's `serviceAdd.send` as `serviceAddSend`. `addCategories` adds categories ([{ name }], Google ids such as categories/gcid:dentist) to each location's CURRENT additional categories: the primary and every category already there are kept, and one already there is skipped. It cannot be combined with `fields.categories`, which replaces both. A location without a primary category errors in the preview. With `addServiceItems` + `skipUnofferedServices`, each location's services are checked against its categories AFTER the edit (the additions, or `fields.categories` when that replaces them).

workspaceId required
locationIds required
fields required
addServiceItems optional
addCategories optional
skipUnofferedServices optional
serviceAddSend optional
snapshots required
dryRun optional
Preview only: returns a preview and changes nothing.

profile_approve

Write, own approval steps: needs a Read & write token

Needs the review:approve permission. Roles with it: owner, admin, manager, client_approver.

Approve a change set that is pending approval (pending_approval -> approved). Approving does not send anything to Google: call profile.apply. Client approvers can approve change sets in their own workspaces only.

id required
dryRun optional
Preview only: returns a preview and changes nothing.

profile_reject

Write, own approval steps: needs a Read & write token

Needs the review:approve permission. Roles with it: owner, admin, manager, client_approver.

Reject a change set that is pending approval, with a reason (pending_approval -> cancelled). The proposer edits the values and proposes again.

id required
reason required
dryRun optional
Preview only: returns a preview and changes nothing.

profile_apply

Write, own approval steps: needs a Read & write token

Needs the profile:edit permission. Roles with it: owner, admin, manager.

Apply an approved change set: approved -> queued and one worker job per changing location (no_change locations are skipped). Asynchronous: nothing is sent to Google inside this call. Each job re-reads the location from Google; if a changed field no longer has the value the preview saw, that location fails with error `conflict` and nothing is written there (someone edited it on Google). Otherwise guardrails run again and the edit is written with a minimal updateMask through the per-location queue (Google allows 10 edits per minute per location; an 11th waits). The change set ends applied (all changing locations applied), partially_applied or failed. Poll profile.changeSets.get for per-location results.

id required
dryRun optional
Preview only: returns a preview and changes nothing.

profile_cancel

Write, own approval steps: needs a Read & write token

Needs the profile:edit permission. Roles with it: owner, admin, manager.

Cancel a change set that has not been applied: draft, blocked, pending_approval or approved. Once applying has started (queued) it cannot be cancelled: CONFLICT.

id required
dryRun optional
Preview only: returns a preview and changes nothing.

profile_changeSets_list

Read: works with any token

Needs the location:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Profile change sets the caller can see, newest first. Filters: workspaceId, status, locationId (change sets that target it). limit 1-100 (default 50). Use status pending_approval for the approval queue. Each change set names its drafter (createdByName; createdSurface mcp means an agent drafted it for that person) and approver (approvedByName).

workspaceId optional
status optional
locationId optional
limit optional

profile_changeSets_get

Read: works with any token

Needs the location:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

One profile change set: desired values, status, guardrail result, what the caller may do next (can.*) and the per-location results (status, error reason code, the field changes and masks). Each change set names its drafter (createdByName; createdSurface mcp means an agent drafted it for that person) and approver (approvedByName).

id required

profile_categories_get

Read: works with any token

Needs the location:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Google's details for up to 10 category ids (categories/gcid:...): displayName and serviceTypes (the structured services a location in that category can list; write them as serviceItems[].structuredServiceItem.serviceTypeId). Unknown ids are left out. Cached for a day per id.

locationId required
regionCode required
languageCode required
names required

profile_attributes_metadata

Read: works with any token

Needs the location:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

The attributes Google offers for a primary category in a region and language: name (attributes/{id}, the key for profile.preview attributes), displayName, groupDisplayName, valueType (BOOL, ENUM, URL, REPEATED_ENUM), repeatable, and for enums the allowed values with display names. Deprecated attributes are left out. Social profile links, where Google offers them, are URL attributes such as attributes/url_facebook. Cached for a day per category.

locationId required
regionCode required
languageCode required
categoryName required

profile_changes_list

Read: works with any token

Needs the location:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Profile changes found by the change watch, newest first: nightly snapshot diffs (someone edited the profile outside OpenGMB) and Google-suggested edits (GOOGLE_UPDATE push; googleSuggested true, `before` is the merchant value, `after` what Google shows). Without locationId it covers every location in the caller's scope (the org-wide alerts inbox). Filters: workspaceId, locationId, groupId, status (open, accepted, reverted, dismissed), googleSuggested, fields (profile field names such as regularHours or websiteUri; a change matches when it touches any of them). total counts every match, past the limit. Each change has fieldPaths, before/after values of those fields, status and can.{accept,revert,dismiss}. limit 1-200 (default 100). Each change also names who resolved it (resolvedByName) and, for a revert, where its change set was drafted (revertChangeSetSurface: ui, or mcp for an agent).

workspaceId optional
locationId optional
groupId optional
status optional
googleSuggested optional
fields optional
limit optional

profile_changes_accept

Write, own approval steps: needs a Read & write token

Needs the profile:edit permission. Roles with it: owner, admin, manager.

Accept an open profile change: record that the new value is fine (open -> accepted). Nothing is written to Google. For a Google-suggested change this means keeping Google's value; note that Google keeps showing its own value as a difference from the merchant's profile until the profile is patched, which this build does not do on accept.

id required
dryRun optional
Preview only: returns a preview and changes nothing.

profile_changes_revert

Write, own approval steps: needs a Read & write token

Needs the profile:edit permission. Roles with it: owner, admin, manager.

Revert a profile change found by the nightly snapshot: creates a profile change set that restores the previous values of the changed fields (profile.changeSets.get shows it) and marks the change reverted. Nothing is written to Google here: the change set waits for approval (review:approve) and is applied by profile.apply with the usual conflict check, so if the field changed again on Google since the change was detected, that location fails with `conflict` and nothing is written. Not available for Google-suggested changes (the merchant value already equals the restored value): accept or dismiss those. A reverted change whose change set was cancelled, blocked or failed can be reverted again.

id required
dryRun optional
Preview only: returns a preview and changes nothing.

profile_changes_dismiss

Write, own approval steps: needs a Read & write token

Needs the profile:edit permission. Roles with it: owner, admin, manager.

Dismiss an open profile change without acting on it (open -> dismissed). Nothing is written to Google.

id required
dryRun optional
Preview only: returns a preview and changes nothing.

invitations tools

invitations_create

Write, proposal: needs a Read & write token

Needs the member:invite permission. Roles with it: owner, admin, manager.

Invite someone by email (owner, admin, manager). role is client_approver or client_viewer (needs workspaceId: they see and act on that workspace only) or manager (organization-wide, owner and admin only; no workspaceId). The invitee gets an email with a link to /invite/<token>; the link is a deep link only: they must still sign up or sign in and complete TOTP before the invitation is applied, and their account email must match. The invitation lasts 7 days. The link (inviteUrl) is returned ONLY when no email provider is configured (RESEND_API_KEY and EMAIL_FROM), so a developer can test; otherwise inviteUrl is null and the token exists nowhere but the email. An account holds one client role: inviting someone who already has a different client role, another organization, or a pending invite is CONFLICT.

email required
role required
workspaceId optional
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

invitations_list

Read: works with any token

Needs the member:invite permission. Roles with it: owner, admin, manager.

Invitations of the caller's organization, newest first (owner, admin, manager). Optional status filter: pending, accepted, revoked, expired. limit 1-200 (default 100). The token is never returned.

status optional
limit optional

invitations_revoke

Write, proposal: needs a Read & write token

Needs the member:invite permission. Roles with it: owner, admin, manager.

Revoke a pending invitation (owner, admin, manager; a manager cannot revoke a manager invitation). The link stops working at once. An invitation that was accepted, already revoked or expired is CONFLICT.

id required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

integrations tools

integrations_clear

Write, proposal: needs a Read & write token

Needs the member:invite permission. Roles with it: owner, admin, manager.

Platform administrators only. Remove the in-app value of one integration key. A value set by the server environment is unaffected. The audit row names the key only.

key required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

integrations_list

Read: works with any token

Needs the member:invite permission. Roles with it: owner, admin, manager.

Platform administrators only (everyone else gets FORBIDDEN). Each optional integration key (Google Maps browser key, Resend email, Pub/Sub push, browser push VAPID, Anthropic) with where its value comes from: env (set by the server environment, read-only here), app (entered in the app), unreadable (stored value cannot be decrypted, enter it again) or missing. Shows at most the last four characters of an in-app value; never the value.

integrations_set

Write, own approval steps: needs a Read & write token

Needs the member:invite permission. Roles with it: owner, admin, manager.

Platform administrators only. Store (or replace) one optional integration key, encrypted at rest. Refused with CONFLICT while the server environment sets that key (the environment wins). The value is never returned or audited; the audit row names the key only. Boot secrets such as ENCRYPTION_KEY are not accepted.

key required
value required
dryRun optional
Preview only: returns a preview and changes nothing.

integrations_testDataForSeo

Read: works with any token

Needs the member:invite permission. Roles with it: owner, admin, manager.

Platform administrators only. Checks the DataForSEO login and password the server has (environment or entered in the app) with a free user_data call and returns the account balance in USD. Never returns the credentials. Returns ok false with a message when the keys are missing or refused.

domains tools

domains_get

Read: works with any token

Needs the workspace:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

The caller's organization's custom address: host (null when none), senderEmail, senderVerified (the sender is used for client emails only once a platform administrator marked it verified in Resend) and dnsTarget, the hostname a CNAME record must point to. Any member can read it; it never returns another organization's row.

domains_list

Read: works with any token

Needs the member:invite permission. Roles with it: owner, admin, manager.

Every organization with its custom address and organization name (platform administrators only: accounts on PLATFORM_ADMIN_EMAILS with a verified email; everyone else gets FORBIDDEN). An organization without an address has host null, so an address can be set for it with domains.set.

domains_set

Write, proposal: needs a Read & write token

Needs the member:invite permission. Roles with it: owner, admin, manager.

Set or remove an organization's custom address (platform administrators only; everyone else gets FORBIDDEN). host is a bare hostname such as portal.agency.com (no scheme, path, port or wildcard), or null to remove the row. A host already used by another organization, or the main host, is refused (CONFLICT / INVALID_INPUT). senderEmail is the agency's own From address; senderVerified true means Resend shows its domain as Verified, and only then is it used (it needs a senderEmail). The change is audited. The hostname also has to be added to the web app's domain list in Coolify before it serves traffic.

orgId required
host required
senderEmail optional
senderVerified optional
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

orgInvites tools

orgInvites_create

Write, proposal: needs a Read & write token

Needs the member:invite permission. Roles with it: owner, admin, manager.

Invite someone to start a NEW organization (platform administrators only: accounts on PLATFORM_ADMIN_EMAILS with a verified email; everyone else gets FORBIDDEN). The invitee gets an email link to /invite/<token>; signing up (also while sign-up is invite only) or signing in from it creates the organization with them as its owner. Their account email must match, they must have no organization yet, and the link lasts 7 days and works once. organizationName is optional (default: the invitee's name). The link (inviteUrl) is returned ONLY when no email provider is configured; otherwise inviteUrl is null. A pending organization invite for the same email, or an account that already belongs to an organization, is CONFLICT.

email required
organizationName optional
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

orgInvites_list

Read: works with any token

Needs the member:invite permission. Roles with it: owner, admin, manager.

Organization invites, newest first (platform administrators only; everyone else gets FORBIDDEN). They belong to no organization, so every platform administrator sees all of them. Optional status filter: pending, accepted, revoked, expired. limit 1-200 (default 100). The token is never returned.

status optional
limit optional

orgInvites_revoke

Write, proposal: needs a Read & write token

Needs the member:invite permission. Roles with it: owner, admin, manager.

Revoke a pending organization invite (platform administrators only). The link stops working at once. An invite that was accepted, already revoked or expired is CONFLICT; a team invitation id is NOT_FOUND here.

id required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

members tools

members_list

Read: works with any token

Needs the member:invite permission. Roles with it: owner, admin, manager.

Members of the caller's organization with their role (owner, admin, manager). Organization-wide members have workspaceId null; client members belong to one workspace. Pass workspaceId to get that workspace's clients plus the organization-wide members.

workspaceId optional

members_remove

Write, proposal: needs a Read & write token

Needs the member:invite permission. Roles with it: owner, admin, manager.

Remove a membership (owner, admin, manager). An owner can remove anyone; an admin anyone but an owner; a manager only client members. The last owner of an organization cannot be removed (CONFLICT). The person's account stays; they lose access to this organization at once: their sessions end and their API tokens for it are revoked.

membershipId required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

members_resetTwoFactor

Write, proposal: needs a Read & write token

Needs the member:reset_two_factor permission. Roles with it: owner.

Reset a member's two-factor authentication (owner only; never your own; not available to API tokens). Deletes their authenticator secret and backup codes and signs them out everywhere. Until they set up a new authenticator app at their next sign-in, their password (or Google) alone signs them in, and they cannot use OpenGMB until they do. CONFLICT when the member has not set up two-factor or also belongs to another organization.

membershipId required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

portal tools

portal_overview

Read: works with any token

Needs the review:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

The client portal's data in one call, for any role that can read reviews: pending (review replies AND posts waiting for approval, oldest submission first, across the caller's workspaces or one workspaceId) and recentlyPublished (replies and post sends published most recently, newest first). Each pending item carries can.approve / can.reject from the caller's role, so a client_viewer sees the queue read-only; act with reviewReplies.approve / reviewReplies.reject / posts.approve / posts.reject. Only active locations are included. Published replies carry autoApprovedMinStars (the star rule that approved them; null when a person approved).

workspaceId optional
recentLimit optional

portal_results

Read: works with any token

Needs the report:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

The client portal's results in one call, over the caller's active locations (or one workspaceId): calls and direction requests from the nightly performance snapshot, and new reviews with their average star rating, for the 30 complete days ending yesterday (UTC) compared with the 30 days before (deltaPct is null when the earlier period was 0; hasData is false when no snapshot exists for the range); plus ratingTrend, the average star rating per calendar month for the last 6 months including the current one (average null when the month has no rated review). Needs report:read.

workspaceId optional

approvals tools

approvals_queue

Read: works with any token

Needs the review:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Everything waiting for a person to approve, across the caller's workspaces or one workspaceId, oldest submission first: review replies, posts, profile change sets and edits of published posts with status pending_approval. Each item has a one-line title, the text, where it is for, who drafted it (provenance.createdSurface is mcp for an agent draft), a guardrail summary and can.approve / can.reject from the caller's role; act with reviewReplies.approve / reject, posts.approve / reject, profile.approve / reject, posts.approveEdit / rejectEdit (a postedit item's id is the edit id; the post stays published while its edit waits). An edit is included only while a live Google post it would patch is at an active location. counts are the totals before limit; truncated is true when limit cut the list. Replies at inactive locations are not included. A change set is included only while at least one location it changes is active, and only active locations are named.

workspaceId optional
locationIds optional
groupId optional
limit optional

approvals_counts

Read: works with any token

Needs the review:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

How many items wait for approval (replies, posts, profile change sets, post edits), across the caller's workspaces or one workspaceId. Count queries only: cheap enough to call on every page, unlike approvals.queue. Same scope and the same numbers as approvals.queue counts.

workspaceId optional
locationIds optional
groupId optional

attention tools

attention_counts

Read: works with any token

Needs the review:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

How many things need a person, across the caller's workspaces or one workspaceId, in disjoint buckets: approvals (replies, posts, profile change sets pending approval; the same numbers as approvals.counts), reviews to answer (negative = rated 1 to negativeMaxStars, other = higher or unrated; the workspace reply policy applies, and a review whose reply is already pending approval, approved or failed is not counted; the rule is the shared reply stage), waitingToPublish (reviews whose approved reply is not yet on Google; reported apart, not in total), open profile changes, the caller's own pending agent proposals (not narrowed by workspaceId), and failed publishes (replies, posts, change sets failed or partially applied). total is the sum. Count queries only: cheap enough for every page.

workspaceId optional

attention_queue

Read: works with any token

Needs the review:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Everything that needs a person, as one list sorted by urgency (failed publishes, negative reviews, approvals, your agent proposals, open profile changes, other reviews to answer; newest first within each), across the caller's workspaces or one workspaceId. Same buckets and counts as attention.counts; truncated is true when limit cut the list. Also returns what the Home page needs: activeLocations in the requested scope (Home shows its owner layout up to 3, the agency layout above), org-wide setup facts, locations that lost their Google connection (relink), per-client rows with an attention count and a 6-month rating trend, cards for up to 3 active locations with reviews, open changes, last post and 30-day calls and directions, the workspaces with an auto-approve rule, and when reviews last synced (UTC). Act on items with the action named by subject (reviewReplies.*, posts.*, profile.*, profile.changes.*, mcp.proposals.*).

workspaceId optional
limit optional

onboarding tools

onboarding_get

Read: works with any token

Needs the location:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Whether the first-run checklist facts stored on the organization are set: healthReportSeen (someone opened a location's health report) and dismissed (an owner or admin hid the checklist).

onboarding_update

Write, own approval steps: needs a Read & write token

Needs the location:manage permission. Roles with it: owner, admin, manager.

Keep the first-run checklist on Home honest. healthReportSeen true records that someone opened a location's health report (it stays on). dismissed true hides the checklist for the whole organization, false brings it back; dismissing needs google:manage (owner, admin). Pass only the fields to change. Writes nothing to Google.

healthReportSeen optional
dismissed optional
dryRun optional
Preview only: returns a preview and changes nothing.

branding tools

branding_get

Read: works with any token

Needs the workspace:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

The caller's organization branding: agencyName (falls back to the organization name), logoUrl (https), primaryColor and accentColor (#rrggbb). Any member can read it; the app, the client portal and emails use it.

branding_update

Write, proposal: needs a Read & write token

Needs the branding:manage permission. Roles with it: owner, admin.

Set the organization's branding (owner, admin). Every field is optional and null clears it: agencyName (1-100 chars), logoUrl (https URL only; a logo file uploaded in the web app wins over it in the app and portal, see branding.logos), primaryColor and accentColor (#rrggbb). Fields you leave out are unchanged.

agencyName optional
logoUrl optional
primaryColor optional
accentColor optional
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

branding_logos

Read: works with any token

Needs the workspace:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

The uploaded logo files the caller may see: orgLogoFileId (the agency logo, or null) and workspaceLogos (one per client in the caller's scope that has one). A file is shown at /api/files/<fileId>. An uploaded logo wins over the logoUrl link. Logos are uploaded in the web app (Settings, Branding); agents cannot upload.

storage tools

storage_usage

Read: works with any token

Needs the branding:manage permission. Roles with it: owner, admin.

How much of the organization's file storage is used (owner, admin): usedBytes, limitBytes (the per-organization allowance, 50 MB unless the server sets STORAGE_QUOTA_MB) and a breakdown by store: storedFiles (logos), postImages (the post image library), mediaUploads (photo uploads not yet sent to Google) and reportPdfs. An upload that would pass the limit is refused.

media tools

media_list

Read: works with any token

Needs the location:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

List a location's photos live from Google (the mock, today) with their category (COVER, PROFILE = the logo, EXTERIOR, INTERIOR, PRODUCT, AT_WORK, FOOD_AND_DRINK, MENU, COMMON_AREA, ROOMS, TEAMS, ADDITIONAL), plus the most recent photo operations queued from here (media.add / media.delete are asynchronous: status pending, applied or failed with a reason code). Calls Google, so it runs outside any database transaction. Photo requirements: JPG or PNG, 10 KB to 5 MB, at least 250px on the short edge, 720px recommended (https://support.google.com/business/answer/6103862).

locationId required

media_add

Write, proposal: needs a Read & write token

Needs the profile:edit permission. Roles with it: owner, admin, manager.

Add a photo to a location from a public https image URL (JPG or PNG; to send the file itself use media.upload) in a category: COVER (the cover photo, one per location), PROFILE (the logo, one per location; LOGO is a deprecated alias and is not accepted), EXTERIOR, INTERIOR, PRODUCT, AT_WORK, FOOD_AND_DRINK, MENU, COMMON_AREA, ROOMS, TEAMS or ADDITIONAL. Setting the cover or logo is simply adding with category COVER or PROFILE; Google replaces the previous one. Asynchronous: records the operation and queues a worker job (returns status pending); nothing is sent to Google inside this call and the URL is never fetched by OpenGMB. Poll media.list for the outcome. Needs profile:edit.

locationId required
sourceUrl required
category required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

media_upload

Write, proposal: needs a Read & write token

Needs the profile:edit permission. Roles with it: owner, admin, manager.

Upload a photo FILE to a location (base64 content, JPG or PNG, at most 5 MB, so at most 7000000 base64 characters) in a category: COVER, PROFILE (the logo), EXTERIOR, INTERIOR, PRODUCT, AT_WORK, FOOD_AND_DRINK, MENU, COMMON_AREA, ROOMS, TEAMS or ADDITIONAL. The format is detected from the bytes (GIF, HEIC and WebP are rejected) and the size and pixels are checked against Google's rules (10 KB to 5 MB and 250px on the short edge, except COVER and PROFILE). Asynchronous like media.add: records the operation and queues a worker job (status pending); the bytes are kept only until Google accepts them, then deleted. Poll media.list. Needs profile:edit. Over MCP this is a two-phase write: the proposal preview shows file facts only, never the image.

locationId required
category required
filename required
contentBase64 required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

media_uploadMany

Write, proposal: needs a Read & write token

Needs the profile:edit permission. Roles with it: owner, admin, manager.

Upload ONE photo FILE (base64, same rules as media.upload) to several locations at once, now or at a later time. Each location gets its own operation (its own result): a location you cannot edit, or that is not linked to Google, is reported in its own result (error code) and does not stop the others. scheduledFor (optional, ISO datetime with offset = an instant, not in the past, at most 90 days ahead; the web app converts the location's local wall time) holds the photo until then: its operations have status scheduled, and a worker sweeps every minute and sends the due ones (so a send can be up to about a minute late). Without scheduledFor the operations are queued at once (status pending). The photo is kept only until Google accepts it. Poll media.batch with the returned batchId for per-location results. Needs profile:edit on each location. Over MCP this is a two-phase write.

locationIds required
category required
filename required
contentBase64 required
scheduledFor optional
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

media_batch

Read: works with any token

Needs the location:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Per-location results of one photo sent to several locations (the batchId media.uploadMany returned) of one workspace (client): for each location its operation status (scheduled, pending, applied or failed with a reason code such as google_http_<n>), the scheduled time and the Google media name once applied. Only locations you can read are listed.

workspaceId required
batchId required

media_cancelScheduled

Write, proposal: needs a Read & write token

Needs the profile:edit permission. Roles with it: owner, admin, manager.

Cancel a photo that is still waiting for its scheduled time (the operation id from media.list or media.batch, status scheduled) in one workspace (client). Moves the operation to the terminal status cancelled and deletes the staged photo bytes. Only works while the status is scheduled: if the minute sweep already took it, nothing changes and cancelled is false (already sent or being sent). Needs profile:edit.

workspaceId required
opId required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

media_delete

Write, proposal: needs a Read & write token

Needs the profile:edit permission. Roles with it: owner, admin, manager.

Delete a photo from a location (`mediaName` as returned by media.list, accounts/{a}/locations/{l}/media/{id}). Asynchronous: records the operation and queues a worker job (status pending); a photo Google no longer has counts as deleted. Poll media.list. Needs profile:edit.

locationId required
mediaName required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

media_customer_list

Read: works with any token

Needs the location:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

List photos contributed by customers at a location, live from Google (outside any transaction). Each item carries the contributor attribution, which Google requires to be shown unaltered, and the takedown URL to report an inappropriate photo. The nightly job notifies (media.customer_photo) once per new photo.

locationId required

verification tools

verification_state

Read: works with any token

Needs the location:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

A location's verification state live from Google (outside any transaction): Voice of Merchant (hasVoiceOfMerchant = in good standing and in control of the listing; hasBusinessAuthority = ownership), which action Google wants next (standing: good_standing, wait_for_review, verify, comply_with_guidelines = fix guideline problems, resolve_ownership_conflict = duplicate of a location in good standing, unknown) with the recommendation reason, and the location's verification attempts (method, PENDING / COMPLETED / FAILED). Read only: OpenGMB starts no verification and submits no appeal; those are manual.

locationId required

suspension tools

suspension_cases_list

Read: works with any token

Needs the location:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Suspension / reinstatement cases the caller can see, newest first, with the evidence checklist (business registration, licence, tax certificate, utility bill, storefront / signage / interior photos, video walkthrough, website match ...), dates (opened, appeal submitted, outcome) and status (open, appealed, reinstated, closed_lost). Filters: locationId, workspaceId, status. This is a record-keeping tool for a manual process: nothing is sent to Google.

locationId optional
workspaceId optional
status optional

suspension_cases_create

Write, proposal: needs a Read & write token

Needs the profile:edit permission. Roles with it: owner, admin, manager.

Open a suspension case for a location: the reason (what Google said or what you see), when it started (openedAt, default now) and a fresh evidence checklist. Records only; nothing is sent to Google. Needs profile:edit.

locationId required
reason required
openedAt optional
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

suspension_cases_update

Write, proposal: needs a Read & write token

Needs the profile:edit permission. Roles with it: owner, admin, manager.

Update a suspension case. checklist: [{ key, done?, note? }] toggles items and sets notes (keys as in suspension.cases.list; unknown keys are rejected). status: open -> appealed (sets appealSubmittedAt, default now) -> reinstated or closed_lost (sets outcomeAt, default now); open may also go straight to reinstated or closed_lost. Google allows one appeal, so there is no second appeal. appealSubmittedAt can be corrected while appealed; outcomeAt and outcomeNotes can be set with the outcome and outcomeNotes edited after it; a finished case is otherwise read only. reason can be reworded while the case is open or appealed. Records only; nothing is sent to Google. Needs profile:edit.

id required
status optional
reason optional
appealSubmittedAt optional
outcomeAt optional
outcomeNotes optional
checklist optional
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

placeActions tools

placeActions_list

Read: works with any token

Needs the location:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

List a location's place action links (booking / ordering buttons on the listing) live from Google (outside any transaction), plus the most recent link operations queued from here (status pending, applied, failed with a reason code). Types: APPOINTMENT, ONLINE_APPOINTMENT, DINING_RESERVATION, FOOD_ORDERING, FOOD_DELIVERY, FOOD_TAKEOUT, SHOP_ONLINE. Only one link per (uri, type) and one preferred link per type exist at a location. Links with isEditable false (managed by an aggregator) cannot be changed.

locationId required

placeActions_create

Write, proposal: needs a Read & write token

Needs the profile:edit permission. Roles with it: owner, admin, manager.

Add a place action link (a booking or ordering URL) to a location. placeActionType: APPOINTMENT, ONLINE_APPOINTMENT, DINING_RESERVATION, FOOD_ORDERING, FOOD_DELIVERY, FOOD_TAKEOUT, SHOP_ONLINE. uri must be https. isPreferred marks it the preferred link for its type (any previous preferred link of that type loses it). Asynchronous: records the operation and queues a worker job (status pending); nothing is sent to Google inside this call. A link with the same uri and type that already exists fails with google_http_409. Needs profile:edit.

locationId required
placeActionType required
uri required
isPreferred optional
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

placeActions_update

Write, proposal: needs a Read & write token

Needs the profile:edit permission. Roles with it: owner, admin, manager.

Change a place action link (`name` as returned by placeActions.list): any of uri (https), placeActionType, isPreferred; only the fields you pass are written (Google's updateMask is exactly those). Links with isEditable false fail at Google. Asynchronous: records the operation and queues a worker job (status pending). Needs profile:edit.

locationId required
name required
uri optional
placeActionType optional
isPreferred optional
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

placeActions_delete

Write, proposal: needs a Read & write token

Needs the profile:edit permission. Roles with it: owner, admin, manager.

Delete a place action link (`name` as returned by placeActions.list). Asynchronous: records the operation and queues a worker job (status pending); a link Google no longer has counts as deleted. Needs profile:edit.

locationId required
name required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

foodMenus tools

foodMenus_get

Read: works with any token

Needs the location:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Read a location's food menus live from Google (v4 getFoodMenus), outside any transaction, plus the most recent food menu saves queued from here (status pending, applied, failed with a reason code). menus is the list Google returns: each menu has labels, sections (labels, items) and cuisines; each item has labels, attributes (price, spiciness, allergen, dietaryRestriction, ...) and optional options. Only restaurants and similar locations have a food menu; supported is false (menus empty) when Google says the location cannot have a food menu, such as a clinic; call this only when a menu is wanted, since it spends a Google call.

locationId required

foodMenus_update

Write, proposal: needs a Read & write token

Needs the profile:edit permission. Roles with it: owner, admin, manager.

Replace a location's whole food menu. Pass the complete list, starting from foodMenus.get: anything left out is removed at Google, and fields this tool does not edit (nutritionFacts, ingredients, cuisines ...) must be passed back unchanged. Each menu needs labels (displayName up to 140 characters, description up to 1000) and at least one section; each section labels and at least one item; each item labels and attributes.price {currencyCode, units, nanos}. Asynchronous: records the operation and queues a worker job (status pending); nothing is sent to Google inside this call, and nothing at all while Google writes are off. Needs profile:edit.

locationId required
menus required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

locationManagers tools

locationManagers_list

Read: works with any token

Needs the location:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Who manages a location on Google, read live (Account Management API locations.admins.list, outside any transaction). Each manager has a display name (an invited person who has not accepted yet shows the invited email), a role (PRIMARY_OWNER, OWNER, MANAGER, SITE_MANAGER; anything else is returned as OTHER) and pendingInvitation. Read only: OpenGMB does not invite, change or remove managers. Spends a Google call, so call it only when the list is wanted. Whether Google includes managers inherited from the account is not documented.

locationId required

mcp tools

mcp_proposals_list

Read: works with any token

Needs the api_token:manage_own permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

List your own write proposals, newest first, with status (pending, applied, expired, cancelled, failed), expiry, the preview that was shown and the name of the token that made each. Over MCP: this token's proposals. In the web app: every token of the signed-in person. status filters before limit; expired includes pending proposals past their expiry. A failed proposal's error reads CODE: message.

status optional
limit optional

mcp_proposals_apply

Write, own approval steps: needs a Read & write token

Needs the api_token:manage_own permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Apply a proposal returned by a write tool (phase 2 of propose -> check -> approve -> publish). Single use: it re-checks that the proposal is still pending and unexpired, was created by this API token and user (or, in the web app, that the signed-in person owns the token that created it; then the token must not be revoked and its read-only or client limits still apply), that its stored input is intact, that you are still authorized, and that the policy findings still do not block it; then it runs the write exactly as if you had called the tool, audit rows included. A second apply is CONFLICT. Returns the write's own result.

proposalId required
dryRun optional
Preview only: returns a preview and changes nothing.

mcp_proposals_cancel

Write, own approval steps: needs a Read & write token

Needs the api_token:manage_own permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Cancel a pending proposal so it can no longer be applied. Only the API token that created it, or its owner signed in to the web app, can cancel it.

proposalId required
dryRun optional
Preview only: returns a preview and changes nothing.

system tools

system_status

Read: works with any token

Needs the location:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Scheduled background jobs on this server (schedule in UTC, last run, result ok/failed/running/never, next run, late when two scheduled runs in a row were missed; error text for owners and admins only) and, for the locations you can see (sorted by name, up to 500), when reviews were last synced, the newest sync attempt and its reason code, the last performance snapshot date and when a profile change was last found. Never calls Google.

monitoring tools

monitoring_overview

Read: works with any token

Needs the member:invite permission. Roles with it: owner, admin, manager.

System health for the whole server (platform administrators only; everyone else gets FORBIDDEN): the worker's last heartbeat and whether it is stale, how alerts are delivered (email to ALERT_EMAIL, or only written to the log), the most recent distinct server errors with how often each was seen (messages are stripped of secrets and personal data), and Google Business API calls per day and method against the 300 requests per minute limit. Read-only, never calls Google.

search_everything

Read: works with any token

Needs the review:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Search locations (name, title, address), review text (and the reviewer's name unless anonymous) and post text in one call, for the ⌘K box. q is matched literally, case-insensitively. Reviews and posts are only searched from 3 characters (locations from 1), so a short q returns locations only. Returns at most limitPerKind (1-10, default 5) of each kind, newest first for reviews and posts. Scope with workspaceId, groupId or locationIds, the same as reviews.list; client roles only see their own workspaces. Reviews are active locations only. Internal notes and assignments are never searched or returned.

q required
workspaceId optional
groupId optional
locationIds optional
limitPerKind optional

ai tools

ai_draftText

Write, own approval steps: needs a Read & write token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Draft text with AI for a client. purpose 'reply' (a reply to a review: sourceText is the review text; optional rating and reviewerName) or 'post' (a Google post: sourceText is the topic). The draft uses the client's brand voice (tone, banned words, sign-off, language), is metered (tokens, model, cost), and then runs through the same guardrails as replies and posts for the client's profile. status 'ok' returns the draft (warningRuleIds lists non-blocking findings); status 'blocked' returns blockedRuleIds and NO text. The call is refused before it is made when it would exceed the platform's or the client's monthly AI limit, and fails with NOT_CONFIGURED when this server has no AI key. A draft is only a proposal: it still goes through approval. Needs review:draft (owner, admin, manager).

workspaceId required
purpose required
sourceText required
rating optional
reviewerName optional
locationId optional
language optional
dryRun optional
Preview only: returns a preview and changes nothing.

ai_draftReply

Write, own approval steps: needs a Read & write token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Draft a reply to one review with AI. Reads the review itself (text, star rating, reviewer first name only, location, the client's brand voice and a few of its reply templates as style examples) and writes in the review's language unless the client's brand voice sets one (language is a hint you may pass). A 1-2 star review gets an apology and an offer to take it offline, with no admission of fault. The draft is metered, em dashes are replaced, and it runs through the same guardrails as a typed reply for this location (including the duplicate check against its recent replies). status 'ok' returns the draft text (warningRuleIds lists non-blocking findings, for example wording the writing style bans); status 'blocked' returns blockedRuleIds and NO text. Refused with AI_BUDGET_EXCEEDED over the monthly cap, NOT_CONFIGURED when this server has no AI key. Nothing is saved: put the text in reviewReplies.createDraft, then reviewReplies.submit. Needs review:draft (owner, admin, manager).

reviewId required
language optional
dryRun optional
Preview only: returns a preview and changes nothing.

ai_draftReplies

Write, own approval steps: needs a Read & write token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Draft replies with AI for up to 20 reviews and put each into the approval queue. One AI call per review, one after another. For each review: drafted (saved and submitted; replyStatus pending_approval, or approved if the client's star rule approves it), blocked (a guardrail blocked the draft; blockedRuleIds; nothing saved), refused (over the monthly cap: the run stops there and the rest are not_attempted), skipped (the review already has a reply or a draft, or is not found or not allowed), failed (the AI call failed). Warnings (for example banned wording) do not stop a draft: they are stored on it and a person sees them in approval. If the client's star rule would auto-approve the draft, a draft with warnings stays a draft instead (replyStatus draft) until a person reads it. Each draft goes through the same metering, guardrails and audit as ai.draftReply. NOT_CONFIGURED when this server has no AI key. Needs review:draft (owner, admin, manager).

reviewIds required
dryRun optional
Preview only: returns a preview and changes nothing.

ai_draftBusinessDescription

Write, own approval steps: needs a Read & write token

Needs the profile:edit permission. Roles with it: owner, admin, manager.

Draft the business description for a location with AI. At most 750 characters (a longer answer is retried once, then cut at a sentence end), plain text, no links, in the client's brand voice and the writing style. The location's top Google search keywords from the stored Performance data are offered to the model as context; keywordsIncluded says which of them the draft happens to use (a hint, never forced). Optional facts the caller already has: categories, services and currentDescription (to improve it). status 'ok' returns the draft; status 'blocked' returns blockedRuleIds and NO text. The draft is only returned: nothing is saved, so it still goes through profile.preview, profile.propose and approval. Metered and capped like ai.draftText; the text sent to the model is never logged. Needs profile:edit and review:draft (owner, admin, manager).

locationId required
categories optional
services optional
currentDescription optional
dryRun optional
Preview only: returns a preview and changes nothing.

ai_draftServiceDescription

Write, own approval steps: needs a Read & write token

Needs the profile:edit permission. Roles with it: owner, admin, manager.

Draft the description of one service for a location with AI. At most 1000 characters (a longer answer is retried once, then cut at a sentence end), plain text, no links, in the client's brand voice and the writing style. serviceName is required; categoryName and currentDescription are optional context. status 'ok' returns the draft; status 'blocked' returns blockedRuleIds and NO text. The draft is only returned: nothing is saved, so it still goes through profile.preview, profile.propose and approval. Metered and capped like ai.draftText; the text sent to the model is never logged. Needs profile:edit and review:draft (owner, admin, manager).

locationId required
serviceName required
categoryName optional
currentDescription optional
dryRun optional
Preview only: returns a preview and changes nothing.

ai_postIdeas

Write, own approval steps: needs a Read & write token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Suggest 5 short Google post ideas for one location with AI, drawn from its services, a general theme of its recent positive reviews (never a quote or a reviewer's name; none at all for healthcare clients) and the occasions coming up in the next 60 days for the client's market (US, AU or IN, from the client's time zone). One AI call, metered and audited like ai.draftText. status 'ok' returns ideas; status 'blocked' returns blockedRuleIds and no ideas. Pick one, then call ai.draftPost with it. Refused with AI_BUDGET_EXCEEDED over the monthly cap, NOT_CONFIGURED when this server has no AI key. Nothing is saved. Needs review:draft (owner, admin, manager).

workspaceId required
locationId required
language optional
dryRun optional
Preview only: returns a preview and changes nothing.

ai_draftPost

Write, own approval steps: needs a Read & write token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Write one Standard Google post for one location with AI, ready to drop into the composer. idea (optional, up to 300 characters) is one of the ai.postIdeas lines; without it the AI picks from the location's services, a general theme of its recent positive reviews and the next 60 days of occasions. Aims at about 600 characters (the post limit is 1500). Metered, em dashes removed, and run through the post guardrails for that location. status 'ok' returns the text (warningRuleIds lists non-blocking findings such as banned wording); status 'blocked' returns blockedRuleIds and NO text. Nothing is saved: put the text in posts.createDraft, then posts.submit. Needs review:draft (owner, admin, manager).

workspaceId required
locationId required
idea optional
language optional
dryRun optional
Preview only: returns a preview and changes nothing.

ai_draftPostVariants

Write, own approval steps: needs a Read & write token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Write a different Standard post for each of up to 20 locations of one client with AI and put each into the approval queue as its own post (one location per post). One AI call per location, one after another, each committed on its own: a failure on one location never undoes the others. Each text names the location or its city and opens differently from the posts already written in the run. idea is optional (see ai.draftPost). For each location: drafted (saved and submitted; postStatus pending_approval, with any warnings stored on the post for the approver to read), blocked (a guardrail blocked the text; nothing saved), refused (over the monthly cap: the run stops there and the rest are not_attempted), skipped (not an active location of this client), failed (the AI call or the save failed). Posts always need a person to approve them; nothing is scheduled or sent. Same metering, guardrails and audit as ai.draftPost. NOT_CONFIGURED when this server has no AI key. Needs review:draft (owner, admin, manager).

workspaceId required
locationIds required
idea optional
language optional
dryRun optional
Preview only: returns a preview and changes nothing.

aiVoice tools

aiVoice_get

Read: works with any token

Needs the review:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

A client's AI brand voice: tone, bannedWords, signOff and language (empty language = the language of the source text). A client that was never set up returns empty values. Needs review:read.

workspaceId required

aiVoice_update

Write, proposal: needs a Read & write token

Needs the review:draft permission. Roles with it: owner, admin, manager.

Set a client's AI brand voice; only the fields you pass change. tone: up to 200 characters (for example 'warm, plain, no jargon'). bannedWords: up to 50 words or phrases the drafts must not use. signOff: up to 200 characters, added at the end of every draft. language: up to 40 characters, a language name or code; empty means the language of the source text. These feed the AI prompt; the guardrails still check every output. Needs review:draft (owner, admin, manager).

workspaceId required
tone optional
bannedWords optional
signOff optional
language optional
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

aiUsage tools

aiUsage_setClientCap

Write, proposal: needs a Read & write token

Needs the review:configure permission. Roles with it: owner, admin.

Set (or clear with null) one client's monthly AI spend cap in USD. A draft that would take the client over it is refused before the model is called. The platform-wide cap (AI_MONTHLY_BUDGET_USD) applies on top. The month is the UTC calendar month. Needs review:configure (owner, admin).

workspaceId required
monthlyCapUsd required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

aiUsage_get

Read: works with any token

Needs the review:configure permission. Roles with it: owner, admin.

This month's (UTC) AI spend per client the caller can see, with each client's cap (null = none), and whether AI is set up on this server. platform (spend and cap across all organizations) is returned only to platform admins, otherwise null. Needs review:configure (owner, admin).

reviewTopics tools

reviewTopics_setAuto

Write, proposal: needs a Read & write token

Needs the review:configure permission. Roles with it: owner, admin.

Turn the daily automatic classification of a client's new reviews by topic and sentiment on or off. Off by default, because every classification uses the client's AI allowance. Needs review:configure (owner, admin).

workspaceId required
enabled required
dryRun optional
Ignored: this tool always stores a proposal, which changes nothing until it is applied.

reviewTopics_status

Read: works with any token

Needs the review:read permission. Roles with it: owner, admin, manager, client_approver, client_viewer.

Where a client's review classification stands: whether the daily automatic classification is on (autoClassify), whether AI is set up on this server (aiOn), how many reviews are classified (classified), could not be classified (unclassified) and still wait (pending: with text and no current classification, including unclassified ones a manual run would retry). Counts only. Needs review:read.

workspaceId required