REST API reference (v1)
Full reference for the FlowMaticX public REST API — authentication, endpoints, request/response shapes, and error codes.
The FlowMaticX public API lets you integrate lead generation, CRM, and credit management into your own tools, dashboards, or automations.
> Plan requirement: API access requires the Agency plan.
---
https://app.flowmaticx.com/api/v1
---
All requests must include an API key in the Authorization header:
Authorization: Bearer lg_live_YOUR_API_KEY
Generate an API key at Settings → API Keys → New key. You can create multiple keys with different scopes and revoke them individually.
| Scope | Description |
|---|---|
leads:read | List and search leads |
jobs:write | Create new search jobs |
jobs:read | List and check job status |
credits:read | View credit balance |
* | All scopes (default for new keys) |
---
| Tier | Limit |
|---|---|
| All plans | 300 requests / minute per API key |
When exceeded, the API returns 429 Too Many Requests. Retry after the Retry-After header value (in seconds).
---
All errors follow the same envelope:
json
{
"ok": false,
"error": {
"code": "INSUFFICIENT_CREDITS",
"message": "Need 20 credits, have 5",
"status": 402
}
}
| Code | HTTP | Meaning |
|---|---|---|
UNAUTHORIZED | 401 | Missing or invalid API key |
FORBIDDEN | 403 | Key lacks required scope or plan feature is locked |
PLAN_FEATURE_LOCKED | 403 | Your plan doesn't include this feature |
NOT_FOUND | 404 | Resource doesn't exist in your workspace |
VALIDATION_ERROR | 400 | Request body failed schema validation |
PLAN_LIMIT_EXCEEDED | 400 | Requested leads exceed plan max-per-job |
INSUFFICIENT_CREDITS | 402 | Not enough credits to run the job |
RATE_LIMITED | 429 | Too many requests |
NO_SUBSCRIPTION | 400 | Workspace has no active subscription |
---
---
Start a new lead generation job. Returns the job ID immediately; use GET /jobs to poll for completion.
Request body
json
{
"workflow_type": "GOOGLE_MAPS",
"keyword": "plumber",
"location": "Manchester, UK",
"leads_requested": 50,
"ai_enabled": true,
"include_risky": false
}
| Field | Type | Required | Description | ||||||
|---|---|---|---|---|---|---|---|---|---|
workflow_type | enum | Yes | GOOGLE_MAPS | LINKEDIN | INSTAGRAM | TIKTOK | FACEBOOK | YELLOW_PAGES | CUSTOM |
keyword | string | Yes | Search keyword or hashtag | ||||||
location | string | Yes | City, region, or country | ||||||
leads_requested | integer | Yes | 1–500 | ||||||
ai_enabled | boolean | No | Enable AI personalisation (default: true; requires Starter+) | ||||||
include_risky | boolean | No | Include RISKY email status leads (default: false) |
Response 200
json
{
"ok": true,
"data": {
"job_id": 10042,
"status": "queued",
"estimated_credits": 100,
"credits_remaining": 850
}
}
---
GET /api/v1/jobs?limit=20&offset=0&status=COMPLETED
| Query param | Type | Description | ||||
|---|---|---|---|---|---|---|
limit | integer | 1–100 (default 50) | ||||
offset | integer | Pagination offset (default 0) | ||||
status | string | Filter: QUEUED | RUNNING | COMPLETED | FAILED | TIMED_OUT |
Response 200
json
{
"ok": true,
"data": {
"jobs": [
{
"id": 10042,
"workflowType": "GOOGLE_MAPS",
"keyword": "plumber",
"location": "Manchester, UK",
"requestedLeads": 50,
"foundLeads": 47,
"processedLeads": 47,
"creditsUsed": 94,
"status": "COMPLETED",
"progress": 100,
"createdAt": "2026-05-04T10:00:00Z",
"startedAt": "2026-05-04T10:00:05Z",
"finishedAt": "2026-05-04T10:02:15Z"
}
],
"total": 1,
"limit": 20,
"offset": 0
}
}
---
GET /api/v1/leads?limit=50&offset=0&job_id=10042&billable_only=true
| Query param | Type | Description | ||
|---|---|---|---|---|
limit | integer | 1–100 (default 50) | ||
offset | integer | Pagination offset | ||
job_id | integer | Filter to leads from a specific job | ||
billable_only | boolean | Only return billable leads (default: true) | ||
email_status | string | Filter: VALID | RISKY | INVALID |
Response 200
json
{
"ok": true,
"data": {
"leads": [
{
"id": 98321,
"businessName": "Bloom Florist",
"category": "Florist",
"email": "sarah@bloomflorist.co.uk",
"emailStatus": "VALID",
"decisionMakerName": "Sarah Blake",
"decisionMakerRole": "Owner",
"phone": "+441615551234",
"website": "bloomflorist.co.uk",
"domain": "bloomflorist.co.uk",
"address": "14 Market St",
"city": "Manchester",
"postalCode": "M1 1AB",
"country": "GB",
"rating": 4.8,
"reviewsCount": 127,
"icebreaker": "Congrats on the 4.8 rating...",
"emailSubject": "Quick question about your website",
"emailBody": "Hi Sarah, ...",
"aiInsight": "Active Google Maps presence with strong reviews...",
"keyword": "florist",
"isBillable": true,
"createdAt": "2026-05-04T10:02:15Z"
}
],
"total": 47,
"limit": 50,
"offset": 0
}
}
---
GET /api/v1/credits
Response 200
json
{
"ok": true,
"data": {
"planId": "AGENCY",
"creditsTotal": 1500,
"creditsUsed": 650,
"creditsRemaining": 850,
"currentPeriodStart": "2026-05-01T00:00:00Z",
"currentPeriodEnd": "2026-05-31T23:59:59Z",
"status": "ACTIVE"
}
}
---
All list endpoints return total, limit, and offset. To page through all results:
`js
let offset = 0;
const limit = 100;
let all = [];
while (true) {
const res = await fetch(/api/v1/leads?limit=${limit}&offset=${offset}, {
headers: { Authorization: 'Bearer lglive...' }
});
const { data } = await res.json();
all = all.concat(data.leads);
if (all.length >= data.total) break;
offset += limit;
}`
---
Attach an Idempotency-Key header to any POST request to prevent duplicate jobs if the client retries:
Idempotency-Key: my-job-ref-abc123
If a job was already created with this key, the original job is returned instead of creating a new one.