Skip to main content
POST
/
v1
/
calls
/
batch
Create batch campaign
curl --request POST \
  --url https://api.nixflex.com/v1/calls/batch
Creates a batch campaign: queues many outbound calls under one campaign ID. Useful for appointment reminders, lead qualification, surveys.

Request

curl -X POST https://api.nixflex.com/v1/calls/batch \
  -H "Authorization: Bearer KEY_ID:KEY_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "agent_125207e452f8714a",
    "from_number": "+447446466847",
    "name": "Tuesday appointment reminders",
    "prompt": "You are Sarah from Bright Smile Dental. Call to remind the patient about their check-up tomorrow and confirm they can attend.",
    "timezone": "Europe/London",
    "recipients": [
      { "phone": "+447111000001" },
      { "phone": "+447111000002", "variables": { "patient_name": "John" } },
      { "phone": "+447111000003" }
    ],
    "schedule_type": "schedule",
    "scheduled_date": "2026-06-15",
    "window_start_minutes": 540,
    "window_end_minutes": 1080,
    "window_days": ["mon","tue","wed","thu","fri"]
  }'

Body parameters

FieldTypeRequiredNotes
agent_idstringYesAgent used for all calls in this batch
promptstringYesThe call purpose for every call in the campaign - what the agent should say and why it is calling. Per-recipient prompt_override replaces it for that recipient.
namestringNoDisplay name for the campaign
from_numberstringSee noteYour Twilio number to dial from. Optional only when the agent has exactly one outbound-enabled number (it auto-resolves). If the agent has multiple numbers attached, this field is required - the launch fails otherwise.
recipientsarrayYesRecipient objects (see below)
skip_invalidboolNoDefault false: reject the whole request if any phone is invalid. true: dial valid numbers only; invalid ones are listed in the response.
schedule_typeenumNonow (launch immediately, default) or schedule
scheduled_datedateIf scheduleYYYY-MM-DD - the day the campaign becomes due
window_start_minutesintNoCalling window start, minutes since midnight (540 = 9:00am)
window_end_minutesintNoCalling window end, minutes since midnight (1080 = 6:00pm)
window_daysarrayNoAllowed weekdays, e.g. ["mon","tue","wed","thu","fri"]
timezonestringNoIANA timezone the calling window runs in, e.g. Europe/London, Asia/Dubai, America/New_York. Invalid values are rejected with invalid_timezone.

Recipient object

{
  "phone": "+447111000001",
  "variables": { "patient_name": "Sarah" },
  "prompt_override": "Optional - replaces the campaign prompt for this recipient only"
}
All variables are automatically injected as context for the agent - you do not need {{placeholders}} in your prompt.

Calling window and timezone

Scheduled campaigns do not fire at midnight - they fire inside the calling window, in local time:
  • The scheduler checks every 60 seconds. A campaign that is due but outside its window stays scheduled and is re-checked each minute - it fires within a minute of the window opening.
  • The window runs in this priority of timezones: campaign timezone (if you sent one) -> the agent’s timezone -> Europe/London.
  • Resellers: your end-user picks their timezone in your app, you send it per campaign - their choice wins over the agent default.
  • Overnight windows are supported (window_start_minutes greater than window_end_minutes, e.g. 18:00-02:00).
  • No window set = the campaign fires when the date is due (legacy behaviour).
One campaign = one timezone. Calling recipients across multiple countries? Split them by region into separate campaigns, each with its own timezone.

Response

201 Created (schedule_type now launches immediately):
{
  "campaign_id": "batchcall_7f8fe206a5522cb7",
  "status": "running",
  "valid_count": 3,
  "invalid_count": 0,
  "invalid": []
}
With schedule_type: schedule the response returns status: scheduled and the campaign fires inside its window on the scheduled date.

Behaviour

  • Calls are queued and processed respecting your per-key concurrent call limit
  • Each recipient becomes one outbound call with its own call_id
  • Failed calls are logged but do not stop the campaign
  • Voicemail detection runs per call; detected voicemails end cleanly with ended_reason: voicemail_detected

Errors

CodeCause
missing_fieldprompt missing - every campaign needs a call purpose
invalid_phone_formatOne or more recipient phones invalid (response lists them; resend with skip_invalid: true to dial valid only)
campaign_creation_failedIncludes invalid_timezone (bad IANA value) and from_number ownership failures - the message states the exact reason

Launching a scheduled campaign

A schedule_type: schedule campaign fires automatically inside its window. You can also launch it manually with Launch batch.