English
English
Appearance
English
English
Appearance
Endpoints to play / download a single call recording, create bulk export jobs (ZIP), control jobs, and pause/resume recording in real time for PCI compliance.
POST /api/telesales/calls/{uuid}/recording/pause
POST /api/telesales/calls/{uuid}/recording/resume| Field | Type | Description |
|---|---|---|
uuid | string | UUID of the call in progress |
| Field | Type | Description | Valid values |
|---|---|---|---|
uuid | string | Call UUID | |
recording | string | Recording state after the call | paused / recording |
Response 200: { "data": { "uuid": "...", "recording": "paused" } }
Use case
The agent can pause recording while the customer reads out sensitive information (credit card number, CVV, ...) to remain PCI-DSS compliant, then resume recording once the sensitive segment is over.
| Endpoint | Purpose |
|---|---|
GET /api/telesales/recordings/{uuid} | Stream audio for playback (returns audio/wav, supports Range requests) |
GET /api/telesales/recordings/{uuid}/download | Download the .wav file with a filename header |
POST /api/telesales/recordings/export-bulk | Create an async ZIP export job |
GET /api/telesales/recordings/export-bulk/{jobId} | Check job status |
GET /api/telesales/recordings/export-bulk/{jobId}/download | Download the ZIP when the job is done |
DELETE /api/telesales/recordings/export-bulk/{jobId} | Cancel a job / clean up the ZIP early |
GET /api/telesales/recordings/{uuid} — stream | Field | Type | Description |
|---|---|---|
uuid | string | Call UUID |
| Header | Description | Value |
|---|---|---|
Content-Type | MIME type | audio/wav |
Accept-Ranges | Range requests supported | bytes |
Content-Length | File size (bytes) | |
Cache-Control | Cache policy | private, max-age=3600 |
Response 200:
Content-Type: audio/wavAccept-Ranges: bytes (for HTML5 audio scrubbing)Content-Length: <bytes>Cache-Control: private, max-age=3600Response 206 Partial Content (HTTP Range request) — used by the audio player for scrubbing.
Response 404 — no recording:
{ "message": "Recording not found.", "error_code": "RECORDING_NOT_FOUND" }Response 410 Gone — the recording exceeded the retention window configured by the admin:
{ "message": "Recording has exceeded the retention window.", "expired_at": "2026-03-01T00:00:00Z" }GET /api/telesales/recordings/{uuid}/download | Field | Type | Description |
|---|---|---|
uuid | string | Call UUID |
| Header | Description | Value |
|---|---|---|
Content-Type | MIME type | audio/wav |
Content-Disposition | Suggested filename for the browser | attachment; filename="call-{uuid}-{date}.wav" |
Response 200:
Content-Type: audio/wavContent-Disposition: attachment; filename="call-093e1024-2026-06-06.wav"Errors 404/410 are identical to the stream endpoint.
POST /api/telesales/recordings/export-bulk — create ZIP job | Field | Type | Required | Description | Valid values |
|---|---|---|---|---|
campaign_id | integer | optional | Filter by campaign | |
date_from | datetime | ✅ | Start timestamp (ISO 8601 UTC) | |
date_to | datetime | ✅ | End timestamp (ISO 8601 UTC) | date_from..date_to ≤ 31 days |
agent_ids[] | array<integer> | optional | Filter by agent | |
disposition_codes[] | array<string> | optional | Only export calls with these dispositions | disposition codes belonging to the account |
Body:
{
"campaign_id": 36,
"date_from": "2026-06-01T00:00:00Z",
"date_to": "2026-06-05T23:59:59Z",
"agent_ids": [25, 26],
"disposition_codes": ["SALE-OK", "CALLBACK_REQ"]
}| Field | Type | Description | Valid values |
|---|---|---|---|
job_id | string | Export job ID | exp_<hex> |
status | string | Initial state | queued |
estimated_files | integer | Estimated recordings to be packaged | ≥ 1 |
estimated_size_mb | integer | Estimated ZIP size (MB) | ≥ 0 |
created_at | datetime | Job creation (ISO 8601 UTC) | |
expires_at | datetime | When the ZIP is auto-deleted (default +30 days) | ISO 8601 UTC |
Response 201:
{
"data": {
"job_id": "exp_abc123",
"status": "queued",
"estimated_files": 215,
"estimated_size_mb": 480,
"created_at": "2026-06-06T07:00:00Z",
"expires_at": "2026-07-06T07:00:00Z"
}
}Response 422 — validation cases:
// Time range exceeds 31 days
{
"message": "The given data was invalid.",
"errors": { "date_to": ["The date_from..date_to range may not exceed 31 days."] }
}
// 0 files match the filter → no job is created
{
"message": "No recordings match the filter.",
"errors": { "filter": ["Estimated 0 files. Adjust date range or filters."] }
}Response 403 — caller lacks the supervisor / admin role:
{ "message": "You are not allowed to bulk-export recordings. Supervisor or admin role is required." }GET /api/telesales/recordings/export-bulk/{jobId} — check status | Field | Type | Description |
|---|---|---|
jobId | string | Job ID returned by the create endpoint |
| Field | Type | Description | Valid values |
|---|---|---|---|
job_id | string | Export job ID | |
status | string | Job state | queued / running / ready / failed / expired / cancelled |
progress_pct | integer | Percent complete | 0-100 |
files | integer | Files packaged (only when ready) | ≥ 0 |
files_processed | integer | Files processed so far (only when running) | ≥ 0 |
size_mb | integer | Actual ZIP size (MB) | |
download_url | string | URL to download the ZIP (when status=ready) | |
created_at | datetime | Job creation (ISO 8601 UTC) | |
completed_at | datetime|null | When packaging finished | |
expires_at | datetime | When the ZIP is auto-deleted | |
error_code | string | Error code when status=failed | e.g. STORAGE_ERROR |
error_message | string | Error description when status=failed | |
failed_at | datetime | When the job failed |
Response 200:
{
"data": {
"job_id": "exp_abc123",
"status": "ready",
"progress_pct": 100,
"files": 215,
"size_mb": 478,
"download_url": "/api/telesales/recordings/export-bulk/exp_abc123/download",
"created_at": "2026-06-06T07:00:00Z",
"completed_at": "2026-06-06T07:08:42Z",
"expires_at": "2026-07-06T07:00:00Z"
}
}Enum status: queued | running | ready | failed | expired | cancelled.
State running also returns progress_pct (0..99) + files_processed.
State failed also returns:
{
"data": {
"job_id": "exp_abc123",
"status": "failed",
"error_code": "STORAGE_ERROR",
"error_message": "Storage unavailable during ZIP packaging.",
"failed_at": "2026-06-06T07:05:00Z"
}
}Response 404 — job does not exist or does not belong to the account.
GET /api/telesales/recordings/export-bulk/{jobId}/download | Field | Type | Description |
|---|---|---|
jobId | string | Job ID (status must be ready) |
| Header | Description | Value |
|---|---|---|
Content-Type | MIME type | application/zip |
Content-Disposition | ZIP filename | attachment; filename="recordings-{jobId}.zip" |
Response 200:
Content-Type: application/zipContent-Disposition: attachment; filename="recordings-exp_abc123.zip"The ZIP contains the .wav files plus a manifest.csv (call UUID, agent extension, agent name, disposition code, start_time, duration, lead phone number).
Response 410 Gone — ZIP has expired (30 days):
{ "message": "Export ZIP has expired. Please create a new job." }Response 409 Conflict — job is not yet ready:
{ "message": "Job exp_abc123 is currently in state 'running' (38%). Wait until ready before downloading." }DELETE /api/telesales/recordings/export-bulk/{jobId} — cancel / clean up | Field | Type | Description |
|---|---|---|
jobId | string | Job ID to cancel or clean up |
Response 204 No Content — queued/running → cancelled; ready → ZIP is deleted early to free storage.