Skip to main content
Every request to /api/v1 is authenticated by an API key, not by a signed-in session. There is no cookie or bearer session token that works here.
Where
SettingsAPI & Integrations
Your role needs
Update access to Lead intake API update-companies. Admin have it by default.
Authenticated by a workspace API key, not by a signed-in session. Creating a key needs the same permission as the rest of the API settings tab.

Sending the key

Send the key as a bearer token:
If your HTTP client reserves the Authorization header, send the same value in X-API-Key instead. The middleware checks Authorization: Bearer first and falls back to X-API-Key only when that header is absent.

Key anatomy

A key looks like plk_live_a1B2c3D4_kQ7mZ2xA9f3...: a prefix, then an underscore, then a secret. The prefix is everything before the last underscore in the token; the prefix itself contains underscores, so splitting on the first one would cut it short. The product only ever shows you a masked form of a key it already issued: the prefix, an ellipsis, then the last four characters of the secret. For example, plk_live_a1B2c3D4…9f3k. Those four characters are the tail of the real secret, not part of the prefix.

Scopes

A key carries one or more scopes, and every route on /api/v1 needs a specific one except GET /me, which only needs a valid key. A key needs at least one scope; there is no way to create or save one with none ticked. Scopes are enforced per route, not per group, so adding a new read endpoint later can never accidentally inherit write permission from an existing key.

What each 401 means

AuthenticateApiKey returns 401 for every problem with the credential itself: a missing key, a malformed token, an unknown prefix, a revoked key and an expired key. All of these produce the same generic body:
That single message stands in for all five causes deliberately: telling a caller which of those it hit would let a script probe for keys that exist. The trigger is any malformed or unknown key: no underscore in the token, a leading or trailing underscore, a prefix that doesn’t start plk_, a prefix over 40 characters, or a prefix that doesn’t match a stored key. One case gets its own message. If the teammate who created the key has since been deleted from the workspace, the key is orphaned (there’s no one left for it to act as) and the body reads:
Both bodies carry the documentation_url above, pointing back at this page. It’s what a 401 in a script or a log line links to. Removing someone from the workspace does not orphan their keys on its own; their account still exists elsewhere, so their keys keep working until someone deliberately revokes them.

The 403: missing scope

A key that authenticates but lacks the scope a route needs gets a 403, not a 401. The credential is valid, it’s just missing a capability:
There is no control in the product to add a scope to an existing key, and rolling a key carries its scopes across unchanged rather than letting you edit them. The fix is a new key created with the scope you need.

Create, roll and revoke API keys

Where keys are created, how to see one’s scopes, and how to roll or revoke it.

API overview

What the public API is for and what it can do.

Errors reference

Every status the API returns and what to change before retrying.