Skip to main content
Three calls that only read: confirm your key and see its workspace, list this workspace’s tags, and read one lead back by id or email, including whether we have emailed them and whether they replied.
Where
Settings→API & 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.

The three endpoints

Every timestamp these three return is UTC ISO-8601 with microseconds: 2026-08-21T09:14:02.000000Z.

Status codes

GET /me

No scope is required for this one. Any key, whatever it’s scoped for, can call it. That makes it the fastest way to confirm a credential works before you build anything else on it, and the right endpoint to wire into your own monitoring as a health check.

Response

That example leaves out rate_limit to keep it short. It’s the two integer fields in the table above. See Idempotency, deduplication and rate limits for what they’re currently set to.

GET /tags

Returns every tag in the workspace the key belongs to, ordered by name. There’s no pagination on this list: by design, since a workspace has tens of tags, not thousands, so there’s nothing here worth adding a cursor for. By default only tags with active: true come back. Pass include_archived=true to also get the ones that have been archived.

Query parameters

Response

GET /leads/

Needs its own leads:read scope, separate from leads:write, which only guards the two POST routes. It is not a default scope: tick it when you create the key, or the call is a 403 insufficient_scope. {id} is either the numeric id from a create response or a URL-encoded email address (jane.doe%40acme.com). A LinkedIn profile URL or a phone number work too. It is resolved with the same precedence POST /leads deduplicates on (email, then LinkedIn, then phone, oldest match first), so the lead this returns for an address is exactly the one a POST with that address would have updated. A lead outside the key’s workspace returns the exact same 404 as an id or email that doesn’t exist anywhere:
404 Not Found
This endpoint can never confirm whether an id or address you don’t have access to exists. The response is identical either way, which also makes the 404 the signal an integration wants: this person is not in the workspace yet, so POST /leads will create rather than update them.

Response

The body is { data }, with no meta: there’s nothing to report about an action, since nothing changed. data is the same lead shape POST /leads returns in its own data field, plus two blocks the POST response does not carry: outreach and campaigns. Every relation is loaded on every call (emails, phones, links, location, tags, and the company’s own links and tags), so none of these fields is ever left out here for lacking an eager load.
This is deliberately not the shape the app’s own screens use internally: no admin-triage columns, CRM bookkeeping, possibility scores or phone-reveal state, and contacts come back as plain string arrays ("emails": ["jane@…"]) instead of objects. So an integration reads lead.emails[0] directly.
company, when present: outreach, which covers email only, since email is what this API feeds:
replied uses the same rule the app’s own dashboard and reply detection use: an out-of-office never counts as a reply, and a reply the classifier hasn’t looked at yet does. If this endpoint says replied: true, the campaign has stopped following up with that person.
Each entry in campaigns:

API overview

Authentication, scopes and what counts as a stable contract.

Lead fields reference

Every field POST /leads accepts, grouped and described one by one.

Status vocabularies

Every value stage, source and status can hold, and what each renders as.