How to Send a Voice Message
Sending a Voice Message via API
Upload an audio file and queue a voice campaign with the LigueLead API.
🤖 Looking for AI-driven calls? This guide covers pre-recorded audio only —
POST /v1/voicerequires avoice_upload_idand does not accept voice agents. To place AI-driven calls (an AI agent that holds a live conversation), use the dedicated endpointPOST /v1/voice-agent/call. See How to Send Voice Calls with AI.
Prerequisites
- Get your
api-tokenandapp-idin your LigueLead account, or anapp-idcreated through the API. - Prepare an audio file in WAV (recommended) or MP3 format. WAV is preferred because MP3's lossy compression can reduce audio quality — see Supported Audio Formats.
- Collect the recipient phone numbers in Brazilian format (for example,
11999999999). Other formats are also accepted — see Phone number format.
Step 1: Upload the audio file
Endpoint: POST /v1/voice/uploads
Run the request to upload the audio file you want to send.
curl -X POST "https://api.liguelead.com.br/v1/voice/uploads" \
-H "api-token: YOUR_API_TOKEN" \
-H "app-id: YOUR_APP_ID" \
-F "title=Welcome Message" \
-F "file=@/path/to/your/audio.mp3"💡 Tip: Upload WAV whenever possible. MP3 is accepted, but its lossy compression may degrade audio quality. The uploaded file's contents are checked against its extension: a file whose bytes clearly belong to the other format (for example, a WAV renamed to.mp3) is rejected with415.
Expected response
{
"message": "Voice upload successful.",
"data": {
"id": 123456,
"title": "Welcome Message",
"url": "https://ll-api-files.s3.amazonaws.com/1234/YOUR_APP_ID/audios/9f2c4e1a7b3d5f60.wav"
}
}Save the returned id. You will use it as voice_upload_id in the next request. The id belongs to the app that uploaded it: only requests with the same app-id can send it, list it or fetch it.
The url points to the stored file, so you can listen to what will be played. Anyone with the link can download the file, so do not publish it.
Step 2: Send the voice message
Endpoint: POST /v1/voice
Run the request to queue the voice message for delivery.
curl -X POST "https://api.liguelead.com.br/v1/voice" \
-H "api-token: YOUR_API_TOKEN" \
-H "app-id: YOUR_APP_ID" \
-H "Content-Type: application/json" \
-d '{
"title": "Welcome Campaign",
"voice_upload_id": 123456,
"phones": ["11999999999", "11888888888"]
}'Expected response
{
"message": "Voice accepted successfully",
"data": {
"campaign_id": "3b4f7c5e-7e2d-4157-b542-5eb2155455c5",
"accepted_at": "2025-12-29T18:34:38.961Z"
}
}A 200 OK response means the request was received and queued for processing.
Request parameters
Upload audio (POST /v1/voice/uploads)
POST /v1/voice/uploads)| Parameter | Type | Required | Description |
|---|---|---|---|
title | string | ✅ | Descriptive name for your audio file. |
file | binary | ✅ | Audio file, sent as multipart/form-data. WAV or MP3, up to 5 MB. |
Send voice message (POST /v1/voice)
POST /v1/voice)| Parameter | Type | Required | Description |
|---|---|---|---|
title | string | ✅ | Campaign identifier. |
voice_upload_id | integer | ✅ | The id returned by an upload made with the same app-id. An audio uploaded by another app, or an id that does not exist, is rejected with 422. |
phones | array | ✅ | Phone numbers to call. See Phone number format. |
is_international | boolean | ❌ | Set to true when the numbers are outside Brazil. The Brazilian format checks are skipped and each number is dialed as sent, without the +, so include the country code. |
retry_attempts | integer | ❌ | See Configuring retries. |
retry_interval_min | integer | ❌ | See Configuring retries. |
retry_end_time | string | ❌ | See Configuring retries. |
webhook_url | string | ❌ | URL that receives the status of this send instead of the app's webhook URL, called exactly as written (query string included). Up to 512 characters; see How to Receive Webhooks. |
Optional: Configuring retries
Use the retry fields to control how the voice service redials a number after a failed call. All three fields are optional.
| Field | Type | Default | Constraints | Description |
|---|---|---|---|---|
retry_attempts | integer | 3 | Minimum 1, maximum 3 | Number of retry attempts after a failed call. |
retry_interval_min | integer | 15 | Minimum 5, maximum 180 | Interval, in minutes, between retry attempts. |
retry_end_time | string | None | HH:MM, between 08:00 and 21:45, and at least 10 minutes in the future in America/Sao_Paulo | Cutoff time for new retry attempts. The system does not redial after this time. |
When you omit retry_attempts and retry_interval_min, the voice service automatically applies the default values of 3 attempts with a 15-minute interval between them. These defaults are managed by the voice service and may vary by account.
When you omit retry_end_time, no custom cutoff time is applied.
Voice sending and retries stop automatically at 21:45 (Brasília time). Set
retry_end_timeearly enough for all attempts to finish before that cutoff.
Example payload with retries
curl -X POST "https://api.liguelead.com.br/v1/voice" \
-H "api-token: YOUR_API_TOKEN" \
-H "app-id: YOUR_APP_ID" \
-H "Content-Type: application/json" \
-d '{
"title": "Payment Reminder",
"voice_upload_id": 123456,
"phones": ["11999999999", "11888888888"],
"retry_attempts": 3,
"retry_interval_min": 15,
"retry_end_time": "21:00"
}'Retry validation errors
The API returns 422 Unprocessable Entity when retry_end_time:
- does not match the
HH:MMformat - is outside the allowed range of
08:00to21:45 - is less than 10 minutes in the future in the
America/Sao_Paulotimezone
Optional: Managing uploaded audio files
Use these endpoints to review the audio files uploaded by this app. Audio files of other apps of the same account are not shown.
List uploaded audio files
Lists the audio files uploaded by this app, newest first.
curl -X GET "https://api.liguelead.com.br/v1/voice/uploads" \
-H "api-token: YOUR_API_TOKEN" \
-H "app-id: YOUR_APP_ID"{
"message": "Voice list.",
"data": [
{
"id": 123456,
"title": "Welcome Message",
"url": "https://ll-api-files.s3.amazonaws.com/1234/YOUR_APP_ID/audios/9f2c4e1a7b3d5f60.wav"
}
]
}When the app has no audio files, data is an empty array and the message is No voice found..
Get one uploaded audio file by ID
curl -X GET "https://api.liguelead.com.br/v1/voice/uploads/123456" \
-H "api-token: YOUR_API_TOKEN" \
-H "app-id: YOUR_APP_ID"{
"message": "Voice found successfully.",
"data": {
"id": 123456,
"title": "Welcome Message",
"url": "https://ll-api-files.s3.amazonaws.com/1234/YOUR_APP_ID/audios/9f2c4e1a7b3d5f60.wav"
}
}An id uploaded by another app answers 404 with { "error": "Audio not found" }, exactly like an id that does not exist.
Phone number format
The API accepts Brazilian phone numbers in any of these formats:
- National:
"11999999999" - International:
"+5511999999999" - With country code, no
+:"5511999999999"
For numbers outside Brazil, send is_international: true and write each number with its country code.
Dialing window (21:45 – 08:00 | America/Sao_Paulo)
To comply with calling time policies, no calls are placed between 21:45 and 08:00 (America/Sao_Paulo).
Requests received during this window are still accepted by the API, but they are not dialed immediately. They remain pending and are processed automatically when dialing resumes at 08:00.
Processing and delivery
- Asynchronous processing: voice messages are queued for delivery.
- Response code:
200 OKindicates successful queuing. - Delivery time: varies based on the carrier and the number of recipients.
- Status tracking: the status of each call arrives as a
campaign.statuswebhook, sent to the app's webhook URL or to thewebhook_urlof the send — see How to Receive Webhooks.
Best practices
- Reuse audio files: upload once and send to multiple campaigns.
- Monitor delivery: track the
campaign.statuswebhooks to confirm each call. - Test first: start with small batches before scaling up.
- Clear titles: use descriptive names for easy identification.
Troubleshooting
| Issue | What to check |
|---|---|
| File upload fails | Confirm the file is a valid WAV or MP3 up to 5 MB and the request uses multipart/form-data. |
| Invalid phone format | Use a Brazilian number in one of the accepted formats, or send is_international: true for numbers outside Brazil. |
| Authentication error | Verify the api-token and app-id headers. |
voice_upload_id is rejected with 422 | The audio must have been uploaded with the same app-id as the send. The error is Voice upload <id> is not an upload of this app, both for an audio of another app and for an id that does not exist. List the app's audio files with GET /v1/voice/uploads, or upload the audio again with this app. |
retry_end_time is rejected | Check the HH:MM format, the 08:00 to 21:45 range, and whether the time is at least 10 minutes in the future in America/Sao_Paulo. |
| Calls are not retried as expected | Confirm the retry settings leave enough time before the 21:45 cutoff. |
webhook_url is rejected with 422 | Use http or https, a public hostname without underscores and at most 512 characters. Private and reserved addresses are refused. |
Updated 1 day ago
