Documentation Index
Fetch the complete documentation index at: https://docs.keupera.com/llms.txt
Use this file to discover all available pages before exploring further.
The Keupera Public API gives you programmatic access to every major platform module: Keyword Research, Backlink Research, Content Management, AI Visibility, and Analytics.
Base URL
https://app.keupera.com/api/v1
All resources are available directly under this prefix, for example:
GET https://app.keupera.com/api/v1/keywords
GET https://app.keupera.com/api/v1/campaigns
GET https://app.keupera.com/api/v1/articles
GET https://app.keupera.com/api/v1/brand-radar/campaigns
GET https://app.keupera.com/api/v1/website/summary
GET https://app.keupera.com/api/v1/me
Authentication
Every request must include your API key as a Bearer token:
Authorization: Bearer YOUR_KEUPERA_API_KEY
Generate keys from Account → API Keys in your Keupera dashboard.
Each key:
- Belongs to a single user and is bound to one website by default (configurable in the dashboard).
- Requires a paid subscription tier with API access enabled.
- Only sees websites within your organisation(s).
Your subscription plan must include Public API access. Requests from plans without API entitlement return 403 Forbidden.
Scoping to a specific website
If your key is bound to a website, every request defaults to that website. To target a different website you own, pass website_id as a query parameter:
GET /api/v1/keywords?website_id=<uuid>
The website must belong to one of your organisations, otherwise the API returns 403.
Common query parameters
Most endpoints accept:
| Parameter | Type | Default | Description |
|---|
website_id | UUID | API key’s website | Override the target website |
limit | integer | varies per endpoint | Number of results to return |
page | integer | 1 | Page number for paginated endpoints |
Date range parameters
Analytics and Search Console endpoints accept date ranges:
| Parameter | Type | Default | Description |
|---|
range | string | 30d | Preset: 7d, 30d, 90d |
from | string | — | Start date (YYYY-MM-DD) |
to | string | — | End date (YYYY-MM-DD) |
When both from and to are provided, range is ignored.
All responses are JSON and follow a consistent shape.
Success
{
"data": [ /* ... */ ],
"meta": {
"total": 150,
"page": 1,
"limit": 20
}
}
Error
{ "error": "Descriptive error message" }
HTTP status codes
| Code | Meaning |
|---|
200 | Success |
201 | Created |
400 | Bad request — missing or invalid parameters |
401 | Unauthorized — missing or invalid API key |
402 | Usage limit reached — crawl credits, AI credits, etc. exhausted |
403 | Forbidden — inactive key, no API access, or unauthorized website |
404 | Not found |
500 | Internal server error |
Rate limits & usage
Each API call counts against your plan’s limits the same way in-app actions do:
| Resource | Routes that consume it |
|---|
keyword_research (10 crawl credits) | POST /keywords/research, automatic enrichment in POST /keywords |
backlink_research (20 crawl credits) | POST /campaigns (backlinks) |
ai_credits (per-token) | POST /opportunities/:id/generate-email, POST /articles, POST /articles/:id/generate |
crawl_credits | Enrichment, GSC syncs |
When a limit is reached the API responds with 402 Payment Required. Enable metered billing in Account → Billing → Usage to allow overage.
CORS
All endpoints respond with Access-Control-Allow-Origin: * so they can be called from any origin — but never ship a key in a browser; always proxy requests through your own backend.