the BotScope
API.
Pull your organisation’s LLM-visibility data — projects, scans, layer scores, share of voice and competitor comparisons — over plain HTTPS and JSON. Authenticate with an org-scoped API key.
- Base URL: https://api.botscope.ai/api/v1
- Authenticate with a Bearer API key created in Settings → Developers.
- Every response is JSON, wrapped in { "data": ... }.
- The API is read-only — it never changes your data or spends credits.
- Included on all paid plans. Rate limit: 120 requests/minute per key.
- Machine-readable spec: openapi.json (OpenAPI 3.1).
This reference describes v1. We’ll add endpoints over time; existing responses won’t change shape without a new version.
SECT.01 Authentication.
Create a key in the dashboard under Settings → Developers → Create
key. The full key (prefixed bsk_) is shown once — store it safely; you can’t retrieve it again,
only revoke it. Send it as a Bearer token on every request:
curl -H "Authorization: Bearer bsk_your_key_here" \
https://api.botscope.ai/api/v1/projects A key only reads the organisation it was created in. Treat it like a password — anyone with the key can read your data. Revoking a key from the same page takes effect immediately.
SECT.02 Quickstart.
export BSK="bsk_your_key_here"
export BASE="https://api.botscope.ai/api/v1"
# 1. List your projects
curl -s -H "Authorization: Bearer $BSK" "$BASE/projects"
# 2. Read a project's visibility overview
PID="<a project id from step 1>"
curl -s -H "Authorization: Bearer $BSK" "$BASE/projects/$PID/visibility" SECT.03 Endpoints.
| Method | Path | Description |
|---|---|---|
| GET | /projects | List all projects in your organisation |
| GET | /projects/{id} | A single project’s configuration |
| GET | /projects/{id}/scans | Paginated scan history (newest first) |
| GET | /projects/{id}/visibility | Overall + L1–L4 scores, trends, citations, share of voice |
| GET | /projects/{id}/share-of-voice | Own brand vs competitor mention share |
| GET | /projects/{id}/competitors | Own brand + tracked competitors by median mentions |
| GET | /projects/{id}/categories | Per-category share of voice, providers, trend, top competitors |
| GET | /projects/{id}/responses | Paginated index of raw LLM responses |
| GET | /projects/{id}/responses/{responseId} | One response with brand detections + citations |
Example response — visibility (numbers are medians across the resolved scans, matching the dashboard):
{
"data": {
"projectId": "1d7367ae-...",
"overall": 34.6,
"overallTrend": 2.1,
"l1": { "layer": "L1", "name": "Entity Recognition", "score": 61.2, "trend": 1.0 },
"l3": { "layer": "L3", "name": "Category Inclusion", "score": 4.93, "trend": 0.2 },
"totalCitations": 59,
"lastScanAt": "2026-05-10T11:36:01.588Z",
"shareOfVoice": { "ownBrandShare": 0.27, "competitors": [] },
"comparedTo": { "kind": "previous_scan", "overall": 32.5 }
}
} SECT.04 Parameters.
Most read endpoints accept a selector for which data to aggregate. With none, they use the latest scan.
| Param | Description |
|---|---|
provider | Filter to one provider, e.g. openai, google_ai_overview. |
scanId | Pin to a specific scan (from the scans list). Takes precedence over a date range. |
from / to | ISO-8601 date window. Both required together. Aggregated across scans in range. |
layer | Responses only — filter to a visibility layer: L1, L2, L3, L4. |
limit | Page size for scans/responses, 1–200 (default 50). Out-of-range values are clamped. |
before | Keyset cursor — pass the previous response’s pagination.nextBefore. |
# One provider
curl -s -H "Authorization: Bearer $BSK" \
"$BASE/projects/$PID/visibility?provider=google_ai_overview"
# A date window (both from & to required)
curl -s -H "Authorization: Bearer $BSK" \
"$BASE/projects/$PID/visibility?from=2026-04-01T00:00:00Z&to=2026-05-31T23:59:59Z"
# A specific scan
curl -s -H "Authorization: Bearer $BSK" \
"$BASE/projects/$PID/visibility?scanId=<scan-id>" SECT.05 Pagination.
List endpoints return a pagination object. When nextBefore is non-null, pass it as before for the next (older) page; null means you’ve reached the end.
{ "data": [ ... ], "pagination": { "limit": 20, "nextBefore": "2026-05-10T09:53:43.562Z" } } SECT.06 Rate limits.
Each key is limited to 120 requests per minute. Every
response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset (Unix
epoch second). Exceeding it returns 429 with a Retry-After header.
SECT.07 Errors.
Errors share one shape:
{ "error": { "code": "not_found", "message": "Project not found", "details": null } } | Status | code | When |
|---|---|---|
| 401 | unauthorized | Missing or malformed Authorization header |
| 401 | invalid_api_key | Unknown, revoked, or expired key |
| 403 | feature_not_available | Your plan doesn’t include API access |
| 404 | not_found | Resource doesn’t exist or belongs to another org |
| 422 | validation_error | Invalid query/path parameter (see details) |
| 429 | rate_limited | Per-key rate limit exceeded |
For privacy, a resource in another organisation returns 404, not 403 — the API never discloses whether something you can’t see exists.
SECT.08 MCP server.
Prefer to use BotScope from an AI assistant? We host a remote MCP server that
exposes these endpoints as tools, so Claude and other MCP clients can read
your data directly. Authenticate with the same bsk_ key as a
Bearer header.
URL: https://mcp.botscope.ai/mcp (Streamable HTTP) · …/sse (legacy).
Claude Code (one line; replace with a real key):
claude mcp add --transport http botscope https://mcp.botscope.ai/mcp --header "Authorization: Bearer bsk_your_key_here" Cursor / Windsurf / generic mcp.json:
{
"mcpServers": {
"botscope": {
"url": "https://mcp.botscope.ai/mcp",
"headers": { "Authorization": "Bearer bsk_your_key_here" }
}
}
} Questions or feedback? Email [email protected].