Skip to main content
REST API v1

API Reference

Base URL: https://botscope.io/api/v1. All endpoints require X-Botscope-Api-Key: YOUR_KEY.

Authentication

Pass your Site API key via X-Botscope-Api-Key header or ?api_key= query param. Find it in the dashboard under Sites → your site → API Key.

/reports* endpoints also accept Authorization: Bearer {token} — a personal access token (Account → API Tokens) scoped to the reports:read ability, letting you query across every site you have access to instead of just one.

POST /api/v1/agent/check

Evaluate a single HTTP request. Returns action + TTL. The agent caches decisions for TTL seconds — subsequent requests from the same visitor hit the local cache.

pass observe challenge block
Request body
{
  "ua":                  "Mozilla/5.0 (compatible; Googlebot/2.1)",
  "ip":                  "66.249.64.0",
  "path":                "/products",
  "visitor_id":          "v_abc123",
  "known_bot_slug":      "googlebot",
  "web_bot_auth_status": "verified_signed",
  "robots_disallowed":   false
}
Response · application/json
{
  "action":          "pass",
  "ttl":             300,
  "decision_reason": "known_bot:googlebot",
  "challenge": {
    "type":         "pow",
    "status_code":  403,
    "theme":        "light",
    "accent_color": "#6366f1"
  }
}
POST /api/v1/agent/sync

Pull the latest configuration. Call on agent startup and every 5 minutes. Also records the running agent version for the dashboard.

Request body
{
  "version": "1.4.2",
  "php":     "8.3"
}
Response · application/json
{
  "mode": "enforce",
  "robots_txt": {
    "disallowed_ua_tokens": ["GPTBot", "CCBot"],
    "etag": "d41d8cd9"
  },
  "rules":      [ … ],
  "banned_ips": [],
  "challenge":  { "type": "pow", "status_code": 403 },
  "agent": {
    "auto_update": true,
    "latest_version": "1.4.2"
  }
}
GET /api/v1/agent/config

Same shape as /agent/sync but does not record the agent version. Use for health checks or initial bootstrap reads.

Response · application/json
{ /* same shape as /agent/sync */ }
GET /api/v1/agent/robots.txt text/plain

Returns the generated robots.txt for your site as plain text. Supports ETag / If-None-Match for conditional fetching.

Response · text/plain
# Generated by Botscope — 2026-06-08
# 1593 known agents · site: example.com

User-agent: GPTBot
Disallow: /

User-agent: Googlebot
Allow: /
POST /api/v1/agent/verify

Perform a reverse-DNS or CIDR lookup to confirm a bot IP belongs to the declared operator.

Request body
{
  "ip":       "66.249.64.0",
  "bot_slug": "googlebot"
}
Response · application/json
{
  "verified": true,
  "method":   "rdns",
  "hostname": "crawl-66-249-64-0.googlebot.com"
}
POST /api/v1/ingest

Record a batch of traffic events for analytics. The agent queues these and sends them asynchronously.

Request body
{
  "events": [
    {
      "visitor_id":      "v_abc123",
      "ua":              "Mozilla/5.0 …",
      "ip":              "1.2.3.4",
      "path":            "/products",
      "action":          "pass",
      "decision_reason": "allowed",
      "known_bot_slug":  null,
      "ts":              1748000000
    }
  ]
}
Response · application/json
{ "accepted": 1 }
POST /api/v1/telemetry

Record one traffic event synchronously (used by the browser SDK and the PHP agent for real-time signals). Rejects timestamps more than 5 minutes old or in the future. Returns 402 once the monthly event quota for your plan is exceeded.

Request body
{
  "site_id":         "…",
  "ip":              "1.2.3.4",
  "ua":              "Mozilla/5.0 …",
  "uri":             "/products",
  "action":          "pass",
  "decision_reason": "allowed",
  "timestamp":       1748000000
}
Response · application/json
{ "ok": true }
GET /api/v1/reports

Self-describing index: available report names, segment dimensions, supported query parameters, and the two supported auth modes.

Response · application/json
{
  "reports": ["traffic-overview", "bot-breakdown", "ai-citations", …],
  "segment_dimensions": ["trafficKind", "anomalyScore", "referrerType", …],
  "authentication": {
    "api_key": "X-Botscope-Api-Key header — single site scope",
    "bearer":  "Authorization: Bearer {token} — multi-site, optional site_id query"
  },
  "parameters": { "days": "1–365, default 28", "format": "json | csv | html | pdf", "…": "…" }
}
GET /api/v1/reports/{report}

Run one of the reports listed by GET /reports. Use a personal access token (scoped to the "reports:read" ability) instead of the site API key to query across every site you have access to in one call — pass ?site_id= to narrow to one. Add ?format=csv|html|pdf to download instead of JSON.

Response · application/json
{
  "report":   "traffic-overview",
  "auth":     "api_key",
  "site_ids": ["…"],
  "site_id":  "…",
  "segment":  null,
  "data":     { "…": "…" }
}

Error responses

401 Unauthorized Missing or invalid API key
422 Unprocessable Validation error — check the JSON body
429 Rate limited Slow down — per-site rate limit exceeded
500 Server error Our fault — retry with exponential backoff