Skip to main content
Help Center

Developer

Public API

Authenticate, call endpoints, and handle errors against the ReachSurge REST API.

Overview

The ReachSurge REST API gives you programmatic access to your websites, analytics, citations, competitors, and Entity Authority data. Available on Growth and above. API keys are created by the workspace owner; a Growth team's members cannot mint one from an inherited plan. To fetch your published ARTICLE content instead (available on Starter), see the Content API, which uses a separate rsc_live_ token. Base URL:

https://reachsurge.ai/api/v1

Generate and manage keys in SettingsAPI Keys. Full endpoint reference lives at SettingsAPI KeysAPI Docs.

Authentication

Every request needs a Bearer token in the Authorization header. Pass your API key (the full string that starts with rs_live_ or rs_test_):

curl -H "Authorization: Bearer rs_live_YOUR_KEY" \
  https://reachsurge.ai/api/v1/websites

Both key types read your live production data. rs_test_ is a naming convention only. There is no sandbox. Treat every key, including test keys, as a production credential: never commit one to a repository, and rotate immediately if you have. You can revoke a key at any time from Settings → API.

Rate limits

Limits are enforced per API key, both per-minute (burst protection) and per-day (quota).

PlanPer minutePer day
Freen/an/a
Starter60500
Growth3001,000
Enterprise1,00010,000

Every response includes X-RateLimit-Remaining and X-RateLimit-Reset headers so you can pace your client. When you exceed a limit you'll get a 429 with a Retry-After value in seconds.

Endpoints

MethodPathReturns
GET/api/v1/websitesYour websites
GET/api/v1/analytics?website_id=&period=30dDaily traffic + AI citations
GET/api/v1/citations?website_id=Per-engine citation feed
GET/api/v1/competitors?website_id=Share-of-voice + competitor list
GET/api/v1/authority?website_id=Entity Authority Score breakdown

Use website_id (snake_case) on every endpoint that takes one, and period (7d, 30d or 90d) to choose the window. There is no from/to range parameter.

Error format

All errors return JSON with the same shape so your client can branch on error.code rather than parsing strings:

{ "error": { "code": "rate_limited", "message": "Rate limit exceeded. Retry after 42s" } }
Statuserror.codeWhen
401unauthorizedMissing Authorization header
401invalid_keyKey revoked or wrong format
400bad_requestRequired parameter missing (usually website_id)
403insufficient_scopeKey doesn't carry the scope the endpoint needs
404not_foundwebsite_id not in your team
429rate_limitedPer-minute burst exceeded. Honour Retry-After
429daily_quota_exceededDaily cap exhausted. Carries X-DailyQuota-* headers, not X-RateLimit-*
500server_errorSomething on our side, safe to retry with exponential backoff

Webhooks (push instead of poll)

For real-time events (new citation, backlink verified, crawl complete, content refreshed, competitor alert), subscribe in SettingsWebhooks. Each delivery is signed with HMAC-SHA256 in the X-ReachSurge-Signature header. See the Webhooks article for verification code.

FAQ

Can I rotate a leaked key without downtime? Yes. Create a new key, deploy it to your client, then revoke the old one. Both keys work simultaneously until the old one is revoked.

What's the difference between live and test keys? Both key types resolve the same team, the same plan tier, and the same quotas, and both read live production data. The rs_live_ / rs_test_ prefix is a label to help you tell keys apart in your own config. It does not change what the key can reach. If you need an isolated dataset for CI, use a separate account.

Do you have client libraries? Not officially yet. The API is plain REST + JSON. Any HTTP client works. We're tracking demand for Node and Python SDKs; ping us via Contact if that would unblock you.