Skip to main content

Overview

Batch calls allow you to:
  • Upload lists of phone numbers
  • Process hundreds of calls automatically
  • Monitor progress in real-time
  • Get detailed reports
  • Handle errors gracefully

Creating a Batch

Upload via API

curl -X POST http://localhost:8010/api/batch-calls \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -F "file=@calls.csv" \
  -F "agent_id=agent-123" \
  -F "campaign_id=camp-456"

CSV Format

phone,name,email,customer_id,custom_field
+1234567890,John Doe,john@example.com,cust-123,value1
+1234567891,Jane Smith,jane@example.com,cust-124,value2
+1234567892,Bob Wilson,bob@example.com,cust-125,value3

JSON Format

[
  {
    "phone": "+1234567890",
    "name": "John Doe",
    "email": "john@example.com",
    "customer_id": "cust-123",
    "custom_data": {
      "order_id": "ORD-456",
      "amount": 99.99
    }
  },
  {
    "phone": "+1234567891",
    "name": "Jane Smith",
    "email": "jane@example.com",
    "customer_id": "cust-124",
    "custom_data": {
      "order_id": "ORD-457",
      "amount": 149.99
    }
  }
]

Batch Configuration

Python Example

from Service.BatchCallService import BatchCallService
from models.models import BatchCallRequest

service = BatchCallService()

batch_request = BatchCallRequest(
    agent_id="agent-123",
    file_url="s3://bucket/calls.csv",  # or local file path
    campaign_name="Q1 Sales Outreach",
    concurrency=5,  # Max parallel calls
    retry_failed=True,
    column_mapping={
        "phone": "phone_number",
        "name": "customer_name",
        "email": "customer_email"
    },
    metadata={
        "campaign_id": "camp-456",
        "priority": "normal"
    }
)

batch = await service.create_batch(batch_request)
print(f"Batch created: {batch.id}")

Monitoring Progress

Real-time Status

# Get batch status
curl -X GET http://localhost:8010/api/batch-calls/{batch_id} \
  -H "Authorization: Bearer YOUR_TOKEN"
Response:
{
  "batch_id": "batch-789",
  "status": "in_progress",
  "total_calls": 1000,
  "completed": 450,
  "failed": 12,
  "pending": 538,
  "progress_percent": 45,
  "estimated_completion": "2024-01-15T15:30:00Z",
  "start_time": "2024-01-15T14:00:00Z",
  "errors": [
    {
      "row": 5,
      "phone": "+1234567895",
      "error": "Invalid phone number",
      "retry_count": 1
    }
  ]
}

WebSocket Updates

// Real-time batch progress
const ws = new WebSocket('ws://localhost:8010/ws/batch/{batch_id}');

ws.addEventListener('message', (event) => {
    const update = JSON.parse(event.data);
    console.log(`Progress: ${update.completed}/${update.total}`);
    console.log(`Status: ${update.status}`);
});

Batch Processing Flow

1. Upload File

2. Validate Data

3. Parse CSV/JSON

4. Check Phone Numbers

5. Create Call Records

6. Queue Calls

7. Execute (with concurrency limit)

8. Handle Errors & Retries

9. Generate Report

Advanced Configuration

Scheduling Batch Execution

batch_request = BatchCallRequest(
    agent_id="agent-123",
    file_url="s3://bucket/calls.csv",
    scheduled_start_time="2024-01-20 09:00:00",
    scheduled_timezone="America/New_York",
    concurrent_calls=10,
)

batch = await service.schedule_batch(batch_request)

Custom Timing

batch_request = BatchCallRequest(
    agent_id="agent-123",
    file_url="s3://bucket/calls.csv",
    call_timing={
        "business_hours_only": True,
        "start_hour": 9,
        "end_hour": 17,
        "timezone": "America/New_York",
        "skip_weekends": True,
        "delay_between_calls": 5  # seconds
    }
)

Retry Logic

batch_request = BatchCallRequest(
    agent_id="agent-123",
    file_url="s3://bucket/calls.csv",
    retry_policy={
        "max_retries": 3,
        "retry_delay": 300,  # 5 minutes
        "exponential_backoff": True,
        "retry_on": ["busy", "no_answer", "timeout"]
    }
)

Error Handling

Invalid Phone Numbers

# Enable validation
batch_request = BatchCallRequest(
    agent_id="agent-123",
    file_url="s3://bucket/calls.csv",
    validate_phone_numbers=True,
    invalid_phone_handling="skip"  # or "use_as_is"
)

Data Validation

# Validate data before processing
async def validate_batch_data(file_path: str):
    issues = []
    
    with open(file_path) as f:
        reader = csv.DictReader(f)
        for idx, row in enumerate(reader, start=1):
            if not row.get('phone'):
                issues.append(f"Row {idx}: Missing phone number")
            
            if not validate_phone_number(row['phone']):
                issues.append(f"Row {idx}: Invalid phone format")
            
            if len(issues) > 10:  # Stop after 10 errors
                break
    
    return issues

Results and Reporting

Get Batch Results

# Download results
curl -X GET http://localhost:8010/api/batch-calls/{batch_id}/results \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -o results.csv

Results CSV Format

phone,name,status,call_id,duration_seconds,recording_url,transcript,error_message
+1234567890,John Doe,completed,call-1,180,https://...,Agent: Hello...,
+1234567891,Jane Smith,failed,call-2,,https://...,,(busy signal)
+1234567892,Bob Wilson,in_progress,call-3,45,,,...

Generate Report

report = await service.generate_report(batch_id)

print(f"Total Calls: {report.total}")
print(f"Completed: {report.completed}")
print(f"Failed: {report.failed}")
print(f"Success Rate: {report.success_rate * 100:.1f}%")
print(f"Average Duration: {report.avg_duration}s")
print(f"Average Cost: ${report.total_cost:.2f}")

Report Export

# Export as PDF
curl -X GET http://localhost:8010/api/batch-calls/{batch_id}/report.pdf \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -o report.pdf

# Export as JSON
curl -X GET http://localhost:8010/api/batch-calls/{batch_id}/report.json \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -o report.json

Stopping a Batch

Pause Batch

curl -X POST http://localhost:8010/api/batch-calls/{batch_id}/pause \
  -H "Authorization: Bearer YOUR_TOKEN"

Resume Batch

curl -X POST http://localhost:8010/api/batch-calls/{batch_id}/resume \
  -H "Authorization: Bearer YOUR_TOKEN"

Cancel Batch

curl -X POST http://localhost:8010/api/batch-calls/{batch_id}/cancel \
  -H "Authorization: Bearer YOUR_TOKEN"

Cost Optimization

Batch Pricing Calculation

batch_report = await service.get_batch_report(batch_id)

cost_breakdown = {
    "outbound_calls": batch_report.completed_calls * 0.05,
    "call_duration": batch_report.total_minutes * 0.01,
    "transcription": batch_report.transcribed_minutes * 0.01,
    "storage": batch_report.recording_size_gb * 0.023,
}

total_cost = sum(cost_breakdown.values())
print(f"Total Batch Cost: ${total_cost:.2f}")

Cost-saving Tips

  1. Concurrency: Batch calls don’t overlap, so you pay sequentially
  2. Disable Recording: Skip recording for analytics-only calls
  3. Disable Transcription: For calls without transcript needs
  4. Off-peak Hours: Schedule batches during off-peak times

Performance

Optimal Settings

# For 10,000 calls
batch_request = BatchCallRequest(
    agent_id="agent-123",
    file_url="s3://bucket/calls.csv",
    concurrency=15,  # Parallel calls
    timeout_per_call=300,  # 5 minutes
    batch_size=100,  # Process in chunks
)

Monitoring Performance

# Check system status
curl -X GET http://localhost:8010/api/system/status \
  -H "Authorization: Bearer YOUR_TOKEN"
Response:
{
  "active_batches": 2,
  "active_calls": 8,
  "queue_size": 150,
  "cpu_usage": 45,
  "memory_usage": 62,
  "disk_usage": 28
}

Examples

Sales Outreach Campaign

batch = await service.create_batch({
    "agent_id": "sales-agent-123",
    "file_url": "s3://leads/q1-leads.csv",
    "campaign_name": "Q1 Sales Push",
    "concurrent_calls": 10,
    "schedule": {
        "start_time": "2024-01-15 09:00:00",
        "end_time": "2024-01-15 17:00:00",
        "timezone": "America/New_York"
    }
})

Customer Survey Campaign

batch = await service.create_batch({
    "agent_id": "survey-agent-456",
    "file_url": "s3://surveys/customer-list.csv",
    "campaign_name": "Customer Satisfaction Survey",
    "record_call": True,
    "transcribe_call": True,
    "max_retries": 2,
})

Appointment Reminders

batch = await service.create_batch({
    "agent_id": "reminder-agent-789",
    "file_url": "s3://reminders/upcoming-appointments.json",
    "campaign_name": "Appointment Reminders",
    "schedule": {
        "time": "24_hours_before",
        "timezone": "America/Los_Angeles"
    }
})

Next Steps

Scheduler

Schedule individual calls for later execution.