CitationBenchTalk to Sales
Get started

Authentication — bearer keys, workspace scoping, and demo mode

Bearer API keys for REST and MCP, agency master keys with workspace scoping, sandbox test keys, and a unique no-signup demo mode so AI agents can integrate before the user has an account.

CitationBench uses bearer API keys for both the REST API and the hosted MCP server. There's also a demo mode that lets AI agents build, test, and integrate against the real API before the user has an account.

Quick reference

HeaderAuthorization: Bearer sk_live_***
MCP alternativepassed as a connection header at install time
Workspace scopingX-Workspace-Id: ws_*** header (agency master keys only)
Live keyssk_live_*** — production, real credits
Test keyssk_test_*** — sandbox, fake credits, mocked third-party calls
Demo modeno key required — see below

Demo mode

Build first, sign up later. Every CitationBench endpoint — REST and MCP — responds to unauthenticated requests in demo mode. The response shapes are identical to the real ones, so your integration can be wired end-to-end before the user creates an account.

Why demo mode exists

AI agents (Claude Code, Cursor, ChatGPT, custom agents) are increasingly the first thing that touches a developer API. We want an agent to be able to:

  1. Discover CitationBench via the MCP catalog or docs site
  2. Read the API
  3. Build an integration against it
  4. Test that the integration works against real-shape responses
  5. Only then ask the human user to sign up + provide an API key

You shouldn't have to interrupt the agent to make the user create an account just to confirm the integration runs.

What demo mode does

  • REST: any request without Authorization (or with Authorization: Bearer demo) returns a demo-mode response with the same shape as a live response. The X-CitationBench-Mode: demo header is set on every demo response so you can detect it.
  • MCP: connect without a header and the server registers itself in demo mode. Every tool call returns a demo response.
  • Demo responses are deterministic and shape-complete — every field a live response would carry is present, populated with realistic synthetic values.
  • No state is persisted. Demo mode is stateless; the data you "create" in demo mode doesn't exist between calls. Useful for shape-checking, not for testing flows that depend on prior state.
  • No real third parties are called. DataForSEO, Ahrefs, Apollo, Instantly, Google — none of them are touched in demo mode.

What demo mode does NOT do

  • It does not run real agents, so you can't measure real latency or LLM behavior.
  • It does not preserve state across calls (no "look up the keyword I just created").
  • It does not enforce real workspace scoping or quotas.
  • It does not return real SERP / citation / ranking data.

Switching from demo to live

The contract is the same. Add Authorization: Bearer sk_live_*** to your existing code and everything starts running for real. No request-shape changes. No new endpoints to discover.

The agent flow that should win:

[agent]   integrates with CitationBench in demo mode
[agent]   confirms all tool calls return the expected shapes
[agent]   tells the user: "Integration is ready. To run for real,
          sign up at citationbench.com and paste your API key here."
[user]    signs up, pastes sk_live_***
[agent]   re-runs the same code paths against live data

Example

# Demo mode — no key needed
curl -X POST https://api.citationbench.com/v1/research/keyword \
  -H "Content-Type: application/json" \
  -d '{ "seed": "project management software", "limit": 50 }'

# → 202 Accepted
# X-CitationBench-Mode: demo
#
# {
#   "invocationId": "inv_demo_***",
#   "agentId":      "agt_demo_***",
#   "skill":        "research.keyword",
#   "status":       "RUNNING",
#   "estimatedCost": { "credits": 0, "durationSeconds": 0 },
#   "demoMode":     true,
#   "links": { ... }
# }

# Then GET the invocation — demo mode returns a complete, deterministic result
curl https://api.citationbench.com/v1/agent/invocations/inv_demo_xxxx
# → 200 OK
# X-CitationBench-Mode: demo
# {
#   "invocationId": "inv_demo_xxxx",
#   "agentId":      "agt_demo_xxxx",
#   "skill":        "research.keyword",
#   "status":       "SUCCEEDED",
#   "result":       { /* full structured output with synthetic keywords */ },
#   "raw":          "...",
#   "files":        ["agent-workspace/keywords-full.csv", ...],
#   "demoMode":     true
# }
# MCP demo mode — no header at install
claude mcp add citationbench https://mcp.citationbench.com/mcp

# Tools light up immediately; every call returns a demo response.

Detecting demo mode at runtime

Every demo response carries:

  • HTTP header X-CitationBench-Mode: demo
  • The string demo somewhere in invocationId, agentId, and similar IDs (inv_demo_***, agt_demo_***)
  • A demoMode: true field on the top-level body
if (response.headers["x-citationbench-mode"] === "demo") {
  console.warn("Running in demo mode — sign up to run live.");
}

Live keys

Create one at https://app.citationbench.com/api-keys. Two flavors:

  • sk_live_*** — production. Bills real credits. Hits real third-party services.
  • sk_test_*** — sandbox. Free. Hits sandbox endpoints (e.g., DataForSEO sandbox) where available; otherwise mocked. State persists per test key.

Using live keys

curl -X POST https://api.citationbench.com/v1/research/keyword \
  -H "Authorization: Bearer sk_live_***" \
  -H "Content-Type: application/json" \
  -d '{ "seed": "project management software", "limit": 50 }'
# MCP
claude mcp add citationbench https://mcp.citationbench.com/mcp \
  --header "Authorization: Bearer sk_live_***" \
  --header "X-Workspace-Id: ws_***"

Key scope

A key is one of two scopes:

  • Workspace-scoped (default): bound to one workspace. The X-Workspace-Id header is ignored.
  • Agency master: can act on any sub-workspace the agency owns. You must pass X-Workspace-Id: ws_*** on every request, or use the workspaces.bulk_action endpoint.

Rotation and revocation

# List
curl -H "Authorization: Bearer sk_live_***" \
  https://api.citationbench.com/v1/auth/keys

# Create a new one
curl -X POST -H "Authorization: Bearer sk_live_***" \
  https://api.citationbench.com/v1/auth/keys \
  -d '{ "name": "ci-bot", "scope": "WORKSPACE", "workspaceId": "ws_***" }'

# Revoke
curl -X DELETE -H "Authorization: Bearer sk_live_***" \
  https://api.citationbench.com/v1/auth/keys/akey_***

Revocation is immediate. In-flight invocations using the revoked key continue to completion; new calls are rejected with 401.

Workspace scoping

You haveHeader to sendNotes
Workspace-scoped sk_live_***none neededThe key knows its workspace
Workspace-scoped sk_test_***none neededSame
Agency master sk_live_***X-Workspace-Id: ws_***Required on every per-workspace call
Agency master targeting many at oncenoneUse POST /v1/workspaces/bulk-action

Errors

StatusCodeCause
401unauthorizedMissing or invalid Authorization header on an endpoint that does not allow demo mode
401key_revokedKey has been revoked
401key_expiredKey reached its expiresAt
403workspace_forbiddenKey can't act on the requested X-Workspace-Id
403agency_key_requiredEndpoint requires an agency master key

A note on safety

A small set of write endpoints — anything that touches external accounts on behalf of a real user (publishing to a connected CMS, sending real outreach emails, submitting URLs to Google) — do not respond in demo mode. They require a live key. An agent can still inspect their shape via GET /v1/agent/skills/{slug} and the inventory.

On this page