Submitting Call Analysis
Learn how to submit call recordings to the CallCov API for AI-powered analysis. This guide covers audio file uploads, metadata submission, and best practices for integration.
Overviewβ
CallCov provides two methods for submitting calls:
- File Upload - Upload audio files directly (recommended for most use cases)
- URL Submission - Provide URLs to audio files stored elsewhere
Both methods return an analysis ID for tracking the processing status.
Endpointβ
POST /api/v1/calls/analyze
Authentication: Required (API Key)
Method 1: File Uploadβ
Upload audio files directly to CallCov for analysis.
Supported Audio Formatsβ
| Format | Extension | Max Size | Recommended |
|---|---|---|---|
| WAV | .wav | 100 MB | β Yes |
| MP3 | .mp3 | 50 MB | β Yes |
| M4A | .m4a | 50 MB | β Yes |
| FLAC | .flac | 100 MB | Supported |
| OGG | .ogg | 50 MB | Supported |
For best results, use WAV or FLAC formats with:
- Sample rate: 16 kHz or higher
- Bit depth: 16-bit minimum
- Channels: Mono or stereo (separate channels preferred for multi-speaker)
Basic File Uploadβ
import requests
API_KEY = "your_api_key_here"API_URL = "https://api.callcov.com/api/v1"
# Prepare the file and metadatafiles = { "audio_file": open("call_recording.wav", "rb")}
data = { "agent_id": "AGENT_001", "contact_id": "CONTACT_12345", "call_direction": "inbound", "call_timestamp": "2024-01-15T10:30:00Z"}
headers = {"X-API-Key": API_KEY}
# Submit for analysisresponse = requests.post( f"{API_URL}/calls/analyze", headers=headers, files=files, data=data)
result = response.json()print(f"Analysis ID: {result['analysis_id']}")print(f"Status: {result['status']}")Request Parametersβ
| Parameter | Type | Required | Description |
|---|---|---|---|
audio_file | File | Yes | The audio file to analyze |
agent_id | String | Yes | Unique identifier for the agent |
contact_id | String | Yes | Unique identifier for the contact/customer |
call_direction | String | No | inbound or outbound |
call_timestamp | String | No | ISO 8601 timestamp of when call occurred |
metadata | Object | No | Additional custom metadata (JSON string) |
Responseβ
{
"analysis_id": "anl_1a2b3c4d5e",
"status": "processing",
"created_at": "2024-01-15T10:30:05Z",
"estimated_completion": "2024-01-15T10:32:00Z",
"webhook_url": "https://your-app.com/webhooks/callcov"
}
Method 2: URL Submissionβ
Submit a URL to an audio file hosted elsewhere. CallCov will download and process the file.
import requests
API_KEY = "your_api_key_here"API_URL = "https://api.callcov.com/api/v1"
# Submit audio URLpayload = { "audio_url": "https://your-storage.com/recordings/call_12345.wav", "agent_id": "AGENT_001", "contact_id": "CONTACT_12345", "call_direction": "outbound", "call_timestamp": "2024-01-15T14:20:00Z"}
headers = { "X-API-Key": API_KEY, "Content-Type": "application/json"}
response = requests.post( f"{API_URL}/calls/analyze", headers=headers, json=payload)
result = response.json()print(f"Analysis ID: {result['analysis_id']}")- URL must be publicly accessible or include authentication in the URL
- Must return
Content-Type: audio/*header - File size limits still apply
- HTTPS URLs recommended for security
Checking Analysis Statusβ
After submission, poll the status endpoint to check progress:
import requestsimport time
def wait_for_analysis(analysis_id, api_key, max_wait=300): """Poll until analysis completes or timeout""" api_url = "https://api.callcov.com/api/v1" headers = {"X-API-Key": api_key}
start_time = time.time() while time.time() - start_time < max_wait: response = requests.get( f"{api_url}/calls/analyze/{analysis_id}", headers=headers )
result = response.json() status = result['status']
if status == 'completed': print("Analysis completed!") return result elif status == 'failed': print(f"Analysis failed: {result.get('error')}") return None
print(f"Status: {status} - waiting...") time.sleep(5) # Poll every 5 seconds
print("Timeout waiting for analysis") return None
# Usageanalysis_id = "anl_1a2b3c4d5e"result = wait_for_analysis(analysis_id, "your_api_key_here")if result: print(f"Sentiment: {result['analysis']['sentiment']}") print(f"Summary: {result['analysis']['summary']}")Instead of polling, configure a webhook to receive notifications when analysis completes. See the Webhooks Guide for details.
Batch Submissionsβ
Submit multiple calls efficiently:
import requestsimport osfrom concurrent.futures import ThreadPoolExecutor, as_completed
API_KEY = "your_api_key_here"API_URL = "https://api.callcov.com/api/v1"
def submit_call(file_path, agent_id, contact_id): """Submit a single call for analysis""" files = {"audio_file": open(file_path, "rb")} data = { "agent_id": agent_id, "contact_id": contact_id } headers = {"X-API-Key": API_KEY}
response = requests.post( f"{API_URL}/calls/analyze", headers=headers, files=files, data=data )
return response.json()
# Batch submit with threadingcalls_to_submit = [ ("recording1.wav", "AGENT_001", "CONTACT_001"), ("recording2.wav", "AGENT_001", "CONTACT_002"), ("recording3.wav", "AGENT_002", "CONTACT_003"),]
results = []with ThreadPoolExecutor(max_workers=5) as executor: futures = [ executor.submit(submit_call, file_path, agent_id, contact_id) for file_path, agent_id, contact_id in calls_to_submit ]
for future in as_completed(futures): try: result = future.result() results.append(result) print(f"Submitted: {result['analysis_id']}") except Exception as e: print(f"Error: {e}")
print(f"\nSubmitted {len(results)} calls for analysis")Best Practicesβ
Audio Qualityβ
- Sample rate: 16 kHz minimum, 44.1 kHz recommended
- Codec: Uncompressed (WAV, FLAC) for best results
- Channels: Separate channels for agent and customer when possible
- Background noise: Minimize for better transcription accuracy
Performance Optimizationβ
- Use webhooks instead of polling for results
- Compress large files before upload (but not too much - quality matters)
- Batch submit during off-peak hours for large volumes
- Cache results to avoid reprocessing the same calls
Error Handlingβ
Always implement retry logic with exponential backoff:
import timeimport requestsfrom requests.adapters import HTTPAdapterfrom requests.packages.urllib3.util.retry import Retry
def create_retry_session(retries=3, backoff_factor=0.3): """Create session with automatic retry""" session = requests.Session() retry = Retry( total=retries, read=retries, connect=retries, backoff_factor=backoff_factor, status_forcelist=(500, 502, 503, 504), ) adapter = HTTPAdapter(max_retries=retry) session.mount('http://', adapter) session.mount('https://', adapter) return session
# Usagesession = create_retry_session()response = session.post( f"{API_URL}/calls/analyze", headers=headers, files=files, data=data)Rate Limitsβ
Submission rate limits vary by plan:
| Plan | Submissions/Minute | Concurrent Processing |
|---|---|---|
| Free | 5 | 1 |
| Starter | 30 | 5 |
| Business | 150 | 25 |
| Enterprise | Custom | Custom |
Common Errorsβ
400 Bad Requestβ
{
"error": {
"code": "invalid_file_format",
"message": "Audio file must be in WAV, MP3, M4A, FLAC, or OGG format"
}
}
Solution: Check file format and ensure it's supported.
413 Payload Too Largeβ
{
"error": {
"code": "file_too_large",
"message": "Audio file exceeds maximum size of 100 MB"
}
}
Solution: Compress the audio or split into smaller segments.
429 Too Many Requestsβ
{
"error": {
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded. Please try again in 32 seconds."
}
}
Solution: Implement rate limiting and exponential backoff in your code.
Next Stepsβ
Need Help?β
- Email: support@callcov.com
- Documentation: docs.callcov.com
- Dashboard: app.callcov.com