Skip to main content

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

GET /leads
Scope: leads:read

Query parameters

ParamTypeNotes
limit, offset, sortOrder, querySee Pagination. query matches first name, last name, email, company, and phone digits.
sortBystringOne of createdAt, firstName, email, company, status, source, estimatedValue.
statusenumFilter by LeadStatus.
sourceenumFilter 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

POST /leads
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

GET /leads/{leadId}
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

PUT /leads/{leadId}
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

DELETE /leads/{leadId}
Scope: leads:write.

Response 200

{ "deleted": true, "id": "lead_..." }

Webhook side effects

A lead.deleted event is dispatched.

Search a lead

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

Query parameters

At least one of these is required:
ParamDescription
emailExact match (normalized to lowercase).
phoneMatches against the digit-only form of stored phones (so +1 (809) 555-1234 matches 8095551234).
qFuzzy match on first/last name, email, company.
limit1..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

ParamNotes
limit1..100, default 20.
offsetDefault 0.
typeFilter by LeadActivityType.
activityScopeFilter 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"
}
FieldRequiredNotes
typeyesOne of call, email, meeting, social_message.
directionyesinbound or outbound.
contentnoFree 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.