RankRight API

A REST API built for AI agents and integrations — reads, org-scoped RPCs, background jobs and report files. Base URL: https://app.rankright.dev/api/v1

Try it now — public sandbox

A shared, read-only, rate-limited key over fictional data (Harbor Light Home Services, client_id 108). Every read RPC, the MCP server and these docs work with it; writes and jobs answer 403 with a hint.

Authorization: Bearer rrk_u154NZ009Kk_dbtPPuXeCpYbEZQgX6gziL-i7uZIN8k

curl -X POST https://app.rankright.dev/api/v1/rpc/get_aeo_summary -H 'Authorization: Bearer rrk_u154NZ009Kk_dbtPPuXeCpYbEZQgX6gziL-i7uZIN8k' -H 'Content-Type: application/json' -d '{"client_id": 108}'

Data is reset periodically. Sign up for a key with the write scope to use your own clients.

Authentication

Every request carries an API key in the Authorization header:

Authorization: Bearer rrk_<your-key>

Keys are issued by the platform administrator — contact [email protected] to request one for your organization. Keys are org-scoped: every call is confined and metered to your organization, and the RPC registry is deny-by-default — methods that haven't been vetted for external use return 403. Only the sha256 of your key is stored server-side; treat the plaintext like a password. Lost keys can't be recovered, only revoked and re-minted.

Requests are rate-limited per key (per-minute window; over-limit calls get 429 with a Retry-After header). Write access depends on your key's scopes (read, write, jobs).

Endpoints

Method & pathWhat it does
GET /api/v1/health Liveness probe — no auth required. Returns status + row counts.
POST /api/v1/rpc/<method> Call a vetted RPC method. JSON body = keyword arguments. Your org id is injected server-side — you never pass it, and you can't read or write another org's data. Unknown / unvetted methods return 403.
GET /api/v1/db/<table> Generic filtered read of an allowed table. Filter with ?where_<column>=value query params; org scoping is applied automatically.
POST /api/v1/jobs Enqueue a background job (audits, rebuilds, reports…). Returns { job_id, status_url }. Requires the jobs scope.
GET /api/v1/jobs/<id> Poll job status + progress + result payload.
POST /api/v1/jobs/<id>/cancel Cancel a queued or running job.
GET /api/v1/files/<path> Download generated artifacts (reports, snapshots) referenced by job results.

MCP server

Connect an agent directly (Model Context Protocol, Streamable HTTP, same bearer key — same scope, org isolation and rate limits as the REST API). Tools: every org-scoped RPC (clients, AI Visibility, branding) plus list_rpcs / describe_rpc / call_rpc for the rest. Resources: these docs. Prompts: the workflows.

# Claude Code
claude mcp add --transport http rankright https://app.rankright.dev/api/v1/mcp \
  --header "Authorization: Bearer rrk_..."

# Generic MCP client config
{"mcpServers": {"rankright": {"type": "http", "url": "https://app.rankright.dev/api/v1/mcp",
                              "headers": {"Authorization": "Bearer rrk_..."}}}}

SDKs & stability

Python: pip install rankright — or straight from here, pip install https://app.rankright.dev/sdk/rankright-python.zip (source, MIT). Any RPC as a method, jobs with wait, exports, OAuth login for CLIs/agents, webhook verification, retries, idempotency keys. TypeScript / others: generate from https://app.rankright.dev/api/v1/openapi.json.

from rankright import Client
rr = Client(api_key="rrk_...")               # or access_token="rro_..." from OAuth
rr.get_aeo_summary(client_id=12)
job = rr.exports.run(); rr.exports.download(job, "export.zip")

Versioning: the API is path-versioned (/api/v1, echoed in X-RankRight-API-Version). Additive changes ship any time and are listed in the changelog; breaking changes only in /api/v2 with 12 months of overlap; a documented method is retired only after 60 days' notice (owner email, the api.deprecation webhook, Deprecation/Sunset/Link headers on every call until then).

OAuth 2.0 for apps & MCP clients

Third-party applications should not hold long-lived keys. RankRight is an OAuth 2.0 authorization server: authorization code + PKCE (S256) only, dynamic client registration (RFC 7591), discovery at https://app.rankright.dev/.well-known/oauth-authorization-server and https://app.rankright.dev/.well-known/oauth-protected-resource/api/v1/mcp. Access tokens (rro_…) live one hour; refresh tokens rotate and slide for 30 days. Scopes read, write, jobs, offline_access, capped by the approving member's role. Members manage grants under Account → Connected apps.

# MCP clients need nothing but the URL — they discover OAuth and open the consent page
claude mcp add --transport http rankright https://app.rankright.dev/api/v1/mcp

# Any client: register once, then the standard code + PKCE flow
curl -X POST https://app.rankright.dev/oauth/register -H "Content-Type: application/json" \
  -d '{"client_name": "My agent", "redirect_uris": ["https://myapp.example/callback"]}'
# → open https://app.rankright.dev/oauth/authorize?response_type=code&client_id=…&redirect_uri=…&scope=read+write+offline_access
#        &code_challenge=…&code_challenge_method=S256&state=…
# → POST https://app.rankright.dev/oauth/token  grant_type=authorization_code&code=…&code_verifier=…&client_id=…&redirect_uri=…
# → Authorization: Bearer rro_…  on /api/v1/* and the MCP server

Security & policies

Encryption, tenant isolation, key scopes, retention, US data residency, incident handling and vulnerability disclosure are documented on the security page (machine-readable contact at /.well-known/security.txt). See also the Privacy Policy (sub-processors, Google Limited Use) and Terms of Service (API deprecation notice, data export).

Single sign-on

Interactive login supports OpenID Connect (authorization code + PKCE, scopes openid email profile). Configured here: Google.

  • Bring your own IdP: Self-serve: an organization owner adds any OIDC issuer (Google Workspace, Microsoft Entra, Okta, OneLogin, JumpCloud, Vendasta) under Account → Single sign-on — issuer URL, client id/secret, allowed email domains, default role for new staff. Register the redirect_uri above with the IdP. Staff then sign in at /login/sso with their work email; unknown staff on an allowed domain are provisioned into that organization. RPCs: list/add/update/delete_org_sso_provider. Redirect URI: https://app.rankright.dev/auth/oidc/<provider>/callback
  • Verification: id_token signature via the provider JWKS; issuer, audience, expiry and nonce checked; state is single-use with a 10-minute TTL; only verified emails are accepted.
  • Accounts: The verified email is matched to an existing RankRight user (any org). An SSO sign-in stands in for the TOTP second factor. Unknown emails are provisioned as owner of a new organization only when the provider has allow_signup, the email domain is in its allowed_domains, or public signup is open; otherwise the user is told to ask an owner for an invite.
  • SAML: SAML 2.0 supported, self-serve per organization (Account → Single sign-on → SAML): SP-initiated, HTTP-Redirect AuthnRequest, HTTP-POST Response; signed Responses or Assertions verified against the IdP certificate; Conditions, Audience, Recipient and InResponseTo checked; encrypted assertions not supported. Give the IdP the SP metadata URL https://app.rankright.dev/saml/<provider key>/metadata (ACS https://app.rankright.dev/saml/<provider key>/acs). Staff sign in at https://app.rankright.dev/login/sso.
  • API & MCP: SSO governs interactive sign-in only; API and MCP access always use rrk_ bearer keys.

Webhooks

Skip polling: register an https endpoint and receive a signed POST when something happens. register_webhook(url, events) (owner) returns the signing secret once; manage with list_webhooks, update_webhook, rotate_webhook_secret, delete_webhook, test_webhook, list_webhook_deliveries, redeliver_webhook — or on the account page.

EventWhen
job.completed / job.failed / job.cancelledA background job reached a terminal state (kind, client_id, error, result summary, status_url).
aeo.capture.ingestedAn AI-engine answer was captured and analyzed (engine, month, scorecard, new / carried / resolved counts).
aeo.report.savedA monthly AI Visibility report was filed.
aeo.item.status_changed / action_item.status_changedA tracker / action item changed status.
pingSent by test_webhook.
POST <your url>
Content-Type: application/json
X-RankRight-Event: job.completed
X-RankRight-Delivery: 8123
X-RankRight-Timestamp: 1788650000
X-RankRight-Signature: t=1788650000,v1=<hex HMAC-SHA256(secret, "1788650000." + body)>

{"id": 8123, "event": "job.completed", "created_at": "…", "org_id": 7, "client_id": 42, "data": {…}}

Respond 2xx within 10 s. Failures retry with exponential backoff (1, 2, 4 … 64 min, 8 attempts); a hook is disabled after 100 consecutive failures. Reject deliveries whose timestamp is more than 5 minutes old. URLs must be https and publicly routable.

Machine-readable docs & workflows

Everything on this page, generated from the live registries (cannot drift):

  • GET https://app.rankright.dev/llms.txt — orientation for AI agents (public)
  • GET https://app.rankright.dev/developers.md — full guide: conventions, workflows, every RPC with params and summary (public; /llms-full.txt is the same text)
  • GET https://app.rankright.dev/api/v1/openapi.json — OpenAPI 3.1, operations tagged by domain (ai-visibility, clients, search-console, …), workflows under x-workflows (public)
  • GET https://app.rankright.dev/api/v1/capabilities — the same inventory as JSON (auth)

Export everything in three calls

  1. POST /api/v1/jobs {"kind": "export_org"} (owner key; a service account adds org_id)
  2. poll GET /api/v1/jobs/<id> — or take the job.completed webhook
  3. GET /api/v1/exports/<org_id>/<filename> — every table as JSON + CSV, filed reports, a manifest; kept 7 days

AI Visibility (AEO) in six calls

Does ChatGPT / Claude / Gemini name and cite a client for buyer questions? All org-scoped by client_id.

  1. generate_aeo_questions(client_id) — question set from the client's services + locations
  2. set_aeo_cadence(client_id, samples_per_month=1, engines=['claude','chatgpt-web']) — enrol; the daily sweep queues runs
  3. get_aeo_summary(client_id) — presence / named-first per service, open tasks, queue
  4. get_aeo_items(client_id, status='open') — the action list (tier A/B website, C Google Business / directories, X market-driven)
  5. update_aeo_item_status(item_id, 'done', client_id=…) — as work completes
  6. aeo_report_html(client_id, month) — white-label monthly report (update_organization_branding sets name / logo / accent)

Quick start

# Liveness
curl https://app.rankright.dev/api/v1/health

# List your clients
curl -X POST https://app.rankright.dev/api/v1/rpc/get_all_clients \
  -H "Authorization: Bearer rrk_..." \
  -H "Content-Type: application/json" -d '{}'

# Enqueue a job, then poll it
curl -X POST https://app.rankright.dev/api/v1/jobs \
  -H "Authorization: Bearer rrk_..." \
  -H "Content-Type: application/json" \
  -d '{"kind": "strategist", "client_id": 123}'

curl https://app.rankright.dev/api/v1/jobs/456 \
  -H "Authorization: Bearer rrk_..."

Errors are JSON: {"error": "..."} with conventional HTTP status codes (401 bad/revoked key, 403 not permitted, 404 not found / not yours, 429 rate-limited, 503 writes disabled).