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 403 with QUEUE_NOT_YOURS, and the queue Fondaro makes for everyone, My day, answers 403 with QUEUE_IS_SYSTEM.
  • A team queue (calling.pool is team) must be shared and only an organization admin can set one: QUEUE_TEAM_POOL_ADMIN_ONLY (403) and QUEUE_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.

bash
curl https://api.fondaro.com/v1/queues \  -H "Authorization: Bearer $FONDARO_API_KEY"
json
{  "queues": [    {      "id": "5c1d9f2e-0000-4000-8000-000000000001",      "name": "Morning calls",      "icon": "Sun",      "scope": "private",      "mine": true,      "system": false,      "summary": "Your leads. Overdue first, then new leads.",      "description": {        "who": "Leads you own",        "lanes": ["Overdue: task past due, oldest due first", "New: status New, newest first"],        "rest": "Everyone else is not listed",        "order": "",        "calling": "Each person is given the leads they own. A lead rests 2 hours after a call.",        "rules": []      },      "root": { "type": "group", "combinator": "and", "children": [] },      "lanes": [],      "rest": "hide",      "sort": null,      "calling": { "pool": "owners", "coolDownMinutes": 120 },      "rules": [],      "updatedAt": "2026-10-10T08:12:44.000Z"    }  ]}

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.

bash
curl https://api.fondaro.com/v1/queues/5c1d9f2e-0000-4000-8000-000000000001 \  -H "Authorization: Bearer $FONDARO_API_KEY"

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.

ParameterInTypeRequiredDescription
queueIdBodystring (uuid)One of the twoA saved queue to try
definitionBodyobjectOne of the twoAn 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.

bash
curl -X POST https://api.fondaro.com/v1/queues/preview \  -H "Authorization: Bearer $FONDARO_API_KEY" \  -H "Content-Type: application/json" \  -d '{    "definition": {      "root": {        "type": "group", "combinator": "and",        "children": [          { "type": "condition", "field": "assignee", "operator": "has_any_of",            "value": { "kind": "strings", "values": ["$me"] } }        ]      },      "lanes": [        {          "name": "Overdue",          "when": {            "type": "group", "combinator": "and",            "children": [              { "type": "condition", "field": "taskOverdue", "operator": "is_true",                "value": { "kind": "boolean", "value": true } }            ]          },          "sort": { "key": "nextTaskDueAt", "dir": "asc" }        }      ],      "rest": "hide"    }  }'
json
{  "summary": "Your leads. Overdue first.",  "description": { "who": "Leads you own", "lanes": ["Overdue: task past due, oldest due first"], "rest": "Everyone else is not listed", "order": "", "calling": "Each person is given the leads they own. A lead rests 2 hours after a call.", "rules": [] },  "lanes": [{ "id": "overdue", "name": "Overdue", "count": 4 }],  "restCount": 31,  "offers": [],  "rows": [    {      "id": 18204,      "firstName": "Ana",      "lastName": "Torres",      "laneId": "overdue",      "laneName": "Overdue",      "reason": "Task 2 days overdue"    }  ],  "rowsPerLane": 10}

$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.

ParameterInTypeRequiredDescription
nameBodystringYesUp to 40 characters. Shown in the sidebar
iconBodystringNoA sidebar icon name such as Sun or House
scopeBodystringNoprivate (default) or shared with the whole organization
rootBodygroupNoWho is in the queue at all. Leave out for every lead the key's person can see
lanesBodyarrayNoUp to 8 lanes, worked in order. Without lanes it is a plain list ordered by sort
restBodystringNohide or last (default). What happens to leads that fit no lane
sortBodyobjectNoThe order of a queue with no lanes
callingBodyobjectNoWho gets the next lead when someone presses Dial
rulesBodyarrayNoUp 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 }:

FieldOperatorsValue
assigneehas_any_of, has_all_of, has_none_of, is_unassigned{ kind: "strings", values }: user ids, or $me
taghas_any_of, has_all_of, has_none_of{ kind: "strings", values }: tag ids
crmStatushas_any_of, has_none_of{ kind: "strings", values }: lead (New), potential, bad_timing, client, unqualified
source, leadType, preferredLanguagehas_any_of, has_none_of{ kind: "strings", values }
phone, emailis_present, is_missing{ kind: "empty" }
createdAt, lastCallAt, lastEmailAt, lastTouchAt, lastInboundAtin_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
nextTaskDueAtin_next_n_days (0 is today), is_before, is_after, is_between, is_on, is_neveras dates
taskOverdueis_true, is_false{ kind: "boolean", value }
lastCallStatushas_any_of, has_none_of{ kind: "strings", values }: completed, no-answer, busy, failed, canceled
lastCallDirectionhas_any_of, has_none_of{ kind: "strings", values }: inbound, outbound
unansweredStreakeq, lt, gt, between{ kind: "integer", value }, or integerRange with min and max: outbound calls in a row with no answer
callCounteq, lt, gt, betweenas unansweredStreak
callSignalhas_any_of, has_none_of{ kind: "strings", values }: what the last call said, such as call.callback_promised or call.not_interested
notesContaincontains{ kind: "string", value }
hasIncompleteTask, hasOpenDealis_true, is_false{ kind: "boolean", value }
dealStagehas_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

FieldTypeDescription
idstringOptional. A stable id of up to 40 characters; made from the name when left out
namestringUp to 40 characters. A name, not a sentence
whengroupWho goes in this lane. A lead is in the first lane it matches; an empty group takes everyone not caught by an earlier lane
sortobject{ 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

FieldTypeDescription
poolstringowners (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
peopleobjectFor team: { userIds, teamIds }. Leave out for everyone who can open the queue
coolDownMinutesinteger0 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.

FieldTypeDescription
idstringOptional. A stable id; made for you when left out
whenstringcall_ended, task_completed or time_passed
ifgroupWho it is about, with the same filters as a lane. An empty group offers to every lead in the queue
offerobjectOne 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)
bash
curl -X POST https://api.fondaro.com/v1/queues \  -H "Authorization: Bearer $FONDARO_API_KEY" \  -H "Idempotency-Key: 0b6f8f0e-6d2b-4b8a-9f43-5f1c2a7d9e11" \  -H "Content-Type: application/json" \  -d '{    "name": "Morning calls",    "icon": "Sun",    "root": {      "type": "group", "combinator": "and",      "children": [        { "type": "condition", "field": "assignee", "operator": "has_any_of",          "value": { "kind": "strings", "values": ["$me"] } }      ]    },    "lanes": [      {        "name": "Overdue",        "when": {          "type": "group", "combinator": "and",          "children": [            { "type": "condition", "field": "taskOverdue", "operator": "is_true",              "value": { "kind": "boolean", "value": true } }          ]        },        "sort": { "key": "nextTaskDueAt", "dir": "asc" }      },      {        "name": "Chasing",        "when": {          "type": "group", "combinator": "and",          "children": [            { "type": "condition", "field": "unansweredStreak", "operator": "between",              "value": { "kind": "integerRange", "min": 1, "max": 9 } },            { "type": "condition", "field": "lastCallAt", "operator": "not_in_last_n_days",              "value": { "kind": "integer", "value": 2 } }          ]        },        "sort": { "key": "lastCallAt", "dir": "asc" }      }    ],    "rest": "hide",    "calling": { "pool": "owners", "coolDownMinutes": 120 },    "rules": [      {        "when": "call_ended",        "if": {          "type": "group", "combinator": "and",          "children": [            { "type": "condition", "field": "unansweredStreak", "operator": "gt",              "value": { "kind": "integer", "value": 9 } }          ]        },        "offer": { "kind": "set_status", "status": "unqualified" }      }    ]  }'

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.

bash
curl -X PATCH https://api.fondaro.com/v1/queues/5c1d9f2e-0000-4000-8000-000000000001 \  -H "Authorization: Bearer $FONDARO_API_KEY" \  -H "Content-Type: application/json" \  -d '{ "name": "Today", "rest": "last" }'

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.

bash
curl -X DELETE https://api.fondaro.com/v1/queues/5c1d9f2e-0000-4000-8000-000000000001 \  -H "Authorization: Bearer $FONDARO_API_KEY"
json
{ "deleted": true, "queueId": "5c1d9f2e-0000-4000-8000-000000000001" }