Leads and lists
Leads and companies, CSV imports, enrichment, research, and saved lists and segments.
Leads
A lead is a person you may contact. Fields include first_name, last_name, title, email, phone (E.164), linkedin_url, timezone, language, company_id, owner_id, phone_type, status, source and custom_fields.
- One live lead per email per workspace. Creating a second one answers
409with the existing lead's id (existing_id). Deleted leads are soft-deleted and free their email. - Status is one of
new,contacted,replied,qualified,meeting_bookedordisqualified. Each status change adds astatus_changeevent to the lead's timeline. - References are checked: a company or owner must belong to the same workspace.
- Timeline:
GET /api/v1/leads/{lead_id}/timelinelists everything that happened to a lead: emails, replies, calls, notes, status changes and imports.
Companies (/api/v1/companies) group leads; signals and research attach to them.
CSV imports
Imports run in three steps: upload → preview → commit.
POST /api/v1/imports/leadsuploads the file. It is parsed and stored until you commit.- Check the preview and the column mapping.
POST /api/v1/imports/{import_id}/commitimports the rows in batches.
Each row is deduplicated against live leads on its strongest identifier: email (case-insensitive), else LinkedIn URL, else phone.
- With
skip, existing leads are left alone. - With
update_empty_fields, only their empty fields are filled. - A second row for the same person in the file is skipped as
duplicate_in_file. - Rows that match a suppression are imported but listed as
suppressed, so they stay uncontactable. Useskip_suppressedto leave them out. - A row that hits a conflict is reported per row (
errororconflict). If the import fails, batches already committed stay.
Opt-in extras at commit time, when the server has them configured:
"enrich": truequeues enrichment for the imported leads."research": truequeues AI research for them.
Both are capped per import to protect free-tier credits.
Enrichment
POST /api/v1/leads/{lead_id}/enrich fills a lead's empty fields from the configured data providers, trying them in order and stopping at the first hit for each group of fields. It never overwrites a field you set. Results are cached per workspace, every call is counted in the credits ledger, and GET /api/v1/enrichment/usage shows the usage. When the server runs enrichment in the background, the route answers 202 and the result lands on the lead and its timeline.
Research
AI research reads a lead's company website and other public sources and stores a brief with cited facts. Run it for one lead, or queue a research batch for many leads, many companies, or the companies accepted from a discovery run (POST /api/v1/research/batches).
Batches have budgets:
- a maximum number of items per batch, per workspace per day, and of batches running at once;
- per-run caps on AI and search calls.
When a daily budget or an AI quota runs out, the batch pauses until its resume_at time; it never retries in a loop. Every claim in a result must cite a fetched source; uncited claims are dropped.
Lists and segments
Saved lead lists (/api/v1/lists) come in two kinds:
| Kind | Members |
|---|---|
static | Hand-picked leads: add and remove them with POST /lists/{list_id}/members and .../members/remove. |
segment | Saved lead filters. Members are computed from the filters each time you read them. |
Deleting a list keeps its leads. A list can be the source of a campaign: POST /api/v1/lists/{list_id}/enroll enrolls its members into a sequence (needs sequences:write with an API key). Lists use the leads:* scopes.