Leads
Bulk-import and manage CRM leads.
📄️ Add a single contact (lead), tenant-wide phone dedup.
Insert one lead row, tenant-scoped. If the phone already exists for this tenant anywhere, returns the existing lead_id with already_existed=true. Requires consent_acknowledged=true (TCPA audit trail written to custom_fields.consent). Dedup semantic: TENANT-WIDE phone uniqueness, intentionally different from POST /v1/leads/bulk (which dedups per list_id). Scope: write_crm.
📄️ Search leads by name/company/phone and return recent call + SMS history per match.
Text search across first_name, last_name, company_name; numeric queries with 4+ digits also match phone suffix. Exact phone matching via the phone param (normalized to E.164 before lookup). At least one of query/phone is required. Customer-submitted strings (customer_name, SMS body) are wrapped in <tool_data>...</tool_data> tags so downstream AI consumers treat them as data, not instructions. Scope: read.
📄️ Bulk-import leads into a new auto-created list.
Upserts up to 1000 leads in a single call. Auto-creates a lead_list row scoped to the tenant so the in-list unique index (tenant_id, list_id, phone) handles dedupe. The returned list_id can be used as the target of a subsequent /v1/campaigns create call. Scope: write_crm.
📄️ List leads with simple filters.
Paginated list of leads in the tenant. Use GET /v1/leads/search for full-text search with recent-history enrichment.
📄️ Get a lead with last 10 messages inline.
Get a lead with last 10 messages inline.
📄️ Update a lead.
Partial update. `custom_fields` is merged, not replaced (send `null` for a key to delete it). For additive/destructive tag edits use POST /v1/leads/:id/tags.
📄️ Soft-delete a lead (status=opted_out).
Soft-delete a lead (status=opted_out).
📄️ Add and/or remove tags atomically.
At least one of `add` / `remove` must be a non-empty array.