Skip to main content

Batch calls

The batchcall resource runs bulk outbound phone campaigns. Upload a recipients file, then launch or schedule the campaign.

Upload recipients

upload reads a .csv, .xls, or .xlsx file (max 5 MB), uploads it, and waits for parsing, returning the parsed batch.

const batch = await client.batchcall.upload({ filePath: "./leads.csv" });

Options: filePath (required), batchId (replace the file on an existing batch), waitForParse (default true), poll interval / timeout.

Track parsing progress

Parsing runs after the file uploads. In Node.js, upload returns a handle that is both awaitable and an event emitter, so you can subscribe to progress with .on. In Go, pass an OnParsing callback; in Rust, pass an on_parsing callback. The parsed batch is the return value, and failures come back as the returned error.

const job = client.batchcall.upload({ filePath: "./leads.csv" });

job.on("parsing", () => {}); // parsing started
job.on("parsed", (batch) => {}); // parsing finished, batch ready to launch
job.on("parse_failed", (err) => {}); // parsing failed
job.on("error", (err) => {}); // any failure: upload, parse, or timeout

const batch = await job; // the handle is also awaitable

Create a campaign

const campaign = await client.batchcall.create({
batchName: "Q3 outreach",
phoneNumberId: "pn_1",
routingRuleId: "rr_1",
batchId, // from upload
timing: "scheduled",
scheduledDate: "2026-07-01",
scheduledTime: "09:30",
});

Required: batchName, phoneNumberId, routingRuleId. Scheduling: timing (immediate or scheduled), timezone, scheduledDate / scheduledTime, allowedFrom / allowedUntil, daysOfWeek. Also retry, webhook, saveAsDraft.

Manage a campaign

await client.batchcall.list({ status: "running" });
await client.batchcall.get(batchId);
await client.batchcall.update(batchId, { scheduledTime: "10:00" });
await client.batchcall.cancel(batchId, "graceful"); // or "immediate"
await client.batchcall.delete(batchId);
await client.batchcall.stats(batchId);

Records

A batch's per-number records are available on the records sub-resource.

await client.batchcall.records.list(batchId, { status: "not connected" });
await client.batchcall.records.update(batchId, recordId, { phoneNumber: "+14155550123" });
await client.batchcall.records.delete(batchId, [recordId]);

const csv = await client.batchcall.records.export(batchId); // CSV text

The batch object

Returned by batchcall.create, list, get, update, cancel, and (resolved) upload.

FieldTypeDescription
batchIdstringUnique batch id.
batchNamestringDisplay name.
statusstringBatch status (parsing, parsed, running, completed, cancelled, …).
phoneNumberIdstringOutbound phone number id.
routingRuleIdstringOutbound routing rule id.
timingstringimmediate or scheduled.
recordsUploadednumberCount of parsed recipient rows.
progressnumberCompletion percentage (list view only).

The record object

Returned by batchcall.records.list and update.

FieldTypeDescription
recordIdstringUnique record id.
batchIdstringParent batch id.
phoneNumberstringRecipient number.
statusstringDisplay status (scheduled, not connected, …).
callIdstringPlaced call id, once dialed.
reasonstringFailure or outcome reason.
attemptsnumberNumber of dial attempts made.
callDurationnumberCall length in seconds, null if not connected.
metadataobjectPer-row custom fields from the uploaded file.

The stats object

Returned by batchcall.stats. Alongside the fields below, the object carries one numeric key per status bucket (scheduled, running, completed, not connected, …).

FieldTypeDescription
batchIdstringBatch id.
statusstringOverall batch status.
totalnumberTotal number of records.

Got a Question? Ask us on discord