Integration API
The dialer's integration API lets your CRM, IVR or Studio flows feed the dialer and read results back:
- push leads into a contact list and enrol them in a campaign;
- start, pause and stop campaigns;
- read each lead's status and outcome in a campaign;
- book, list, reschedule and cancel callbacks ("please call me back").
Everything else (creating and configuring campaigns, agents, dispositions, outgoing numbers) is done in the Campaigns view or the dialer console.
Basics
- Base URL:
https://<your-floor-walker-host>/api/v1 - Authentication: send your API key in the
X-Api-Keyheader. Each key carries scopes and can call only the endpoints they cover (see Scopes); ask us for one key per integration, with only the scopes it needs.GET /api/v1/mereturns the key's name (identity) andscopes. API keys are issued by us; keep them on the server side and never put them in a browser or a mobile app. Ask us to revoke a key that may have leaked. - Format: JSON request and response bodies (
Content-Type: application/json). Times are ISO 8601 with an offset, for example2026-11-02T10:30:00+02:00. IDs are UUIDs. - Phone numbers may be in E.164 (
+972501234567) or local format; local numbers are read with the contact list's default country.
curl -H "X-Api-Key: <your-api-key>" "https://<your-floor-walker-host>/api/v1/campaigns?status=running"
Scopes
| Scope | Endpoints |
|---|---|
campaigns:read | GET /campaigns, GET /campaigns/:id |
campaigns:control | POST /campaigns/:id/start, /pause, /stop |
leads:write | GET /contact-lists, GET /contact-lists/:id, POST /contact-lists/:id/leads, POST /campaigns/:id/leads/sync |
results:read | GET /campaigns/:id/leads |
callbacks:read | GET /callbacks, GET /callbacks/:id |
callbacks:write | POST /callbacks, PATCH /callbacks/:id, plus everything callbacks:read covers |
Every key can call GET /me. A key needs a matching scope for every other endpoint on this page; anything else answers 403 forbidden.
Errors
Errors return an HTTP status and a JSON body with a machine-readable error code and, where useful, details:
{ "error": "outside_calling_window", "message": "outside_calling_window", "details": { "reason": "calendar_closed", "nextWindowAt": "2026-11-03T09:00:00.000+02:00", "timezone": "Asia/Jerusalem" } }
| Status | When |
|---|---|
400 validation_error | The body or query does not match the endpoint; details lists each problem |
401 unauthorized, 401 invalid_api_key | No key, or the key is unknown or revoked |
403 forbidden | The key's scopes do not cover this endpoint; details.requiredScopes lists the scopes that would |
404 …_not_found | The campaign, contact list, lead or callback does not exist |
409 | The request conflicts with the current state, for example invalid_transition or callback_exists |
422 | The request is valid but not allowed, for example dnc or outside_calling_window |
Campaigns
List campaigns
Scope: campaigns:read
GET /campaigns?status=&channel=&page=&pageSize=
status is draft, running, paused, stopped or archived; channel is voice, sms or whatsapp. Pages of up to 200 (default 50).
{
"items": [
{ "id": "0192f4c1-…", "name": "Renewals November", "status": "running", "mode": "progressive", "channel": "voice", "contactListId": "0192f4b8-…", "priority": 3 }
],
"total": 1, "page": 1, "pageSize": 50
}
GET /campaigns/:id returns one campaign.
Start, pause and stop
Scope: campaigns:control
POST /campaigns/:id/start, POST /campaigns/:id/pause, POST /campaigns/:id/stop
No body. Returns the campaign with its new status. Allowed changes:
| From | To |
|---|---|
draft | running |
running | paused, stopped |
paused | running, stopped |
stopped | running |
Anything else returns 409 invalid_transition with from and to in details. Pausing or stopping places no new calls; calls in progress finish.
Leads
A campaign dials the leads of its contact list. Getting leads from your CRM into a campaign takes two calls: push the leads into the contact list, then enrol the new ones in the campaign.
Find the contact list
Scope: leads:write
GET /contact-lists?page=&pageSize= returns { items, total, page, pageSize }, each item with its id, name, countryDefault and timezoneDefault. A campaign's list is its contactListId.
Push leads
Scope: leads:write
POST /contact-lists/:id/leads
Up to 1,000 leads per request. The upload is idempotent by externalId: a lead whose externalId is already in the list is updated, not duplicated. Leads without an externalId are matched by phone number when dedupeByPhone is on (the default).
{
"leads": [
{
"externalId": "CRM-10442",
"firstName": "Dana",
"lastName": "Levi",
"phone": "+972501234567",
"phones": [{ "phone": "03-1234567", "type": "home" }],
"timezone": "Asia/Jerusalem",
"custom": { "plan": "gold", "renewalDate": "2026-12-01" },
"existingCustomer": true,
"consentAt": "2026-03-14T00:00:00Z"
}
],
"dedupeByPhone": true
}
| Field | Meaning |
|---|---|
externalId | Your ID for the person (up to 128 characters) |
firstName, lastName | Name shown to the agent |
phone, phones | At least one is required. phone is a mobile number; phones lists numbers with a type (mobile, home, work, other), up to 10 |
timezone, country | IANA time zone for calling windows and the two-letter country for local numbers; the list's defaults apply when omitted |
custom | Free-form fields, usable in the campaign's lead filter (custom.<key>) and in message variables |
existingCustomer, consentAt | Consent basis for marketing messages and the national registry (Compliance) |
dncRegistryListed, dncRegistryCheckedAt | The result and date of your national do-not-call registry check |
On update, fields you leave out keep their stored values, and custom is merged into the stored fields.
Response:
{ "received": 1, "created": 1, "updated": 0, "duplicates": 0, "dnc": 0, "invalid": [] }
dnc counts numbers that are on a DNC list (they are stored but never dialed). invalid lists rejected leads by their position in the request, with a reason such as no_phone or invalid_phone.
Enrol new leads in a campaign
Scope: leads:write
POST /campaigns/:id/leads/sync
Adds the leads of the campaign's contact list that match its lead filter and are not in the campaign yet. Safe to call after every upload; leads already in the campaign are left alone. Body, all optional:
| Field | Meaning |
|---|---|
dryRun | true only counts, without enrolling |
limit | Enrol at most this many (0 = all matching) |
{ "enrolled": 120, "alreadyEnrolled": 3400, "matching": 3520, "wouldEnrol": 120, "dryRun": false }
Read results
Scope: results:read
GET /campaigns/:id/leads?status=&search=&page=&pageSize=
The campaign's leads with their dialing state and latest outcome, in dial order. status is one of ready, dialing, in_progress, done, excluded, callback, owned (see Lead lifecycle); search matches name, customer ID or phone. Each item includes:
| Field | Meaning |
|---|---|
lead_id, external_id | The lead and your ID for it |
status, attempts, next_attempt_at | Where the lead is in the campaign |
last_disposition_code | The agent's last outcome (for example interested) |
exclude_reason | Why an excluded lead is no longer dialed, for example dnc, invalid_number, opted_out or max_attempts:no_answer |
phones | Numbers with their type and status |
last_message | For SMS and WhatsApp campaigns: the latest message's state and its sent, delivered, read and replied times |
The response also has total and countsByStatus.
Callbacks
A callback is a promise to call a customer back, for example from an IVR "please call me back" option or a web form. It belongs to a campaign and follows that campaign's caller ID, calling windows, calendar and DNC lists. See Callbacks.
Book a callback
Scope: callbacks:write
POST /callbacks
curl -X POST "https://<your-floor-walker-host>/api/v1/callbacks" \
-H "X-Api-Key: <your-api-key>" -H 'Content-Type: application/json' \
-d '{"phone":"+972501234567","name":"Example Customer","notes":"asked for a callback in the IVR"}'
| Field | Meaning |
|---|---|
campaignId | Optional. Without it, the campaign named Callbacks |
leadId or phone | One is required. Without leadId, the lead is looked up by phone in the campaign's list, or created |
name, externalId | Used when a new lead is created |
scheduledAt | When to call. Omitted means as soon as possible (moved to the next opening when outside the allowed hours) |
windowMin | How long after scheduledAt the call may still start (default 15) |
ownerWorkerSid | A worker SID for an agent-owned callback; omit or null for any agent on the campaign |
notes | Shown to the agent (up to 500 characters) |
Returns 201 with the callback: id, campaignId, leadId, phoneE164, scheduledAt, windowMin, ownerWorkerSid, status, notes, leadName, campaignName.
| Error | Meaning |
|---|---|
422 outside_calling_window | The requested time is outside the allowed hours. details.reason is lead_window (the lead's calling window), calendar_closed (with calendarEvent.title when a holiday or closure applies) or calendar_unavailable; details.nextWindowAt is the next opening |
422 dnc | The number is on a DNC list |
422 invalid_phone | The number cannot be read |
422 campaign_required | No campaignId and no campaign named Callbacks |
409 callback_exists | The lead already has an active callback; details.id is its ID |
409 campaign_not_active | The campaign is stopped or archived |
List and read callbacks
Scope: callbacks:read
GET /callbacks?owner=&campaignId=&from=&to=&status=&limit=&offset=
owner is any (callbacks for any agent) or a worker SID; status is a comma-separated list of pending, dispatched, dialed, done, expired, canceled; from and to bound the scheduled time. Up to 500 per page (default 100).
curl -H "X-Api-Key: <your-api-key>" \
"https://<your-floor-walker-host>/api/v1/callbacks?owner=any&status=pending,dispatched"
The response is { items, total }. GET /callbacks/:id returns one callback, with its last dial attempt.
Reschedule, reassign or cancel
Scope: callbacks:write
PATCH /callbacks/:id
| Field | Effect |
|---|---|
scheduledAt | Reschedule; also revives an expired or canceled callback |
windowMin, notes | Change the window or the note |
ownerWorkerSid | A SID reassigns it; null hands it to any agent |
status: "canceled" | Cancel. Cannot be combined with a reschedule or a reassignment |
A callback that can no longer be changed returns 409 not_reschedulable or 409 not_cancelable with its current status.