REST API v1 · Resource
Sales CRM
Leads, notes, follow-up tasks and the pipeline.
API reference · Sales CRM
Endpoints
Paths are relative to https://fliok.com/api/v1. Each endpoint names the scope and the lowest key role it needs; a key without them gets 403 (see Authentication).
Every WhatsApp contact is a lead with a stage, an owner, a rating, a deal value and a timeline. The phone number is the lead’s identity, so POST /leads is safe to retry: a number you already have is recaptured (its timeline shows it came in again) instead of duplicated. Anywhere you pass a stage, lost reason or team member you can use its name or email instead of an id, and a lead can be addressed by its phone number. Reads need any key; writes need the agent role. Changes made through the API show on the lead’s timeline and fire the same automations and lead.* / task.* webhooks as changes made in the dashboard.
No code at all? Turn on Lead capture in Settings → Sales pipeline for a private URL that website forms, Zapier, Make, Pabbly and Google Sheets can POST leads to without an API key (/api/leads/capture/{token} — JSON, form or multipart).
Sales CRM
9- GET
/leadsList leads, page-numbered. Filter by view, a filter JSON or ?q=, sort by any sortable fieldScopecrm:read· viewer role or higherNeeds an API key - POST
/leadsAdd a lead. Idempotent by phone: a known number is recaptured, never duplicated. Stage and owner by name or emailScopecrm:write· agent role or higherNeeds an API key - GET
/leads/{id}One lead with stage, owner, deal value and custom fields — by our id or by phone numberScopecrm:read· viewer role or higherNeeds an API key - PATCH
/leads/{id}Move stage (with lost reason), reassign, rate, tag or edit fields. Lands on the lead’s timeline and fires automationsScopecrm:write· agent role or higherNeeds an API key - POST
/leads/{id}/notesAdd a note to a lead’s timeline — never sent to the customerScopecrm:write· agent role or higherNeeds an API key - GET
/tasksList follow-up tasks with counts per status (open, overdue, today, upcoming, done, cancelled)Scopecrm:read· viewer role or higherNeeds an API key - POST
/tasksCreate a follow-up on a lead; the assignee defaults to the lead’s ownerScopecrm:write· agent role or higherNeeds an API key - PATCH
/tasks/{id}Complete (with an outcome), cancel, reschedule or reassign a taskScopecrm:write· agent role or higherNeeds an API key - GET
/pipelineYour pipeline stages (kind initial, active, won or lost) and lost reasonsScopecrm:read· viewer role or higherNeeds an API key
Examples
Add a lead (or recapture one you already have)
curl -X POST https://fliok.com/api/v1/leads \
-H "Authorization: Bearer wa_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"phone": "+91 98765 43210",
"name": "Asha Rao",
"email": "asha@example.com",
"source": "Partner portal",
"stage": "Contacted",
"owner": "urvi@yourcompany.com",
"rating": 3,
"dealValue": 250000,
"tags": ["december"],
"attributes": { "city": "Udaipur" },
"note": "300 guests, wants a lake view"
}'// 201 Created (200 with "created": false when the number was already a lead)
{
"created": true,
"lead": {
"id": "4ca441d8-6a95-4b45-9a60-4d5c3ec0f67a",
"name": "Asha Rao",
"phone": "919876543210",
"email": "asha@example.com",
"stage": { "id": "1e43…", "name": "Contacted", "color": "#a78bfa", "kind": "active" },
"lostReason": null,
"rating": 3,
"source": "Partner portal",
"owner": { "id": "c4f6…", "name": "Urvi", "email": "urvi@yourcompany.com" },
"dealValue": 250000,
"paidTotal": 0,
"tags": ["december"],
"attributes": { "city": "Udaipur" },
"nextFollowUpAt": null,
"captureCount": 1,
"createdAt": "2026-09-14T10:00:00.000Z",
"conversationId": null
}
}List leads — a view, a filter, a search
# Won leads, biggest deals first, 25 per page
curl "https://fliok.com/api/v1/leads?view=sys:won&sort=dealValue&dir=desc&pageSize=25" \
-H "Authorization: Bearer wa_YOUR_API_KEY"
# Any filter the dashboard can build (URL-encode it)
curl -G "https://fliok.com/api/v1/leads" \
--data-urlencode 'filter={"match":"all","conditions":[{"field":"source","op":"in","value":["Website"]},{"field":"rating","op":"gte","value":4}]}' \
--data-urlencode "q=asha" \
-H "Authorization: Bearer wa_YOUR_API_KEY"// 200 OK — views: sys:open, sys:all, sys:unassigned, sys:new_today,
// sys:followups, sys:won, sys:lost, or the id of a view shared with your team
{
"leads": [ { "id": "…", "name": "Asha Rao", "stage": { "name": "Won", "kind": "won" }, … } ],
"total": 15,
"page": 1,
"pageSize": 25
}Move a lead, and log what happened
# :id is our lead id OR the phone number
curl -X PATCH https://fliok.com/api/v1/leads/+919876543210 \
-H "Authorization: Bearer wa_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "stage": "Lost", "lostReason": "Too expensive", "owner": "urvi@yourcompany.com", "addTags": ["priced-out"] }'
curl -X POST https://fliok.com/api/v1/leads/+919876543210/notes \
-H "Authorization: Bearer wa_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "body": "Asked for a quote under 2L" }'// PATCH → 200 OK. "changed" lists what actually moved; each is on the lead's timeline
{
"lead": { "id": "…", "stage": { "name": "Lost", "kind": "lost" }, "lostReason": { "id": "…", "label": "Too expensive" }, … },
"changed": ["stage_changed", "owner_changed", "tags_changed"]
}
// POST notes → 201 Created
{ "note": { "id": "510a…", "leadId": "4ca4…", "body": "Asked for a quote under 2L", "createdAt": "2026-09-14T10:05:00.000Z" } }
// An unknown name is refused, never guessed:
// 400 { "error": "invalid", "message": "There is no stage called \"Wonn\". GET /api/v1/pipeline lists the stages." }Follow-up tasks
curl -X POST https://fliok.com/api/v1/tasks \
-H "Authorization: Bearer wa_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "leadId": "+919876543210", "type": "call", "title": "Call back with revised quote",
"dueAt": "2026-09-16T11:00:00+05:30", "priority": "high", "assignee": "tushar@yourcompany.com" }'
curl "https://fliok.com/api/v1/tasks?status=overdue&pageSize=50" -H "Authorization: Bearer wa_YOUR_API_KEY"
curl -X PATCH https://fliok.com/api/v1/tasks/31089580-1422-48cc-becd-85c4e6689352 \
-H "Authorization: Bearer wa_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "status": "done", "outcome": "Sent revised quote" }'// POST → 201 Created; PATCH → 200 OK with the same shape
{
"task": {
"id": "31089580-1422-48cc-becd-85c4e6689352",
"lead": { "id": "4ca4…", "name": "Asha Rao", "phone": "919876543210" },
"type": "call",
"title": "Call back with revised quote",
"dueAt": "2026-09-16T05:30:00.000Z",
"priority": "high",
"status": "pending",
"state": "pending",
"assignee": { "id": "c4f6…", "name": "Tushar" },
"completedAt": null,
"outcome": null
}
}
// GET → { "tasks": [ … ], "total": 3, "page": 1, "pageSize": 50,
// "counts": { "overdue": 3, "today": 1, "upcoming": 7, "done": 40, "cancelled": 2 } }Read the pipeline
curl https://fliok.com/api/v1/pipeline -H "Authorization: Bearer wa_YOUR_API_KEY"// 200 OK — switch on "kind", not on your team's stage names
{
"stages": [
{ "id": "2167…", "name": "New lead", "color": "#53bdeb", "kind": "initial", "position": 0 },
{ "id": "1e43…", "name": "Contacted", "color": "#a78bfa", "kind": "active", "position": 1 },
{ "id": "9b75…", "name": "Won", "color": "#00a884", "kind": "won", "position": 5 },
{ "id": "9502…", "name": "Lost", "color": "#f15c6d", "kind": "lost", "position": 6 }
],
"lostReasons": [ { "id": "97e8…", "label": "Too expensive", "position": 1 } ],
"initialStageId": "2167…"
}Rate limits
The buckets these endpoints use. Burst is how many requests you can make back-to-back from a full bucket; sustained is how fast it refills.
| Bucket | Endpoints | Burst | Sustained |
|---|---|---|---|
| CRM writes | POST /leads · PATCH /leads/{id} · notes · POST /tasks · PATCH /tasks/{id} | 120 | 10 / sec |
| Lead capture URL | POST /api/leads/capture/{token} (per sending address) | 30 | 30 / min |
Every limit, the RateLimit-* headers and what to do on a 429: Rate limits.