Skip to Content
Builder Docs
Telephony, Calls & Campaigns

Running Bulk Campaigns

Prepare campaign CSVs, configure caller-ID pools, calling schedules, retry rules, circuit breakers, and launch, monitor, or redial outbound campaigns safely.

Running Bulk Campaigns

Talkar's campaign engine turns a CSV lead list into structured outbound calls while respecting calling hours, caller-ID rotation, organization concurrency caps, and automatic failure protection. Campaigns always execute the workflow's Published snapshot.


Step 1: Prepare & Upload Your CSV

Upload your .csv file (under 10 MB) via POST /api/v1/s3/presigned-upload-url, then create the campaign via POST /api/v1/campaign/create (passing required source_type: "csv"):

  1. Strict phone_number Formatting (+ Required): Every non-empty phone_number value must start with + (E.164 format, e.g., +919876543210). Campaign creation fails immediately and reports the exact invalid row numbers if any row omits +.
  2. UTF-8, Headers & Row Count: Files must be valid UTF-8 with at least 1 data row. Column headers are automatically trimmed and lowercased on ingest.
  3. Duplicate Lead Rejection: Duplicate phone_number entries within the same CSV (compared after stripping spaces, -, (, ), and .) are rejected at creation time.
  4. Required Template Variable Validation: Every bare workflow prompt variable ({{customer_name}}) without a nested prefix (initial_context.*, gathered_context.*) or default/fallback filter (| default, | fallback:value)—excluding system variables provider, campaign_id, and source_uuid—must exist as a CSV column header and be non-empty in every single row. (Add | default if using {{current_time_*}} or {{current_weekday_*}} inside workflows destined for campaigns.)
  5. Optional Caller-ID Override (caller_number): Include caller_number per row to prefer a verified DID from the trunk pool. If that CLI stays busy past 20s, the dispatcher automatically falls back to another active CLI in the pool.

3-Step API CSV Upload & Create Flow

When automating campaigns from your CRM or n8n.talkar.in:

  1. Request a 15-minute presigned S3 upload URL (POST /api/v1/s3/presigned-upload-url):
{
  "file_name": "leads_nov.csv",
  "file_size": 24576,
  "content_type": "text/csv"
}

Returns {"upload_url": "https://...", "file_key": "campaigns/42/<uuid>_leads_nov.csv", "expires_in": 900}. 2. Upload raw CSV bytes directly to upload_url via HTTP PUT:

curl -X PUT "<upload_url>" \
  -H "Content-Type: text/csv" \
  --data-binary @leads_nov.csv
  1. Create the campaign (POST /api/v1/campaign/create) passing file_key as source_id:
{
  "name": "November Sales Outreach",
  "workflow_id": 128,
  "source_type": "csv",
  "source_id": "campaigns/42/<uuid>_leads_nov.csv",
  "telephony_configuration_id": 7,
  "max_concurrency": 5,
  "retry_config": {
    "enabled": true,
    "max_retries": 2,
    "retry_delay_seconds": 120,
    "retry_on_busy": true,
    "retry_on_no_answer": true,
    "retry_on_voicemail": true
  },
  "schedule_config": {
    "enabled": true,
    "timezone": "Asia/Kolkata",
    "slots": [
      { "day_of_week": 0, "start_time": "10:00", "end_time": "19:00" },
      { "day_of_week": 1, "start_time": "10:00", "end_time": "19:00" }
    ]
  },
  "circuit_breaker": {
    "enabled": true,
    "failure_threshold": 0.5,
    "window_seconds": 120,
    "min_calls_in_window": 5
  }
}

Step 2: Trunks, Rate Limits, Concurrency & Progress

SettingDefault / RangeBehavior
telephony_configuration_idOptional (uses org default trunk)Must reference an active trunk with active numbers. Omitting uses your default outbound trunk (HTTP 400 if none exists).
rate_limit_per_secondRead-only default 1 call/secServer-enforced outbound pacing limit surfaced on campaign progress responses (not user-editable on /create or PATCH).
max_concurrency1–100 (optional)Caps simultaneous live calls for this campaign. Returns HTTP 400 if the target trunk has 0 active phone numbers, and effectively caps at min(org_limit, active_from_numbers). Leave null to share the org pool.
CLI (from_number) PoolingAutomaticEach call leases a free active number on the trunk (20s wait limit for explicit caller_number) and releases it upon hangup/failure.

Leads vs. Call Attempts & Completion Progress

  • Leads vs. Attempts: One CSV lead row can trigger multiple call attempts (1 + max_retries) when busy/no-answer/voicemail retries run. Use GET /api/v1/campaign/{id}/runs with latest_per_lead and sort_by to view either per-lead outcomes or every attempt.
  • Completion Clamp: Live progress bars clamp at 99.9% while the final calls finish, with a 30s inactivity grace period before marking a campaign completed.

Step 3: Retries, Calling Schedules & Circuit Breaker

Automatic Retries (retry_config)

Configure how unsuccessful connection attempts reschedule with randomized ±20% jitter (0.8x–1.2x) to avoid synchronized retry storms:

  • enabled: true / false
  • max_retries (0–10): Maximum retry attempts per lead (total attempts = max_retries + 1).
  • retry_delay_seconds (30–3600): Base wait window (default 120s).
  • Trigger toggles: retry_on_busy, retry_on_no_answer, and retry_on_voicemail. Initiation failures also retry while retry_count < max_retries.

Pass `retry_config` fields explicitly in API calls

If retry_config is completely omitted on POST /api/v1/campaign/create, Talkar defaults to max_retries: 1 and retry_on_voicemail: false. If you pass a partial JSON object ({"enabled": true}), omitted nested fields adopt API schema defaults (max_retries: 2, retry_on_voicemail: true). Always pass all fields explicitly in API integrations.

Calling Hours & Business Schedules (schedule_config)

{
  "enabled": true,
  "timezone": "Asia/Kolkata",
  "slots": [
    { "day_of_week": 0, "start_time": "10:00", "end_time": "19:00" },
    { "day_of_week": 1, "start_time": "10:00", "end_time": "19:00" },
    { "day_of_week": 2, "start_time": "10:00", "end_time": "19:00" },
    { "day_of_week": 3, "start_time": "10:00", "end_time": "19:00" },
    { "day_of_week": 4, "start_time": "10:00", "end_time": "19:00" }
  ]
}
  • day_of_week: 0 = Monday through 6 = Sunday (1 to 50 slots).
  • timezone: Valid IANA timezone (e.g. "Asia/Kolkata", "America/New_York", "UTC").
  • Window validation: start_time and end_time cannot be identical (start_time != end_time). Overnight slots (start_time > end_time, e.g. 22:00 to 02:00) are supported automatically.
  • Outside window behavior: Campaign remains running cleanly until the next open slot—it does not fail or pause.

Sliding-Window Circuit Breaker (circuit_breaker)

  • Fields & Bounds:
    • enabled (default true)
    • failure_threshold (0.0 – 1.0, default 0.5 = 50%)
    • window_seconds (30 – 600, default 120)
    • min_calls_in_window (1 – 100, default 5)
  • What trips it: Only telephony/carrier failures (failed, error, or initiation failures). Normal unanswered outcomes (busy, no-answer) do not trip it.
  • Recovery: Trips move the campaign to paused (paused_reason = "circuit_breaker"). Resuming clears the rolling window cleanly.

Step 4: Campaign Lifecycle APIs, Auto-Pauses & CSV Reports

Lifecycle Endpoints & Controls

ActionEndpointNotes
Create / UpdatePOST /api/v1/campaign/create / PATCH /api/v1/campaign/{id}Create requires source_type: "csv".
Start / Pause / Resume / CancelPOST .../start, .../pause, .../resume, .../cancelActive in-flight calls finish cleanly on pause.
DeleteDELETE /api/v1/campaign/{id}Removes campaign record when stopped/completed.
One-Click RedialPOST /api/v1/campaign/{id}/redialCreates a fresh follow-up campaign for non-connected leads (allowed once on a completed campaign).
Runs & Source CSVGET .../runs, GET .../source-download-urlQuery runs (latest_per_lead, sort_by) or fetch original CSV via signed download link.

Auto-Pause & Halt Conditions

State / paused_reasonTrigger Condition
circuit_breakerFailure rate >= failure_threshold inside window_seconds.
concurrency_limit_exhaustedOrganization call slots stayed saturated across 6 consecutive checks.
phone_number_pool_exhaustedZero free active CLIs in trunk pool across 3 consecutive checks.
quota_exceeded / wallet_depleted / spending_cap_exceededPre-call wallet/cap exhaustion (5 transient quota checks pause automatically).
failed3 consecutive fatal batch ingestion/dispatch errors.
policy_suspended / under_reviewCompliance suspension or manual review lock.

Campaign Export Reports

Download campaign CSV reports with optional start_date and end_date filters. Exports automatically flatten per-lead extracted_variables alongside canonical outcomes and core audit columns (Campaign ID, Agent ID, Agent Definition ID, Created At, phone numbers, duration, disposition, and tags).

On this page