REST API
Use Pendium's REST API directly with curl, fetch, or any HTTP client — no MCP required.
When to use the REST API
The MCP server is the recommended way to connect AI agents to Pendium — it handles tool discovery, parameter validation, and structured responses automatically.
But if you're building a custom integration, scripting with curl, or working in an environment that doesn't support MCP, the REST API gives you direct HTTP access to the same data.
Base URLs:
Authentication
Pass your API key in the x-api-key header:
Or, for HTTP clients that only support bearer auth (Databricks Unity Catalog, Bruno, Insomnia, n8n), use Authorization: Bearer:
No key? Most endpoints return a 401 with instructions on how to sign up. The score lookup endpoint works without authentication.
An account in read-only mode can read its data through the API but can't trigger writes or spend — write/scan endpoints return a 403 (code: "READ_ONLY"); read endpoints (polling, reports, lookups) work normally. A free-plan API key can't trigger scans at all: POST /api/visibility/scan returns a 403 with code: "PLAN_UPGRADE_REQUIRED". A paid key rescanning a group-shared brand whose owner is on the free plan gets a 403 with code: "OWNER_PLAN_UPGRADE_REQUIRED" until the owner upgrades; polling that brand's existing scans still works. Separately, during a platform upgrade we may briefly pause all new scans: POST /api/visibility/scan then returns 503 (code: "SCANS_PAUSED") while polling and reports keep working.
See Authentication for full details.
Endpoints at a glance
Scanning and reports
| Method | Endpoint | What it does |
|---|---|---|
POST | /api/visibility/scan | Trigger a new visibility scan for a brand |
GET | /api/visibility/scan | Check if a scan is done and get progress |
GET | /api/visibility/report | Get the full visibility report with raw LLM responses |
POST | /api/visibility/scan-preview | Trigger a fast, shareable Visibility Scan Preview (slug-canonical, perfect for outreach links) |
GET | /api/visibility/scan-preview | Read the structured Visibility Scan Preview — both scores, analysis, personas, prompts |
A scan only creates a public Brand Index page when you trigger it with publishToBrandIndex: true. Once a brand has a page, it shows the newest scan.
Scans report transient failures honestly: if a run can't reach any AI engine (a temporary hiccup), it comes back with scanFailed: true (when polling the latest completed scan) or success: false (in a webhook callback, which is scoped to the run that just finished) and a 0 score — so you never mistake a transient zero for a real result. The same honesty applies per platform: any platformScores entry the scan didn't query comes back with queried: false and a null score, not a 0. Which platforms a scan queries, and its query cap, follow the brand owner's plan rather than the calling key's; see Platforms by plan.
Site content
| Method | Endpoint | What it does |
|---|---|---|
GET | /api/v1/site/export | Read a brand's published pages, posts, profile, and business details in one call |
The site export is a versioned contract for your own renderer, so its responses carry an ETag and no _pendium block. Use your own front end walks through a site built on it.
Brand data
| Method | Endpoint | What it does |
|---|---|---|
GET | /api/visibility/account | See your plan, credits, and all your brand agents |
GET | /api/visibility/score | Look up any brand's public visibility score (no auth needed) |
Topics and personas
| Method | Endpoint | What it does |
|---|---|---|
GET | /api/visibility/topics | List all topics and search queries for a brand |
POST | /api/visibility/topics | Add new topics with search queries |
GET | /api/visibility/personas | List buyer personas used in scans |
POST | /api/visibility/personas | Create a new persona (AI-generated or manual) |
Response format
Every Visibility API response includes a _pendium object with context about what you're looking at and what to do next. This is designed for both humans reading JSON and AI agents parsing responses.
Rate limits
- Authenticated: 60 requests/minute, plus a shared 5/minute for
POSTtoscan,scan-preview,topics, andpersonas - Unauthenticated: 15 requests/minute (keyless
POSTs toscan,topics, andpersonascount against the same 15)
Limits are counted per server instance, so they're approximate.
See Rate Limiting for details.