Scheduled Calls
Queue outbound calls for a future time instead of dialing immediately — and understand exactly when and how they go out.
Scheduling a call
Pass scheduledAt (ISO 8601) when creating the call. Instead of dialing, the call is stored with status scheduled:
curl -X POST https://api.threll.io/v1/accounts/9c3e8f02-7a14-4b62-bc59-1d8e5fa3027b/phone-calls \
-H "x-api-key: $THRELL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"workerId": "2b7d9a4c-6e3f-48a1-9c5d-8e0b4f2a1c8d",
"phoneNumber": "+15555550100",
"context": "Renewal reminder, contract expires June 30.",
"scheduledAt": "2026-06-12T09:00:00Z"
}'const call = await threll('/v1/accounts/9c3e8f02-7a14-4b62-bc59-1d8e5fa3027b/phone-calls', {
method: 'POST',
body: JSON.stringify({
workerId: '2b7d9a4c-6e3f-48a1-9c5d-8e0b4f2a1c8d',
phoneNumber: '+15555550100',
context: 'Renewal reminder, contract expires June 30.',
scheduledAt: '2026-06-12T09:00:00Z',
}),
});
console.log(call.status); // scheduledcall = session.post(
f"{BASE}/v1/accounts/9c3e8f02-7a14-4b62-bc59-1d8e5fa3027b/phone-calls",
json={
"workerId": "2b7d9a4c-6e3f-48a1-9c5d-8e0b4f2a1c8d",
"phoneNumber": "+15555550100",
"context": "Renewal reminder, contract expires June 30.",
"scheduledAt": "2026-06-12T09:00:00Z",
},
).json()
print(call["status"]) # scheduledValidation (telephony setup, call scripts) happens at create time, so a scheduled call that was accepted won't fail later for configuration reasons that already existed — see telephony errors.
How dispatch works
A scheduler sweeps for due calls every 2 minutes and dispatches them in small batches with a cap on simultaneous active calls, so a large batch of calls drains gradually rather than all at once. In practice:
- A call goes out at or shortly after its
scheduledAt— typically within a couple of minutes. - If many calls are due at once, they're processed in batches; later ones wait for capacity.
- Status moves
scheduled → queued → in_progress → completed. Subscribe tocall.status_updateto follow along.
Right before a scheduled call dials, Threll fires the call.worker_request sync webhook — so the call re-resolves its worker configuration at run time, not at schedule time. Use it to inject context that's fresh on the day of the call.
Scheduling in bulk
For call batches driven by an AI agent over MCP, use the batch tools: prepare_phone_call_batch validates up to 100 call drafts atomically and returns one confirmation token; confirm_phone_call_batch inserts them all as scheduled calls in a single transaction, and the scheduler drains them. Over REST, simply create multiple calls with staggered or identical scheduledAt values — the dispatch cap prevents a thundering herd.
Cancelling and monitoring
- Cancel — a scheduled call can be cancelled any time before dispatch: in the platform, or via the MCP tool
cancel_scheduled_call. - Inspect — fetch the call;
scheduledAtstays on the resource, andstartedAt/endedAtfill in once it runs. - Listen —
call.status_updateevents fire on every transition, andcall.endedmarks completion.