Welcome to the CompetLab API documentation. This API provides programmatic access to your competitive intelligence data — technology stacks, content strategy, messaging & positioning, pricing plans, AI brand visibility across ChatGPT, Claude, Gemini, Perplexity, and Google AI Overviews, and — for Perplexity and Google AI Overviews — the pages they read when they answer your buyers' questions.
Who is this for?
- Developers building integrations with internal tools, CRMs, or BI platforms
- Agencies building whitelabel competitive dashboards for their clients
- AI agents and MCP servers consuming structured competitive data
- Automation platforms (Zapier, n8n) monitoring competitor changes
Authentication
All endpoints require a CL-API-Key header. Generate your API key in the CompetLab app under Your Organization → Settings → API Keys.
CL-API-Key: cl_live_a1b2c3d4e5f6...
Keys are organization-scoped — one key accesses all projects in your organization. Two permission scopes exist: read reads everything, and read_write reads everything and also writes. Today the Strategic Tickets endpoints are the ones that write; a read key lists and reads them like anything else, and is refused on every endpoint that writes with 403 insufficient_scope. Scope is fixed when a key is made — to change it, revoke the key and create another.
To manage your keys (create, revoke, set expiration): Your Organization → Settings → API Keys.
Response Format
Every response follows one of three shapes:
Single resource:
{ "item": { "id": "...", "name": "..." } }
Collection (with optional pagination):
{ "items": [...], "pagination": { "page": 1, "limit": 20, "total": 47, "totalPages": 3, "hasMore": true } }
Error:
{ "error": { "code": "project_not_found", "message": "Project not found", "status": 404 } }
Pagination uses ?page=1&limit=20 (1-indexed, default 20, max 100).
Error Codes
All errors return a machine-readable code field for programmatic handling:
| Code | Status | Description |
|---|---|---|
api_key_missing | 401 | No CL-API-Key header provided |
api_key_invalid | 401 | Key not found or malformed |
api_key_revoked | 401 | Key has been revoked |
api_key_expired | 401 | Key has expired |
insufficient_scope | 403 | Key doesn't have the required permission scope |
subscription_required | 402 | The organization has no plan, and this call fetches or scans a site on CompetLab's side |
project_not_found | 404 | Project doesn't exist or doesn't belong to your organization |
no_data_available | 404 | No monitoring data available yet for this dimension |
not_found | 404 | Requested resource not found |
invalid_parameters | 400 | Invalid query parameters or request format |
rate_limit_exceeded | 429 | Rate limit exceeded for this API key |
internal_error | 500 | Unexpected server error — retry or contact support |
bad_gateway | 502 | Upstream service returned an invalid response — retry with backoff |
service_unavailable | 503 | Service temporarily unavailable — retry with backoff |
gateway_timeout | 504 | Upstream service timed out — retry with backoff |
Note on 5xx responses: The message field for 5xx errors is a static string ("Internal server error"). Branch on code for programmatic handling — do not pattern-match on message for 5xx.
Monitoring Dimensions
CompetLab monitors six dimensions of competitive intelligence:
| Dimension | Route | What it monitors |
|---|---|---|
| Tech & Trust Profile | /tech-trust | Technology stack, security headers, trust signals, DNS, robots.txt |
| Content Intelligence | /content | Sitemap structure, URL volume, content categories, URL changes |
| Positioning | /positioning | What each company says on its homepage as the page says it, what you say that nobody else does, what changed, and what pages say about you |
| Pricing Intelligence | /pricing | What each company charges as its pricing page shows it, what typical setups cost cheapest first and where you stand, what changed, and what pages say about you |
| AI Visibility | /ai-visibility | Which companies ChatGPT, Claude, Gemini, Perplexity and Google AI Overviews recommend in your category — the market map — and where you stand among them |
| AI Sources | /ai-sources | The pages Perplexity and Google AI Overviews read when they answer your buyers' questions, and whether you are on them — per engine, never pooled |
Each dimension has a dashboard (latest monitoring data), a history (paginated past runs) and a run detail (full data for one past run — a check detail on AI Visibility and AI Sources). AI Visibility adds a trend (how the market the models draw moved over a window), and Content a changelog (URL changes over time).
Strategic Briefing
Beyond the raw per-dimension data, /strategic-briefing returns the latest synthesized competitive briefing — the as-of read of what changed and what it means, with an executive hub, deep-dives and a competitor dossier. What it recommends doing is not a section of it: the briefing opens those recommendations as tickets on the project's board (/tickets, below), and each edition reports what it did to the board: the tickets it opened and where they now sit, the comments it wrote on tickets already there, and the tickets it found already on the board. It synthesizes a broader analytical set than the monitored dashboards it reads — all six above, plus eight it researches for the briefing alone: landscape, funding, hiring/GTM, product launches and more. It is lean by default (request only the sections you need — it defaults to the hub, which doubles as the navigation map) and always carries methodology coverage caveats. See the endpoint for the full sections list.
Strategic Tickets
/tickets is the project's board — the work your team has decided to do about its competitors, with an assignee, a column and a thread. It is the one part of this API you can write to, and it reads and writes the same tickets the team sees in the app: five fixed columns (triage, todo, in_progress, done, dismissed), a Markdown description and thread, the project's own coloured labels, an assignee, a due date, effort and impact.
Reading needs any key. Creating, updating, moving, commenting and deleting need a read_write key, and everything written through this API is recorded as written by a key rather than by a person. A key reads everything its organization has and works its Strategic Tickets board on any plan and after one ends; the calls that fetch or scan a site on CompetLab's side need a plan — without one they answer 402 with the code subscription_required.
A move names neighbours rather than an index — the ticket you want this one to sit below, and the one you want it to sit above — or the top or the bottom of the column (position), so two clients reordering at the same time converge on one order instead of overwriting each other, and a stale view of the board never turns into an error. The answer says where the ticket landed (placement).
Quick Start
Step 1 — Get your API key from Your Organization → Settings → API Keys in the CompetLab app
Step 2 — List your projects:
curl -H "CL-API-Key: cl_live_your_key_here" https://api.competlab.com/v1/projects
Step 3 — Get the latest pricing intelligence:
curl -H "CL-API-Key: cl_live_your_key_here" https://api.competlab.com/v1/projects/{projectId}/pricing
Additional Resources
- OpenAPI JSON Spec — Machine-readable API definition for code generators and integrations
- API Key Management — Your Organization → Settings → API Keys in the CompetLab app
Rate Limits
The Strategic Tickets endpoints and the free tools allow 1,000 requests per minute per API key — except /tools/fetch-url, which allows 60 per minute. Past the limit they answer 429 with the code rate_limit_exceeded, and the limit resets within a minute. The other endpoints are not rate limited today — we recommend keeping them under 60 requests per minute.
Authentication: send your CompetLab API key as the CL-API-Key header (keys start with cl_live_, issued at app.competlab.com → Organization Settings → API Keys). The competitive-intelligence data is read-only. Strategic Tickets can also be written, with a read_write key (a read key is refused with 403 insufficient_scope). A key reads everything its organization has and works its Strategic Tickets board on any plan and after one ends; the calls that fetch or scan a site on CompetLab's side need a plan (402 subscription_required without one). The on-demand site-audit tools use POST: three start a scan you then read with GET; the sitemap, AI-crawler and fetch-URL tools answer in the same call.
Endpoints
Every endpoint the live contract declares (54 in total). Parameters and response shapes for each are in the interactive explorer below, and in the machine-readable spec.
| Method | Endpoint | What it does |
|---|---|---|
GET | /v1/health | Check API health |
GET | /v1/projects | List all projects |
GET | /v1/projects/{projectId} | Get project details |
GET | /v1/projects/{projectId}/competitors | List project competitors |
GET | /v1/projects/{projectId}/competitors/{competitorId} | Get competitor details |
GET | /v1/projects/{projectId}/tech-trust | Get latest tech & trust data |
GET | /v1/projects/{projectId}/tech-trust/history | Get tech & trust run history |
GET | /v1/projects/{projectId}/tech-trust/history/{runId} | Get tech & trust data for a specific run |
GET | /v1/projects/{projectId}/content | Get latest content intelligence data |
GET | /v1/projects/{projectId}/content/history | Get content intelligence run history |
GET | /v1/projects/{projectId}/content/history/{runId} | Get content intelligence data for a specific run |
GET | /v1/projects/{projectId}/content/changelog | Get content changelog |
GET | /v1/projects/{projectId}/positioning | Get the latest positioning check |
GET | /v1/projects/{projectId}/positioning/history | Get the positioning check history, with what each check found changed |
GET | /v1/projects/{projectId}/positioning/history/{runId} | Get one past positioning check |
GET | /v1/projects/{projectId}/pricing | Get the latest pricing check |
GET | /v1/projects/{projectId}/pricing/history | Get the pricing check history, with what each check found changed |
GET | /v1/projects/{projectId}/pricing/history/{runId} | Get one past pricing check |
GET | /v1/projects/{projectId}/ai-visibility | Get latest AI visibility data |
GET | /v1/projects/{projectId}/ai-visibility/history | Get AI visibility check history |
GET | /v1/projects/{projectId}/ai-visibility/history/{checkId} | Get AI visibility data for a specific check |
GET | /v1/projects/{projectId}/ai-visibility/trend | Get how the market the AI models draw has moved |
GET | /v1/projects/{projectId}/ai-sources | Get latest AI sources data |
GET | /v1/projects/{projectId}/ai-sources/history | Get AI sources check history |
GET | /v1/projects/{projectId}/ai-sources/history/{checkId} | Get AI sources data for a specific check |
GET | /v1/projects/{projectId}/alerts | List project alerts |
GET | /v1/projects/{projectId}/schedules | List monitoring schedules |
GET | /v1/projects/{projectId}/strategic-briefing | Get the current state of this project's strategic briefing |
GET | /v1/projects/{projectId}/strategic-briefing/history | List this project's briefing editions |
GET | /v1/projects/{projectId}/strategic-briefing/history/{runId} | Get one briefing edition by id |
GET | /v1/projects/{projectId}/tickets/labels | List the project's ticket labels |
POST | /v1/projects/{projectId}/tickets/labels | Create a ticket label |
PATCH | /v1/projects/{projectId}/tickets/labels/{labelId} | Rename or recolour a ticket label |
DELETE | /v1/projects/{projectId}/tickets/labels/{labelId} | Delete a ticket label |
GET | /v1/projects/{projectId}/tickets/assignees | List the people a ticket can be assigned to |
GET | /v1/projects/{projectId}/tickets | List project tickets |
POST | /v1/projects/{projectId}/tickets | Create a ticket |
GET | /v1/projects/{projectId}/tickets/{ticketId} | Get a ticket |
PATCH | /v1/projects/{projectId}/tickets/{ticketId} | Update a ticket |
DELETE | /v1/projects/{projectId}/tickets/{ticketId} | Delete a ticket |
PATCH | /v1/projects/{projectId}/tickets/{ticketId}/move | Move a ticket |
GET | /v1/projects/{projectId}/tickets/{ticketId}/comments | List a ticket's comments |
POST | /v1/projects/{projectId}/tickets/{ticketId}/comments | Add a ticket comment |
PATCH | /v1/projects/{projectId}/tickets/{ticketId}/comments/{commentId} | Edit a ticket comment |
DELETE | /v1/projects/{projectId}/tickets/{ticketId}/comments/{commentId} | Delete a ticket comment |
POST | /v1/tools/tech-stack/scans | Start an async tech-stack scan |
GET | /v1/tools/tech-stack/scans/{scanId} | Get an async tech-stack scan by ID |
POST | /v1/tools/trust-signals/scans | Start an async trust-signals scan |
GET | /v1/tools/trust-signals/scans/{scanId} | Get an async trust-signals scan by ID |
POST | /v1/tools/ai-crawler-checker | Check AI crawler accessibility for a domain |
POST | /v1/tools/sitemap-visualizer | Analyze sitemap structure of a domain |
POST | /v1/tools/agent-adoption/scans | Start an async agent-adoption scan |
GET | /v1/tools/agent-adoption/scans/{scanId} | Get an async agent-adoption scan by ID |
POST | /v1/tools/fetch-url | Fetch URL body and headers with JS-rendering + bot-protection handling |
Errors
Errors return a JSON body describing the failure (an error object with a machine-readable code, a message and the HTTP status). Standard HTTP status codes apply: 400 (invalid parameters), 401 (missing/invalid API key), 402 (no plan, on a call that fetches or scans a site on CompetLab's side), 403 (key lacks the read_write scope a write needs), 404 (not found), 429 (rate limited).