API Reference
Batch Call Upload

Batch Call Upload API

Upload multiple calls (1-100) in a single API request for efficient bulk import.

Overview

The Batch Upload API allows you to import historical calls or integrate with external systems to automatically upload calls to Aila.

Endpoint

POST /v1/calls/batch-upload

Authentication

Requires API key in header:

Authorization: Bearer YOUR_API_KEY

Request Format

Request Body

{
  "calls": [
    {
      "external_id": "call_12345",
      "audio_url": "https://yourdomain.com/recordings/call1.mp3",
      "user_email": "agent@company.com",
      "contact_name": "John Doe",
      "contact_phone": "+15551234567",
      "contact_email": "john@example.com",
      "call_date": "2025-01-15T14:30:00Z",
      "direction": "outbound",
      "duration": 350,
      "metadata": {
        "campaign": "Q1 2025",
        "product": "Enterprise Plan"
      }
    },
    {
      "external_id": "call_12346",
      "audio_url": "s3://your-bucket/call2.mp3",
      "user_email": "agent2@company.com",
      "contact_name": "Jane Smith",
      "contact_phone": "+15559876543",
      "call_date": "2025-01-15T15:45:00Z",
      "direction": "inbound",
      "duration": 420
    }
  ]
}

Parameters

Required:

  • external_id - Your unique identifier for the call
  • audio_url - URL to audio file (HTTP/HTTPS or S3)
  • user_email - Team member's email
  • call_date - ISO 8601 timestamp

Optional:

  • contact_name - Contact's full name
  • contact_phone - Phone number (E.164 format recommended)
  • contact_email - Contact's email
  • direction - inbound or outbound
  • duration - Call duration in seconds
  • metadata - Custom key-value pairs

Audio File Requirements

Supported Formats:

  • MP3
  • WAV
  • M4A
  • AAC

File Access:

  • Public URLs (no auth required)
  • Signed S3 URLs
  • Aila S3 bucket (auto-detected)

File Size:

  • Maximum: 2GB per file
  • Recommended: Under 200MB

Response Format

Success Response

{
  "success": true,
  "batch_id": "batch_abc123",
  "calls_submitted": 2,
  "status": "processing"
}

Tracking Batch Status

GET /v1/calls/batch-upload/{batch_id}

Response:

{
  "success": true,
  "batch_id": "batch_abc123",
  "status": "processing",
  "submitted_at": "2025-01-15T16:00:00Z",
  "total_calls": 2,
  "processed": 1,
  "failed": 0,
  "pending": 1,
  "calls": [
    {
      "external_id": "call_12345",
      "status": "completed",
      "aila_call_id": "aila_xyz789",
      "processed_at": "2025-01-15T16:03:00Z"
    },
    {
      "external_id": "call_12346",
      "status": "processing",
      "progress": "transcribing"
    }
  ]
}

Error Response

{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid calls array",
    "details": {
      "calls": [
        {
          "index": 0,
          "external_id": "call_12345",
          "errors": [
            "audio_url is not accessible",
            "duration must be positive number"
          ]
        }
      ]
    }
  }
}

Batch Status Values

  • submitted - Batch received, queued for processing
  • processing - Calls being processed
  • completed - All calls processed successfully
  • partial - Some calls succeeded, some failed
  • failed - All calls failed

Individual Call Status

  • pending - Waiting to process
  • downloading - Fetching audio file
  • transcribing - Converting speech to text
  • analyzing - AI analysis in progress
  • completed - Fully processed
  • failed - Processing failed

Automatic Actions

When batch upload completes, Aila automatically:

  1. Creates Users - New users created from user_email
  2. Creates Contacts - New contacts from contact info
  3. Matches Existing - Links to existing users/contacts
  4. Transcribes - Generates full transcript
  5. Analyzes - Extracts AI insights
  6. Scores Quality - Evaluates against checklists
  7. Syncs CRM - Updates connected systems

Examples

JavaScript/Node.js

const fetch = require('node-fetch');
 
async function batchUploadCalls(calls) {
  const response = await fetch('https://api.aila.com/v1/calls/batch-upload', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.AILA_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ calls })
  });
 
  const result = await response.json();
  console.log('Batch ID:', result.batch_id);
 
  // Poll for status
  const batchId = result.batch_id;
  while (true) {
    const statusResponse = await fetch(
      `https://api.aila.com/v1/calls/batch-upload/${batchId}`,
      {
        headers: {
          'Authorization': `Bearer ${process.env.AILA_API_KEY}`
        }
      }
    );
 
    const status = await statusResponse.json();
    console.log(`Status: ${status.status}, Processed: ${status.processed}/${status.total_calls}`);
 
    if (status.status === 'completed' || status.status === 'partial') {
      return status;
    }
 
    await new Promise(resolve => setTimeout(resolve, 5000)); // Wait 5s
  }
}
 
// Usage
const calls = [
  {
    external_id: 'call_001',
    audio_url: 'https://example.com/call1.mp3',
    user_email: 'agent@company.com',
    contact_name: 'John Doe',
    call_date: new Date().toISOString()
  }
];
 
batchUploadCalls(calls);

Python

import requests
import time
import os
 
def batch_upload_calls(calls):
    response = requests.post(
        'https://api.aila.com/v1/calls/batch-upload',
        headers={
            'Authorization': f'Bearer {os.environ["AILA_API_KEY"]}',
            'Content-Type': 'application/json'
        },
        json={'calls': calls}
    )
 
    result = response.json()
    batch_id = result['batch_id']
    print(f'Batch ID: {batch_id}')
 
    # Poll for status
    while True:
        status_response = requests.get(
            f'https://api.aila.com/v1/calls/batch-upload/{batch_id}',
            headers={'Authorization': f'Bearer {os.environ["AILA_API_KEY"]}'}
        )
 
        status = status_response.json()
        print(f'Status: {status["status"]}, Processed: {status["processed"]}/{status["total_calls"]}')
 
        if status['status'] in ['completed', 'partial']:
            return status
 
        time.sleep(5)
 
# Usage
calls = [
    {
        'external_id': 'call_001',
        'audio_url': 'https://example.com/call1.mp3',
        'user_email': 'agent@company.com',
        'contact_name': 'John Doe',
        'call_date': '2025-01-15T14:30:00Z'
    }
]
 
batch_upload_calls(calls)

Best Practices

Batch Sizing

  • Recommended: 10-50 calls per batch
  • Maximum: 100 calls per batch
  • Larger batches for better efficiency
  • Smaller batches for faster per-call feedback

Error Handling

const failed = status.calls.filter(c => c.status === 'failed');
if (failed.length > 0) {
  console.error('Failed calls:', failed);
  // Retry failed calls
  const retryCalls = failed.map(f =>
    originalCalls.find(c => c.external_id === f.external_id)
  );
  await batchUploadCalls(retryCalls);
}

Audio File Hosting

Best Practices:

  • Use signed URLs for private files
  • Set reasonable expiration (1-24 hours)
  • Ensure high availability
  • Consider using S3 for reliability

Progress Monitoring

Poll every 5-10 seconds:

async function waitForBatch(batchId) {
  const maxWait = 30 * 60 * 1000; // 30 minutes
  const pollInterval = 5000; // 5 seconds
  const startTime = Date.now();
 
  while (Date.now() - startTime < maxWait) {
    const status = await getBatchStatus(batchId);
 
    if (status.status === 'completed' || status.status === 'partial') {
      return status;
    }
 
    await new Promise(resolve => setTimeout(resolve, pollInterval));
  }
 
  throw new Error('Batch processing timeout');
}

Troubleshooting

Audio File Not Accessible

Error: "audio_url is not accessible"

Solutions:

  • Verify URL is publicly accessible
  • Check signed URL hasn't expired
  • Ensure CORS headers if needed
  • Test URL in browser

User Not Found

Error: "user_email not found"

Solution:

  • Create user first via dashboard
  • Or API will auto-create (if enabled)
  • Verify email format
  • Check organization membership

Processing Timeout

If calls stuck in processing:

  1. Check batch status endpoint
  2. Review individual call errors
  3. Verify audio file format
  4. Contact support with batch_id

Rate Limits

  • Batches per hour: 100
  • Calls per hour: 10,000
  • Concurrent batches: 10

Enterprise customers can request higher limits.

Next Steps