Skip to main content
The lead is the central resource of FlowEstate. Every endpoint on this page operates inside the calling organization’s tenant — you cannot read or write leads from another organization with the same key.

List leads

Scope: leads:read

Query parameters

Response 200


Create a lead

Scope: leads:write At least one of email or phone is required. Empty strings are treated as missing.

Request body

Source field semantics. FlowEstate accepts any string for source. Known LeadSource values are stored as-is. Unknown values are stored as other on the enum column, with the original string preserved in sourceMetadata.providedSource. This lets you keep your own UTM/campaign mapping without losing data.

Round robin distribution

POST /leads runs the round robin end to end in a single call — it creates the lead, assigns it through a pool’s rotation, and emits lead.assigned so your downstream automation (for example, an agent WhatsApp notification) fires. No universal lead webhook or middleware bridge is required. When the lead has no owner, assignment is resolved in this order:
  1. assignedToId — assigned directly to that member.
  2. roundRobinId — assigned through that pool. The target is explicit, so it is honored even if the pool has no connections, and the pool’s assignInboundLeads / assignManualLeads flags are bypassed.
  3. Neither — generic auto-assignment: the lead is routed to an active pool with assignInboundLeads enabled. A pool with no connections acts as the catch-all “generic inbound” pool, so you can distribute API leads without configuring any webhook connection.
If no pool matches — or the matched pool has no eligible participant — the lead is created unassigned. Assignment is best-effort: it never fails lead creation.

Response 201

assignedToId is the assigned member (or null if the lead was left unassigned). roundRobinId is the pool the lead was assigned through (null for an explicit assignedToId or when no assignment happened).

Common errors

  • 400 VALIDATION_ERROR — invalid email, both email and phone missing, or assignedToId is not a member of this organization (validated before the lead is created).
  • 403 FORBIDDEN — plan limit reached. Message identifies the limit.

Webhook side effects

  • Always: lead.created (dispatched with X-FlowEstate-Source: api).
  • If the lead is assigned (via assignedToId, roundRobinId, or generic auto-assignment): lead.assigned. Its autoAssigned flag is true when the round robin picked the participant and false for an explicit assignedToId, so you can distinguish the two downstream.

Get a lead

Scope: leads:read. Returns the same shape as a list item. 404 NOT_FOUND if the lead doesn’t exist or belongs to another org.

Update a lead

Scope: leads:write. Same body as create, all fields optional. Must provide at least one field. The contact-identity rule (email or phone) still applies after the merge. Pass null to clear a field; omit it to leave it untouched.

Webhook side effects

  • Always: lead.updated.
  • If stageId changed: lead.stage_changed.
  • If status changed to won: lead.won. To lost: lead.lost.
  • If assignedToId changed: lead.assigned (when set) or lead.unassigned (when cleared).

Delete a lead

Scope: leads:write.

Response 200

Webhook side effects

A lead.deleted event is dispatched.

Search a lead

Scope: leads:read. Designed for Zapier / Make “Find Lead” steps.

Query parameters

At least one of these is required:

Response 200


List activities

Scope: leads:read. Lists timeline activities (notes, calls, emails, meetings, system events).

Query parameters

Response 200


Add a note

Scope: leads:write.

Request body

content is required, 1..5000 chars.

Response 201

Webhook side effects

A lead.note_added event is dispatched.

Log a communication

Scope: leads:write. Records a phone call, email, meeting, or social-media message against the lead’s timeline.

Request body

Response 201

Webhook side effects

A lead.communication_logged event is dispatched.