Authentication
How it works
Every request carries your API key in a CL-API-Key header. The key identifies your
organization, and the API returns only that organization’s data. There’s no session and no
login round-trip — the key travels with each call, so a request is only ever as authorized
as the key you send.
curl https://api.competlab.com/v1/projects \
-H "CL-API-Key: YOUR_COMPETLAB_API_KEY"Create an API key
Keys are managed in the CompetLab dashboard under Settings → API Keys. You’ll need the Owner or Admin role, and each organization can hold up to five active keys.
When you create a key, copy it immediately — the full key is shown once and can’t be retrieved later (only a short hint is stored for display). If you lose it, revoke it and create a new one.
Key format
A key is the prefix cl_live_ followed by 32 hexadecimal characters — 40 characters
total:
cl_live_0123456789abcdef0123456789abcdefThe API validates this shape before anything else, so a malformed key is rejected
immediately with a 401.
Scopes
Keys can be created with a read or read_write scope. Scope is fixed when the key is made.
| Scope | What it can do |
|---|---|
read | Every read: projects, dashboards, history, the Strategic Briefing, and listing and reading Strategic Tickets. Also the free scan tools, which are stateless POSTs that don’t modify your data. |
read_write | Everything a read key can, plus the writes on the Strategic Tickets board: create, update, move and delete tickets, write and edit comments, and manage labels. |
A read key that calls a route that writes is refused with 403 insufficient_scope. To write,
create a read_write key. Nothing else in the API writes — projects, competitors, alerts,
schedules and settings are read-only over the API.
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, and
without one they return 402 subscription_required, whatever the key’s scope. A ticket or
comment written through a key is recorded as written by an API key, not by a person.
Errors
Authentication failures return 401 with the standard { error } envelope:
code | Meaning |
|---|---|
api_key_missing | No CL-API-Key header on the request. |
api_key_invalid | The key is malformed or not recognized — the wrong shape (cl_live_ + 32 hex = 40 characters), or a well-formed key that doesn’t match an active key. |
api_key_revoked | The key was revoked in the dashboard. |
api_key_expired | The key has passed its expiry. |
{ "error": { "code": "api_key_invalid", "message": "Invalid API key", "status": 401 } }A valid key can still be refused: 403 insufficient_scope when a read key calls a Strategic
Tickets route that writes, and 402 subscription_required when a free-tool call fetches or scans
a site on CompetLab’s side and the organization has no plan.
Keep your key safe
- Treat a key like a password: don’t commit it, don’t paste it into shared chats, and rotate it if it leaks.
- Store it in a secret manager or an environment variable, not in source.
- Revoke unused keys — you get five active per organization, so retire the ones you don’t need.
Building for an AI agent instead of your own backend? The MCP server uses
the same key and additionally accepts it as a ?api_key= URL parameter for clients that
can’t send custom headers. For the REST API, always use the CL-API-Key header.
FAQ
Where do I get a CompetLab API key?
In the CompetLab dashboard under Settings → API Keys. You need the Owner or Admin role, and each organization can hold up to five active keys. The full key is shown once when you create it — copy it then, because only a short hint is stored afterward. If you lose a key, revoke it and create a new one.
What does a valid key look like?
It's the prefix cl_live_ followed by 32 hexadecimal characters — 40 characters in total. The API validates the shape first, so a key of the wrong length or prefix is rejected immediately; a well-formed key that isn't recognized (a typo, or a key rotated at the source) also comes back as 401 api_key_invalid. All of this happens before the request reaches your data.
Do the read and read_write scopes limit what a key can do?
Yes, on the routes that write. A read key can call every read in the API — including listing and reading Strategic Tickets — and the free scan tools. Writing to the Strategic Tickets board (creating, updating, moving or deleting a ticket, writing or editing a comment, managing labels) needs a read_write key; a read key is refused there with 403 insufficient_scope. Scope is fixed when the key is made, so to write, create a read_write key. The board works on any plan and after one ends. The free scan tools fetch or scan a site on CompetLab's side, so they need a plan and return 402 subscription_required without one. Nothing else in the API writes.
How do I authenticate the MCP server?
With the same CompetLab API key. The MCP server accepts it as a CL-API-Key header or, for clients that can't send custom headers like Claude on the web, as a ?api_key= URL parameter. The REST API itself uses the header only. See the MCP Connect guide for per-client setup.