Documentation Index
Fetch the complete documentation index at: https://developers.flowestate.app/llms.txt
Use this file to discover all available pages before exploring further.
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
| Param | Type | Notes |
|---|
limit, offset, sortOrder, query | — | See Pagination. query matches first name, last name, email, company, and phone digits. |
sortBy | string | One of createdAt, firstName, email, company, status, source, estimatedValue. |
status | enum | Filter by LeadStatus. |
source | enum | Filter by LeadSource. |
Response 200
{
"data": [
{
"id": "lead_...",
"firstName": "Ada",
"lastName": "Lovelace",
"email": "ada@example.com",
"phone": "+18095551234",
"company": "Analytical Engines",
"jobTitle": "CTO",
"status": "new",
"source": "website",
"stageId": null,
"stageName": null,
"estimatedValue": null,
"score": null,
"temperature": null,
"notes": null,
"city": null,
"state": null,
"country": "DO",
"projectId": null,
"projectName": null,
"unitId": null,
"assignedToId": null,
"assignedTo": null,
"customFields": null,
"createdAt": "2026-04-29T18:04:15.000Z",
"updatedAt": "2026-04-29T18:04:15.000Z"
}
],
"pagination": { "total": 327, "limit": 50, "offset": 0, "hasMore": true }
}
Create a lead
Scope: leads:write
At least one of email or phone is required. Empty strings are treated as missing.
Request body
{
"firstName": "Ada",
"lastName": "Lovelace",
"email": "ada@example.com",
"phone": "+18095551234",
"company": "Analytical Engines",
"jobTitle": "CTO",
"status": "new",
"source": "meta",
"stageId": "uuid-or-omitted",
"estimatedValue": 250000,
"score": 80,
"temperature": "hot",
"notes": "Came from Lookalike audience",
"city": "Punta Cana",
"state": "La Altagracia",
"country": "DO",
"projectId": "uuid-or-omitted",
"unitId": "uuid-or-omitted",
"customFields": {
"campaignName": "Q3-launch",
"leadId": "2442330062872321"
}
}
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.
Response 201
{
"id": "lead_...",
"firstName": "Ada",
"lastName": "Lovelace",
"email": "ada@example.com",
"phone": "+18095551234",
"company": "Analytical Engines",
"status": "new",
"source": "meta",
"createdAt": "2026-04-29T18:04:15.000Z",
"updatedAt": "2026-04-29T18:04:15.000Z"
}
Common errors
400 VALIDATION_ERROR — invalid email, or both email and phone missing.
403 FORBIDDEN — plan limit reached. Message identifies the limit.
Webhook side effects
A lead.created event is dispatched with X-FlowEstate-Source: api.
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
{ "deleted": true, "id": "lead_..." }
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:
| Param | Description |
|---|
email | Exact match (normalized to lowercase). |
phone | Matches against the digit-only form of stored phones (so +1 (809) 555-1234 matches 8095551234). |
q | Fuzzy match on first/last name, email, company. |
limit | 1..50, default 10. |
Response 200
{
"data": [
{
"id": "lead_...",
"firstName": "Ada",
"lastName": "Lovelace",
"email": "ada@example.com",
"phone": "+18095551234",
"company": "Analytical Engines",
"status": "new",
"source": "website",
"stageId": null,
"stageName": null,
"assignedTo": null,
"createdAt": "2026-04-29T18:04:15.000Z"
}
]
}
List activities
GET /leads/{leadId}/activities
Scope: leads:read. Lists timeline activities (notes, calls, emails, meetings, system events).
Query parameters
| Param | Notes |
|---|
limit | 1..100, default 20. |
offset | Default 0. |
type | Filter by LeadActivityType. |
activityScope | Filter by LeadActivityScope. Defaults to lead_event. |
Response 200
{
"data": [
{
"id": "act_...",
"leadId": "lead_...",
"type": "note",
"activityScope": "lead_event",
"content": "Called and left voicemail",
"changes": null,
"communicationType": null,
"communicationDirection": null,
"user": { "id": "user_...", "name": "...", "email": "...", "image": null },
"createdAt": "2026-04-29T18:04:15.000Z"
}
],
"pagination": { "total": 12, "limit": 20, "offset": 0, "hasMore": false }
}
Add a note
POST /leads/{leadId}/notes
Scope: leads:write.
Request body
{ "content": "Spoke today, very interested" }
content is required, 1..5000 chars.
Response 201
{
"id": "act_...",
"leadId": "lead_...",
"content": "Spoke today, very interested",
"createdAt": "2026-04-29T18:04:15.000Z"
}
Webhook side effects
A lead.note_added event is dispatched.
Log a communication
POST /leads/{leadId}/communications
Scope: leads:write. Records a phone call, email, meeting, or social-media message against the lead’s timeline.
Request body
{
"type": "call",
"direction": "outbound",
"content": "Discussed unit availability"
}
| Field | Required | Notes |
|---|
type | yes | One of call, email, meeting, social_message. |
direction | yes | inbound or outbound. |
content | no | Free text, ≤ 5000 chars. |
Response 201
{
"id": "act_...",
"leadId": "lead_...",
"type": "call",
"direction": "outbound",
"content": "Discussed unit availability",
"createdAt": "2026-04-29T18:04:15.000Z"
}
Webhook side effects
A lead.communication_logged event is dispatched.