Skip to main content
Most campaign calling starts with a CSV: you upload a contact list, launch a run, and the platform works through it. On-demand calls are the other way in — your own system asks SquawkVoice to call one person, as soon as the campaign’s calling hours allow or at a time up to 48 hours ahead, and the campaign supplies the agent, the caller ID, the calling hours and the compliance rules. Use it when the trigger lives in your systems rather than in a list: a web form submission that deserves an immediate callback, a CRM stage change, an abandoned checkout, a support ticket that needs a voice follow-up.
On-demand calling is for voice campaigns.

Before You Start

1

Set up a voice campaign

The campaign needs an AI agent assigned on its Setup tab, and that agent needs at least one phone number bought in the Studio: on-demand calls come from the agent’s own numbers. It also needs a saved Schedule, because on-demand calls are only dialed inside the campaign’s Calling Hours. See Campaign Setup, Scheduling and Phone Numbers.
2

Copy the campaign ID

Open Manage → Campaigns → your campaign → On-Demand. The campaign ID is at the top with a copy button — that ID goes in the request path.Campaigns isn’t in the default sidebar for the Agent Builder role. Add it with Customize sidebar, or press Cmd/Ctrl+K and search for it. See Navigating Studio.
3

Create an API key

On that same On-Demand tab, click API reference, then Manage API Keys, and create a key. API Keys has no sidebar or search entry, so that button is the way in from Studio; you can also add /manage/api-keys to your Studio address. The key is shown once — copy it then. See API Keys.
A campaign with no agent, or whose agent has no usable phone number, still accepts your call and returns success. The contact then sits at pending, and nothing in the Studio explains why. Before you point an integration at a campaign, check the Caller ID section of its Setup tab, which lists the numbers the agent calls from.
You do not need to launch the campaign. A draft campaign accepts and dials on-demand calls — which also means on-demand calling bypasses the launch checklist, including its compliance attestation step. A campaign you deliberately stopped, or one that failed, refuses on-demand calls until you relaunch it. A paused campaign does not: it still accepts and dials them (see Things to Design Around).

The On-Demand Tab

Every campaign has an On-Demand tab, at Manage → Campaigns → your campaign. It holds:
  • The campaign ID, with a copy button.
  • Refresh — reloads the on-demand activity and confirms with “On-demand activity refreshed”.
  • API reference — a drawer with your API base URL as its own copyable field, plus ready-to-run curl and JavaScript snippets for all three endpoints, and a Manage API Keys button.
  • A status card for the campaign’s on-demand run, once your first call has landed. It shows the run’s status, how many calls are in progress, when the run ended if it has, and a count for each problem outcome (for example blocked, failed, busy or no answer). Before that the tab reads “No on-demand calls yet” — the run is created for you by the first successful request, so there is nothing to set up.
Clicking the status card opens On-Demand activity: the same contact list as a normal run detail, with a Cancel action on any contact that is still waiting to be dialed: one that is Pending, Retry or Callback requested.
Copy the base URL from the API reference drawer rather than assuming it — it differs between environments, and the drawer always shows the correct one for the Studio you are signed in to.

Place a Call

Returns 202 Accepted. That means the contact was accepted, not that a call has been placed: consent and the other compliance gates are checked when the call is due.
Without consent fields, a 202 does not lead to a call. A contact is only dialed when has_pewc is true (with a pewc_date) and is_voice_call_opted_out is not true. Leave has_pewc out and the request is still accepted with a 202, but the contact shows as Blocked in On-Demand activity, with a reason saying it is missing prior express written consent, and no call is placed. The snippets in the API reference drawer don’t include has_pewc or pewc_date, so add them before you use one. Send has_pewc: true only for contacts who have given you prior express written consent.

Request fields

How scheduled_at is interpreted:
  • With an offset or a Z, it is a self-contained instant and is used as-is.
  • Without one, it is read in scheduled_at_timezone if you supplied that.
  • Without either, it is read in the timezone derived from the postcode.

Response

dialing_status is pending for an immediate call and callback_requested for a scheduled one. Keep the request_id — it is the reference you can cancel by, and the only identifier you hold if you did not store contact_id.

Cancel a Call

A call can be cancelled while it is still waiting to be dialed. Either identifier works:
Both return 200 with already_cancelled telling you which of the two things happened:
Cancelling is idempotent — a repeat call, or a call that arrives after the contact has already been picked up for dialing, is not an error. It comes back as 200 with already_cancelled: true. A contact can actually be cancelled while it is pending, queued for a retry (retry — for example waiting for the calling hours to open, or backing off after a busy or no answer), or scheduled for later (callback_requested). Once a dial is in progress or finished there is nothing to stop.

Responses and Errors

Requests are rate limited by IP address, at roughly 1,000 requests a minute. Systems that share one outbound IP address share that allowance. Go over it and you get a 429, and further requests can keep getting 429 for a few minutes, so back off before retrying.

Things to Design Around

A retried POST places a second real call. Repeat submissions of the same phone number are accepted deliberately — each one is its own attempt with its own request_id — so de-duplicate on your side, and store the request_id you get back.
Anything further out is rejected with a 400. There is no long-horizon scheduler behind this endpoint. To call someone next week, hold the request in your own system until it is inside the window.
A campaign’s on-demand run can be dialing at the same time as a CSV run, and the on-demand run has first claim on the campaign’s max_concurrent_calls budget. While on-demand traffic is flowing, the CSV run visibly dials fewer calls per tick — and nothing in the Studio explains the slowdown. Raise the campaign’s concurrency if both need to run hard at once.
Pause, Resume and Stop on a campaign act on its CSV runs, not on the on-demand run. A paused campaign still accepts and dials on-demand calls. Only a stopped or failed campaign refuses new requests, and calls you already sent keep going. To halt those, cancel them from On-Demand activity.
A CSV run is frozen at launch: it keeps immutable snapshots of the settings, schedule and agent. The on-demand run is not. It re-reads the campaign’s dialing settings and schedule on every request, which is why its cards are labelled “current” rather than “snapshot”. Editing them therefore changes on-demand calling immediately, with no relaunch — convenient, but easy to do by accident.Caller IDs are the exception. On-demand calls come from the phone numbers of the agent the campaign had when its first on-demand call arrived. If you change the campaign’s agent later, the new agent handles the calls, but they still go out from the first agent’s numbers, and a contact who calls back reaches the first agent. Adding or removing numbers on that first agent does take effect on the next dial.
The response is fire-and-forget. There is no key-authenticated way to ask how a call went — outcomes live in the Studio, on the On-Demand activity list and in Call History.

Compliance Still Applies

Placing a call through the API skips the CSV, not the rules. Every compliance gate is evaluated again at dial time, exactly as it is for a CSV run:
  • The campaign’s own Calling Hours from its Schedule tab. A call requested outside them waits in the queue and is dialed when the window opens, and you can still cancel it while it waits.
  • Legal calling hours for the contact’s resolved timezone, and TCPA restrictions — see Scheduling.
  • Prior express written consent, and voice opt-out. A contact without has_pewc: true and a pewc_date, or with is_voice_call_opted_out: true, is Blocked and never dialed.
  • DNC scrubbing, with its scrub fee — see Compliance & DNC.
  • Frequency caps.
An insufficient wallet balance pauses the on-demand run, the same as for any other campaign calling — including when auto top-up is turned on but suspended, which counts as off. The next request the API accepts switches that run back on, and it pauses again at the next dial if the balance is still too low, so add funds before you send more traffic. A call that has already connected is charged minute by minute from when it’s answered, and it ends at the next minute if the balance can’t cover it. See Charges while a call is live.
Because a draft campaign accepts on-demand calls, the launch checklist’s attested-disclosure step can be bypassed. Make sure your agent’s disclosure is configured before you send live traffic through this endpoint.

Where On-Demand Activity Shows Up

This keeps your CSV run reporting comparable across launches, with Compare as the one exception. When you need the on-demand picture, go to the tab.

Where to go next

API Keys

Create and revoke the keys this API authenticates with.

Campaign Setup

Assign the agent, check the numbers it calls from, and set the dialing settings on-demand calls will use.