Authentication
One key, three surfaces
Bearer keys with scopes drive REST, A2A, and MCP. Console keys choose Read-only or Read + write, and either all sites or a selected list; admin-issued keys carry any scope subset.
Updated 2026-11-08
On this page
API key setup
One key walks the whole flow: REST, A2A, and MCP share the same Bearer credential.
Get a key — admin-issued or self-serve
Admins issue keys in the admin console (POST /v1/ai/keys, any scope subset). Signed-in users create a key in Console → Access (POST /v1/seo/me/api-keys): pick a preset (Read-only / Read + write) or individual scopes, all sites or selected sites, optional 30/90/365-day expiry, max 5 live keys. A raw key is shown once — store it as $SEO_WATCH_KEY and never paste it into docs or chat.
Pick the right permissions
Read-only = radar:read + rules:read + audit:read. Read + write adds sites:write (create/verify sites, billing), audits:write (run audits, import sitemaps), keywords:write and monitoring:write (schedules, alerts, webhooks, custom checks). The agent endpoints still take the smallest scope that does the job: A2A message/send and the site/finding MCP tools need audit:read; the MCP radar tool needs radar:read. The MCP handshake (initialize, notifications/initialized, tools/list, ping), A2A tasks/get, and GET 405s need no key.
Scope by site, not by creation
A key can reach all your sites or only the ones you select. The whitelist gates reads, audits and write tools on those sites; it does not block site creation or the GSC import flow. Radar and rule reads are global and not site-scoped. Other site ids answer 404, the same as a site that does not exist.
Auth failures are uniform
REST answers 401 AUTH_UNAUTHORIZED; A2A/MCP answer 401 with JSON-RPC error code -32002. Missing key and wrong scope look identical on purpose.
No anonymous quota anymore
Agent endpoints no longer count per-IP anonymous quota — a valid key is the only gate. Usage still counts against the key's monthly quota.
Auth · scopes
Pick a credential, then the smallest scope that does the job. Missing key and insufficient scope look identical on purpose (401 AUTH_UNAUTHORIZED; A2A/MCP answer JSON-RPC -32002).
Credentials
Admin-issued key REST · A2A · MCP
Issued in the admin console (POST /v1/ai/keys). Any subset of the 8 scopes, picked at issuance. Raw key shown once — store it as $SEO_WATCH_KEY.
Console self-serve key REST · A2A · MCP
Created in Console → Access (POST /v1/seo/me/api-keys). Pick a preset or individual scopes, all sites or a selected list; never expires by default (optional 30/90/365-day expiry), max 5 live keys. Same $SEO_WATCH_KEY usage.
Login session / Cloudflare Access Console BFF (me/*) · admin console only
Google session cookie drives me/*; Access identity drives the admin console. Neither reaches AI key endpoints — third parties always use a key.
Boundary: me/* endpoints serve the console BFF only (session credential) and are intentionally absent from every reference table here — third parties always use an API key surface above.
Scope matrix
any valid key Any valid key may self-read its quota; the call is not counted.
- GET /v1/ai/quota
radar:read Read Google update radar (triage-filtered). Also gates the MCP get_radar_updates tool.
- GET /v1/ai/updates
- GET /v1/ai/updates/impact
rules:read Read versioned audit rules.
- GET /v1/ai/rules
audit:read Read audit runs, findings, and site reports. Also gates A2A message/send and the site/finding MCP tools.
- GET /v1/ai/audit-runs
- GET /v1/ai/audit-runs/{runId}/findings
- GET /v1/ai/audit-runs/{runId}/findings/{findingId}
- GET /v1/ai/sites/{id}/aeo
- GET /v1/ai/sites/{id}/cross-report
- GET /v1/ai/sites/{id}/fingerprint
- GET /v1/ai/sites/{id}/gsc
- GET /v1/ai/sites/{id}/i18n
- GET /v1/ai/sites/{id}/opportunities
- POST /v1/ai/sites/{id}/effect-verify
sites:read Read competitor targets you own. Gates the MCP get_competitor_changes / get_competitor_feed / get_competitor_gaps tools; write tools stay on their own scopes.
sites:write Create and verify sites, and open billing endpoints for the owning account.
- POST /v1/ai/sites
- POST /v1/ai/sites/{id}/verify
audits:write Run audits and import sitemap URLs. Gates the MCP run_audit / import_sitemap tools.
- POST /v1/ai/sites/{id}/audits
- POST /v1/ai/sites/{id}/import-sitemap
keywords:write Add tracking keywords, write annotations and enrich terms with vendor data.
- POST /v1/ai/sites/{id}/annotations
- POST /v1/ai/sites/{id}/keywords
- POST /v1/ai/keywords/enrich/estimate
- POST /v1/ai/sites/{id}/keywords/enrich
monitoring:write Manage audit schedules, alert/webhook subscriptions and custom checks.
- GET /v1/ai/schedules
- POST /v1/ai/sites/{id}/schedules
- DELETE /v1/ai/schedules
- GET /v1/ai/subscriptions
- POST /v1/ai/subscriptions
- DELETE /v1/ai/subscriptions/{id}
- GET /v1/ai/notify-subscriptions
- POST /v1/ai/notify-subscriptions
- DELETE /v1/ai/notify-subscriptions/{id}
- POST /v1/ai/notify-subscriptions/batch
- GET /v1/ai/custom-checks
- POST /v1/ai/custom-checks
- POST /v1/ai/custom-checks/{id}/run
- POST /v1/ai/custom-checks/batch
admin only Admin console only (Cloudflare Access + allowlist). Bearer keys never pass this gate.
- GET /v1/ai/keys
- POST /v1/ai/keys
- POST /v1/ai/keys/{id}/revoke
- POST /v1/ai/keys/batch
- GET /v1/ai/sites/{id}/cross-report
- POST /v1/ai/sites/{id}/effect-verify
- GET /v1/ai/sites/{id}/gsc
- GET /v1/ai/sites/{id}/opportunities
Agent presets
Read-only patrol radar:read + rules:read + audit:read + sites:read
An agent that inspects radar, rules, and findings but changes nothing.
Can execute patrol + all write scopes
Adds site setup, audits, keywords, monitoring, alerts, webhooks and custom checks. Console keys can request this preset; a site whitelist only limits which sites they can read or audit.
Handshake methods need no key: A2A tasks/get, MCP initialize / tools/list / ping, and GET 405s. Everything else answers 401 without a valid key.
Agent prompts, one-click copy
Generated from the OpenAPI surface, never hand-written. <YOUR_API_KEY> stays a placeholder everywhere.