Which address should you use?
Sign in and manage keys in the app athttps://app.sorank.com/settings/api. Send API requests to https://app.sorank.com/api/public/v1. There is no API endpoint to create or host yourself.
Your first request, step by step
- Open Settings → API access in the SORANK app and select Create key.
- Give the key a name, select at least one website, select View websites (
profiles:read), choose an expiry, and create it. Add View quotas (quotas:read) if you want the second request below. - Copy the complete key now. It is shown only once. Keep it in a secret manager or a local environment variable; the prefix shown later in settings cannot authenticate requests.
- Choose an example below. For cURL, enter the key when prompted. For JavaScript or Go, provide it as the server process’s
SORANK_API_KEYenvironment variable. The HTML tab includes a local Node.js backend at127.0.0.1:3100; run it with the key in its environment, then open that address in a browser. Keep the key out of HTML and browser JavaScript. Add your application’s authentication before using this pattern beyond a local demo.
- cURL
- HTML
- JavaScript
- Go
data list of the websites you authorized. Copy one data[].id value for calls requiring profile_id. If the list is empty, check the website selection on your key and your access to it. The cURL, JavaScript and Go examples also read that profile’s quota when you have granted quotas:read.
Use the Public API reference in the developer navigation to find every path, required scope, request body and response schema. The first request above is read-only; it does not use account quota.
Authenticate
Create a personal API key in Settings → API access for scripts, or authorize an OAuth client with PKCE S256. Restrict the key or grant to the profiles and exact scopes you need. Send it as a Bearer token. Browser cookies and Supabase tokens do not authorize this API. For an application connecting on a user’s behalf, start athttps://app.sorank.com/.well-known/oauth-protected-resource/api/public/v1 and https://app.sorank.com/.well-known/oauth-authorization-server. Discover the advertised authorization, token and registration endpoints. Register a public client if needed, then use authorization code with PKCE S256, the scopes you need, and the exact resource value https://app.sorank.com/api/public/v1. Send the resulting access token as Bearer. An MCP access token has a different resource and cannot be reused for REST.
Permissions and quota
ReadgetQuotas before generation. profiles:read, quotas:read, calendar:read, calendar:write, articles:read, articles:generate and articles:publish cover the example below. Calendar creation also requires generation and publication scopes. One account quota applies across the app, REST and MCP; extra keys do not increase it.
The read scopes View products (products:read), View analytics (analytics:read), View AI visibility (geo:read) and View settings (settings:read) never consume quota. Edit settings (settings:write) changes the same settings as the app; grant it only when you want an integration to change them.
Check eligibility
The API is available once you have completed onboarding in Sorank and the website has a valid subscription. An agency collaborator uses the website owner’s subscription. Sorank checks this when you create a key or approve an OAuth connection, and again on every request.listProfilesreturns only eligible websites.- An unfinished onboarding returns
403 onboarding_required. - A website without a valid subscription returns
402 subscription_required, withdetails.reason(paused,past_due,incompleteorinactive) when known.
Read products, analytics, AI visibility and settings
These reads return what the Sorank app shows you. They never start an analysis, a synchronization or a generation.- Products (
products:read):listProductspages through the product catalog with a cursor. After409 product_catalog_cursor_stale, restart from the first page. - Analytics (
analytics:read): Search Console performance, queries, pages, countries and devices, and Google Analytics traffic from AI assistants.startandend(YYYY-MM-DD) are required. Each call reads Google live and has a lower rate limit. Connect Google in Sorank first; otherwise you receive409 gsc_not_connectedor409 ga_not_connected, and403 google_access_lostwhen access was lost. - AI visibility (
geo:read): GEO statistics, mentions over time, citations timeline, citing sources and the competitors cited in an analysis. - Settings (
settings:read):getSettingsreturns the website, the business brief with itsrevision, competitors, article defaults, visuals and the YouTube channel.
Change settings
Withsettings:write, you can change the business name, brand color and market, replace the business brief, replace the competitor list, change the calendar article defaults, the image mode and covers, and connect, pause or disconnect the YouTube channel. The website URL cannot be changed through the API (400 field_not_writable).
Each change requires an Idempotency-Key. The response contains the resulting settings, a receipt and an effects list naming the background work the change started, as in the app: geo_questions_regeneration_queued, backlink_refresh_queued, calendar_slots_shifted, image_gallery_analysis_queued, youtube_sync_queued or youtube_purge_queued.
To replace the business brief, send the expected_revision read from getSettings. If the brief changed meanwhile, you receive 409 business_brief_revision_conflict: read the settings again before retrying.
Try a complete REST workflow
The following advanced example creates content and can consume quota. Replace the example IDs, future dates, idempotency keys and credential before running it. Use a key with the scopes above. Dates are local to the IANA timezone in the calendar request. CheckgetCapabilities before selecting a CMS target or category.
Track work and retry
Mutations require a uniqueIdempotency-Key. Keep the same key when retrying the same command. Read data.receipt.operation_id, then poll getOperation until succeeded, failed or verification_pending. An accepted receipt does not mean publication is complete. An article generation batch returns 202 with a receipt that is already succeeded; follow each article listed in selection.accepted_ids with getArticle. Reauthorization occurs on every poll, so revocation takes effect immediately.
Handle errors
Every error has the same shape in REST and MCP:{"error": {"code", "message", "request_id", "retryable", "details"}}. Base your logic on code, not on the message. Retry only when retryable is true, after Retry-After when present.
401 invalid_credential: invalid, expired or revoked credential.403 missing_scopeor403 onboarding_required;402 subscription_requiredor402 insufficient_quota.404 not_found: the resource is missing or not accessible to this credential.409: a conflict such asidempotency_conflict;429 rate_limited: wait forRetry-After.503 auth_state_unavailable: access is denied until the authorization state recovers; retry later.
code and request_id with support; never send your token.
For assistant connections, see the MCP guide.
