Concurrency limits
Concurrency limits
Concurrency is how many calls can be live at the same moment. It is a different thing from your monthly quota: a quota is how much you may use over a month, concurrency is how much you may use right now.
Three separate ceilings apply to every call. A call has to clear all of the ones that apply to it:
| Ceiling | Applies to | Default | Who sets it |
|---|---|---|---|
| Per number | PSTN calls (in and out) and softphone calls, counted on each phone number | 2 | Platform admin |
| Per workspace | Every live call — phone, web and softphone together | unset (∞) | You (owner/admin) |
| Browser | Web calls only — widget, test calls, SDK sessions | 50 | Platform admin |
The one that surprises people is the per-number cap. It is not a per-workspace limit. A number with a cap of 2 carries two simultaneous calls no matter how many numbers, agents or credits you have. If you want 20 calls at once you need either a higher per-number cap or more numbers — or a campaign, which paces the calls for you.
Setting the per-workspace cap
This is the one you control yourself.
- Go to Usage in the sidebar.
- Click Edit limits (top-right).
- Set Max concurrent calls — the number of simultaneous live calls your workspace may have.
- Leave it blank for unlimited. A value of 0 hard-pauses all calling.
- Make sure Enforce these limits is on. With it off the meters still count but nothing is blocked (the panel shows an Observe-only badge).
- Click Save limits.
The Concurrent now meter on the Usage page shows live usage against this cap.
Requires owner or admin. See Usage & billing for the monthly quotas that live in the same dialog.
Setting the per-number and browser caps
These are platform-admin settings, because they protect the carrier and the platform, not just your spend. If you are on a hosted plan, ask your platform admin; the steps below are for the admin console.
Change the default for every org
- Open the admin console → Platform fee.
- Find Default concurrency caps.
- Set:
- Browser (per org) — max simultaneous web calls per organization.
- Telephony (per number) — max simultaneous PSTN/softphone calls on each number.
- Save.
These apply to every organization that has no override of its own.
Override for one org
- Open the admin console → Billing accounts.
- Find the organization's row and click the concurrency cell (it reads
default, or e.g.50 web / 4 per #when overridden). - Enter the browser cap, then the per-number cap.
- Leave either empty to fall back to the platform default.
Raise the per-number cap only as far as the carrier and the number's own channel count actually allow. Setting 20 on a number the carrier will only carry 4 calls on does not create capacity — it just moves the refusal from us to the carrier, where it arrives as a failed call instead of a clean 429.
What happens when a limit is hit
The call is refused before the carrier is contacted — never silently dropped, and never billed. You get 429 Too Many Requests with a Retry-After header and a body that tells you which ceiling you hit:
{
"success": false,
"error": "This number is already on its limit of 2 simultaneous calls (2 live). Retry in about 240s, or send bulk calls through a campaign so they are paced for you.",
"retryAfter": 240,
"reason": "number_at_capacity",
"scope": "number",
"cap": 2,
"active": 2,
"position": 3,
"medianCallSecs": 120
}
| Field | What it tells you |
|---|---|
scope | Which ceiling: number, org or browser. This decides who fixes it — number and browser are platform-admin settings, org is yours under Usage → Edit limits. |
cap | The ceiling that refused you. |
active | How many calls are live on it right now. |
position | Your place in the queue behind the cap. 1 = you are next. |
retryAfter | Seconds to wait, derived from your position and your workspace's typical call length. Also sent as the standard Retry-After header. |
medianCallSecs | The typical call length the estimate was built from (your own recent calls). |
Honour retryAfter — don't invent your own backoff
Each refused caller is given a different wait, worked out from where it sits in the queue: the first one waits about one call-length, the fiftieth waits about twenty-five. That spreads a backlog across the time it will actually take to drain.
If every client retries on its own fixed timer instead, they all come back at the same instant, and all but a couple are refused again. Reading Retry-After is what stops that.
async function dial(body) {
for (let attempt = 0; attempt < 5; attempt++) {
const res = await fetch('https://api.telenow.ai/api/sessions/initiate-call', {
method: 'POST',
headers: { 'X-API-Key': KEY, 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
if (res.status !== 429) return res;
const wait = Number(res.headers.get('Retry-After') ?? 30);
const { scope, cap, active } = await res.json();
// A workspace-level refusal will not clear by trying a different number.
console.log(`at ${scope} capacity (${active}/${cap}) — retrying in ${wait}s`);
await new Promise((r) => setTimeout(r, wait * 1000));
}
throw new Error('still at capacity after 5 attempts');
}
Don't fan out parallel dials
The single-dial API places one call. Firing it 200 times in parallel does not produce 200 calls — it produces however many your caps allow and a pile of 429s, because the ceiling is a property of the phone number, not of how hard you ask.
For anything bulk, use a campaign: you hand over the whole list once, and the platform paces the dialing within your caps, retries no-answers, respects quiet hours and reports every outcome back.
Which cap is stopping me?
| Symptom | Cause | Fix |
|---|---|---|
scope: "number" on one number while others work | That number is full | More numbers, a higher per-number cap, or a campaign |
scope: "org" no matter which number | Workspace cap | Usage → Edit limits |
scope: "browser" on widget/test calls only | Browser cap | Ask your platform admin |
403, not 429 | Not concurrency — a monthly quota, a spend cap, or a suspended account | Usage & billing |
| Campaign dials far fewer at once than its concurrency setting | The campaign's own concurrency is capped again by the per-number ceiling | Spread the campaign across more numbers |
A campaign has its own concurrency setting too. It is an upper bound on that campaign, not an exemption: a campaign set to 10 on a single number with a per-number cap of 2 still runs 2 at a time.
How the limits behave in practice
- Counted the moment a call is admitted, not when it connects — so a burst of simultaneous requests is refused correctly rather than all being let through.
- Freed the moment a call ends, including calls nobody answered.
- Shared across servers, so the ceiling is the same no matter which server takes your request.
- Never fail closed. If the tracking layer is unavailable the platform keeps calling rather than stopping your business; enforcement resumes by itself.
Related
- Usage & billing — monthly quotas, spend caps, wallet
- Outbound campaigns — the paced way to run bulk calls
- Campaigns API — create and run one over HTTP
- Making & receiving calls
- Phone numbers — buying more numbers to raise real capacity