Queues
List, preview, create, change and delete queues through the Fondaro API: saved views with lanes that say who to call next and why.
A queue is a saved view with lanes. root says who is in it, each lane says which of those leads it takes and in what order, and rest says what happens to everyone else. A lead is in the first lane it matches. The product guide is Queues; this page lists the /v1 routes.
Reading needs crm:read. Writing needs crm:write and an active plan. No role is needed: a queue is your own saved view, so a key acts on the queues of the person it belongs to.
- You change or delete only queues you made. Another person's queue answers
403withQUEUE_NOT_YOURS, and the queue Fondaro makes for everyone, My day, answers403withQUEUE_IS_SYSTEM. - A team queue (
calling.poolisteam) must besharedand only an organization admin can set one:QUEUE_TEAM_POOL_ADMIN_ONLY(403) andQUEUE_TEAM_POOL_NOT_SHARED(400). - Queues are also available to AI clients through Fondaro MCP, with the same rules.
List queues
GET /v1/queues
The queues you can open: your own, shared ones and My day. Each comes back in plain words and as its full definition.
mine is true when you made the queue. system is true for the queue Fondaro made for everyone. The description text is built by Fondaro and can change, so branch on root, lanes and the other fields, not on the words.
Get a queue
GET /v1/queues/{queueId}
One queue, in the same shape as an item of the list.
A queue you cannot open answers 404.
Preview a queue
POST /v1/queues/preview
Try a queue without saving anything. Send a saved queueId, or an unsaved definition; one of the two is required. Needs crm:read.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
queueId | Body | string (uuid) | One of the two | A saved queue to try |
definition | Body | object | One of the two | An unsaved queue: any of root, lanes, rest, sort, calling, rules, as in Create a queue |
The answer has the size of each lane, how many leads fit no lane, how many leads would be offered each change now, and the first ten leads of each lane with why each is there.
$me is read as the person the key belongs to. restCount counts the leads in the queue that no lane takes, whether or not rest lists them. Day boundaries such as "due today" use UTC here.
Create a queue
POST /v1/queues
Needs crm:write and an active plan. Accepts an Idempotency-Key header; see Errors and limits.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
name | Body | string | Yes | Up to 40 characters. Shown in the sidebar |
icon | Body | string | No | A sidebar icon name such as Sun or House |
scope | Body | string | No | private (default) or shared with the whole organization |
root | Body | group | No | Who is in the queue at all. Leave out for every lead the key's person can see |
lanes | Body | array | No | Up to 8 lanes, worked in order. Without lanes it is a plain list ordered by sort |
rest | Body | string | No | hide or last (default). What happens to leads that fit no lane |
sort | Body | object | No | The order of a queue with no lanes |
calling | Body | object | No | Who gets the next lead when someone presses Dial |
rules | Body | array | No | Up to 10 offers, see Offers below |
Filters: root and a lane's when
A group has a combinator (and or or) and children: conditions, or one more level of group. Up to 25 children per group.
A condition is { type: "condition", field, operator, value }:
| Field | Operators | Value |
|---|---|---|
assignee | has_any_of, has_all_of, has_none_of, is_unassigned | { kind: "strings", values }: user ids, or $me |
tag | has_any_of, has_all_of, has_none_of | { kind: "strings", values }: tag ids |
crmStatus | has_any_of, has_none_of | { kind: "strings", values }: lead (New), potential, bad_timing, client, unqualified |
source, leadType, preferredLanguage | has_any_of, has_none_of | { kind: "strings", values } |
phone, email | is_present, is_missing | { kind: "empty" } |
createdAt, lastCallAt, lastEmailAt, lastTouchAt, lastInboundAt | in_last_n_days, not_in_last_n_days, in_last_n_hours, not_in_last_n_hours, is_on, is_before, is_after, is_between, is_never | { kind: "integer", value } for last N days or hours; a date value for the rest; { kind: "empty" } for is_never |
nextTaskDueAt | in_next_n_days (0 is today), is_before, is_after, is_between, is_on, is_never | as dates |
taskOverdue | is_true, is_false | { kind: "boolean", value } |
lastCallStatus | has_any_of, has_none_of | { kind: "strings", values }: completed, no-answer, busy, failed, canceled |
lastCallDirection | has_any_of, has_none_of | { kind: "strings", values }: inbound, outbound |
unansweredStreak | eq, lt, gt, between | { kind: "integer", value }, or integerRange with min and max: outbound calls in a row with no answer |
callCount | eq, lt, gt, between | as unansweredStreak |
callSignal | has_any_of, has_none_of | { kind: "strings", values }: what the last call said, such as call.callback_promised or call.not_interested |
notesContain | contains | { kind: "string", value } |
hasIncompleteTask, hasOpenDeal | is_true, is_false | { kind: "boolean", value } |
dealStage | has_any_of, has_none_of | { kind: "strings", values } |
$me is read as the person who opens the queue, so the same queue is personal to each of them. Read without a person, it is refused with 400.
Lanes
| Field | Type | Description |
|---|---|---|
id | string | Optional. A stable id of up to 40 characters; made from the name when left out |
name | string | Up to 40 characters. A name, not a sentence |
when | group | Who goes in this lane. A lead is in the first lane it matches; an empty group takes everyone not caught by an earlier lane |
sort | object | { key, dir }: the order inside the lane |
sort.key is one of purchasedAt (when the lead arrived), nextTaskDueAt, lastCallAt, lastTouchAt, lastInboundAt, totalCalls, pendingTasks, firstName or crmStatus. dir is asc or desc.
Calling
| Field | Type | Description |
|---|---|---|
pool | string | owners (default): each person is given the leads they own. team: anyone in the pool is given the next lead, and the first connected call claims an unassigned one. A team queue must be shared, and only an admin sets it |
people | object | For team: { userIds, teamIds }. Leave out for everyone who can open the queue |
coolDownMinutes | integer | 0 to 1440. How long a lead rests after any call to it. Default 120 |
Offers
An offer is how a queue proposes a change after a call, a finished task or the passing of time. It never changes a lead by itself: the person sees one plain sentence and taps it, with Undo after. See Queues.
| Field | Type | Description |
|---|---|---|
id | string | Optional. A stable id; made for you when left out |
when | string | call_ended, task_completed or time_passed |
if | group | Who it is about, with the same filters as a lane. An empty group offers to every lead in the queue |
offer | object | One change: { kind: "set_status", status }, { kind: "add_tag", tagId }, { kind: "remove_tag", tagId }, { kind: "assign", userId } or { kind: "follow_up", inDays } (0 to 365; a call back task) |
The answer is 201 with the queue, in the shape of an item of the list. The queue is private unless you set scope to shared. It appears in the sidebar of the person the key belongs to the next time they open Fondaro.
Update a queue
PATCH /v1/queues/{queueId}
Change a queue you made. Send only what changes; fields you leave out stay as they are. lanes replaces the whole list of lanes when given, and so does rules. Needs crm:write and an active plan.
The answer is the queue after the change.
Delete a queue
DELETE /v1/queues/{queueId}
Delete a queue you made. The leads in it are not touched, and the queue leaves every sidebar it was pinned in. Needs crm:write and an active plan.