Sends an automated voice call (IVR) to a list of phone numbers, using a text message converted to speech (TTS).
Endpoint
POST https://wa20.nuke.co.in/v6/api/v1/voice/send
Authentication
Required. Send a JWT in the header:
Authorization: Bearer <jwt_token>
Headers
| Header | Value |
|---|---|
Content-Type | application/json |
Authorization | Bearer <jwt_token> |
Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
broadcast_name | string | Yes | Any label for this campaign. |
caller_id | string | No | The number the call appears to come from. If omitted, a fixed default number is used. |
message | string | Conditional | The text to be converted to speech and played on the call. Max 5000 characters. Provide either message or audio_url — not required if audio_url is sent. |
audio_url | string (URL) | Conditional | A direct link to a pre-recorded audio file to play on the call instead of generating speech. Provide either message or audio_url. |
language | string | No | Language for TTS — only used when message is sent. Accepts "hindi", "hi", "english", "en", or any 2-letter language code. Defaults to English if not recognized. |
contacts | array of strings | Yes | Phone numbers to call, 10–16 digits each (no country-code symbols like +). Duplicates are removed automatically; invalid numbers are silently dropped. |
voiceplan | string | No | "15" or "30" — sets the billing block size (in seconds) used to calculate credits for this campaign. See How Credits Are Calculated. |
dtmf_flow | object | No | IVR configuration for call transfers, submenus, audio playback, and recording caller responses. See DTMF Menus & Call Forwarding below. |
callback_audio | array | No | Simple call-forwarding shortcut — maps a keypad digit directly to a forwarding number, without the full menu features of dtmf_flow. See Call Forwarding (callback_audio) below. |
retries | number | No | Number of retry attempts if a call isn't answered. |
retry_interval | number | No | Seconds to wait between retries. Must be one of: 5, 10, 30, 60, 180, 300. |
You must send exactly one of
messageoraudio_url— whichever is provided determines what the recipient hears when the call connects.
Payload Examples
1. Simple Call — Text-to-Speech
A normal voice blast where the recipient hears your message, converted to speech.
{
"broadcast_name": "test",
"message": "नमस्कार! यह आपके लिए एक महत्वपूर्ण सूचना है। कृपया इस संदेश को अंत तक ध्यानपूर्वक सुनें।",
"language": "hindi",
"contacts": ["9193xxxxxxxx"],
"voiceplan": "15",
"retries": 1,
"retry_interval": 10
}
cURL Example
curl --location 'https://wa20.nuke.co.in/v6/api/v1/voice/send' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...' \
--data '{
"broadcast_name": "test",
"message": "नमस्कार! यह आपके लिए एक महत्वपूर्ण सूचना है।",
"language": "hindi",
"contacts": ["9193xxxxxxxx"],
"voiceplan": "15",
"retries": 1,
"retry_interval": 10
}'
2. Simple Call — Pre-recorded Audio File
Same as above, but instead of converting text to speech, a ready-made audio file is played. Send audio_url and leave out message/language.
{
"broadcast_name": "Voice Campaign",
"caller_id": "9999999999",
"audio_url": "https://example.com/audio/sample_voice.mp3",
"contacts": [
"9193xxxxxxxx",
"9194xxxxxxxx"
],
"retries": 1,
"retry_interval": 10,
"voiceplan": "15"
}
messageandlanguageare omitted here sinceaudio_urlis provided instead.
DTMF Menus & Call Forwarding
Two ways to build an interactive call are supported: the simple callback_audio shortcut for a flat digit → forwarding-number mapping, and the fuller dtmf_flow object for menus, submenus, audio playback, and recording caller responses.
Call Forwarding (callback_audio)
callback_audio)The simplest way to forward a call based on a keypad digit — no menu, no submenu, just digit → number.
{
"broadcast_name": "test",
"message": "नमस्कार! यह आपके लिए एक महत्वपूर्ण सूचना है। कृपया इस संदेश को अंत तक ध्यानपूर्वक सुनें।",
"language": "hindi",
"contacts": ["919340886343"],
"voiceplan": "15",
"retries": 1,
"retry_interval": 10,
"callback_audio": [
{
"dtmf": "1",
"selected_number": "9893075453"
}
]
}
| Field | Type | Required | Description |
|---|---|---|---|
callback_audio | array | No | List of digit → forwarding-number mappings. |
callback_audio[].dtmf | string | Yes | The keypad digit the recipient must press. |
callback_audio[].selected_number | string | Yes | The number the call is forwarded to when this digit is pressed. |
audio_urlcan be used here in place ofmessage/languagethe same way as in a simple call — the recipient hears whichever one you send, then presses a digit to be forwarded.
DTMF Menu / Submenu (dtmf_flow)
dtmf_flow)For richer flows — nested submenus, playing additional audio on a digit press, or recording the caller's response — use dtmf_flow instead. Each entry in rows can specify an action:
action | What it does |
|---|---|
transfer | Forwards the call to number, trying fallback_numbers (up to 3 max) in order if the primary doesn't connect. |
submenu | Plays prompt_audio, then waits for another digit press evaluated against its own nested rows array. |
audio | Plays the given audio file, then does whatever after specifies (e.g. "hangup" to end the call). |
record | Starts recording the caller's spoken response after this digit is pressed (e.g. for a satisfaction survey). |
back | Used inside a submenu's rows to return to the parent menu. |
Example — Submenu
{
"broadcast_name": "test_submenu_back",
"message": "मुख्य मेनू में आपका स्वागत है। अधिक जानकारी के लिए 1 दबाएं, या ऑफर सुनने के लिए 2 दबाएं।",
"language": "hindi",
"contacts": ["919340886343"],
"voiceplan": "15",
"retries": 1,
"retry_interval": 10,
"dtmf_flow": {
"rows": [
{
"digit": "1",
"action": "submenu",
"prompt_audio": "https://wa1.goshort.in/uploads/2026/08/12/audio/e975181b-f406-4d51-ba12-ba5fc6845fcc.mp3",
"rows": [
{
"digit": "1",
"action": "back"
}
]
},
{
"digit": "2",
"action": "audio",
"audio": "https://wa1.goshort.in/uploads/2026/08/12/audio/ff374203-56e2-42e0-b219-d9ace6267055.mp3",
"after": "hangup"
}
]
}
}
In this example: pressing 1 plays prompt_audio as a submenu, where pressing 1 again goes back to the main menu. Pressing 2 on the main menu plays an audio clip and then hangs up.
Example — Record Key
Use action: "record" to capture the caller's spoken answer after they press a digit (e.g. a quick voice survey):
{
"broadcast_name": "test_record_key",
"message": "हमारी सेवाओं से आप कितने संतुष्ट हैं? संतुष्ट होने पर 1 दबाएं, असंतुष्ट होने पर 2 दबाएं।",
"language": "hindi",
"contacts": ["919340886343"],
"voiceplan": "15",
"retries": 1,
"retry_interval": 10,
"dtmf_flow": {
"rows": [
{ "digit": "1", "action": "record" },
{ "digit": "2", "action": "record" }
]
}
}
As with the other examples,
audio_urlcan be sent instead ofmessage/languagein anydtmf_flowpayload — the prompt heard before the menu can be either TTS or a pre-recorded file.
Example Response — 200 OK
{
"request_id": "VCAMP_20260728_9F3A21B0",
"campaign_name": "test",
"contacts": 1,
"counts_per_contact": 3,
"credits_deducted": 3,
"ivr_enabled": true,
"status": "Pending for Verification",
"audio_url": "https://wa20.nuke.co.in/v6/api/uploads/2026/07/28/audio/9f3a21b0....mp3"
}
Response Fields
| Field | Description |
|---|---|
request_id | Unique campaign ID, in the format VCAMP_YYYYMMDD_XXXXXXXX. Use this to track the campaign. |
campaign_name | Same as the broadcast_name you sent. |
contacts | Number of valid, deduplicated phone numbers the call was queued for. |
counts_per_contact | Credits charged per contact — calculated from audio duration and your voiceplan block size. |
credits_deducted | Total voice_credits deducted (counts_per_contact × contacts). |
ivr_enabled | true if a dtmf_flow/callback_audio flow was attached to this campaign. |
status | Initial campaign status — always "Pending for Verification" right after submission. |
audio_url | The audio that will be played on the call — either your generated TTS file, or the audio_url you provided. |
How Credits Are Calculated
Credits are charged in blocks per contact — any part of a block counts as a full block (rounded up). The block size is controlled by voiceplan: "15" uses 15-second blocks, "30" uses 30-second blocks.
| Audio Duration | Credits per contact (15s plan) |
|---|---|
| Up to 0:15 | 1 |
| 0:16 – 0:30 | 2 |
| 0:31 – 0:45 | 3 |
| 0:46 – 1:00 | 4 |
| 1:01 – 1:15 | 5 |
| 1:16 – 1:30 | 6 |
| 1:31 – 1:45 | 7 |
| Up to 2:00 (max) | 8 |
Confirm the equivalent table for the
"30"(30-second block) plan before publishing — likely half the blocks of the 15s plan for the same duration, but get the exact numbers from your team.
- Maximum audio duration is 120 seconds (2:00) — longer messages/audio files are rejected.
credits_deducted = counts_per_contact × number of valid contacts, taken from yourvoice_creditsbalance.- If your balance is insufficient, the request fails before any calls are queued.
Validation Rules
broadcast_nameis required.- Exactly one of
messageoraudio_urlmust be provided. message, if sent, cannot exceed 5000 characters.contactsmust be a non-empty array; each number must be 10–16 digits (after removing symbols), duplicates are removed automatically.voiceplan, if given, must be"15"or"30".retry_interval, if given, must be one of5, 10, 30, 60, 180, 300seconds.dtmf_flow(if provided) must be a valid object containing arowsarray; each row's required fields depend on itsaction(numberfortransfer,prompt_audio+ nestedrowsforsubmenu,audioforaudio).callback_audio(if provided) must be an array of objects, each withdtmfandselected_number.
Error Responses
These are returned as validation/processing errors before a call is queued:
| Message | Reason |
|---|---|
broadcast_name is required | Missing broadcast name. |
Either audio_file_id or message is required | Neither message nor audio_url was provided. |
Text for voice message cannot exceed 5000 characters. | message too long. |
Provide an array of phone numbers in 'contacts' | contacts missing or empty. |
retry_interval must be one of: 5, 10, 30, 60, 180, 300 | Invalid retry_interval value. |
No valid numbers were found in contacts. | None of the given numbers passed the 10–16 digit format check. |
Audio duration cannot exceed 120 seconds | The generated speech or provided audio file is longer than the 120-second limit. |
Insufficient credits. Required: X, Available: Y | Not enough voice_credits balance. |
dtmf_flow is not valid JSON | The provided dtmf_flow data was structured incorrectly. |
Confirm whether a dedicated error message exists for an invalid
voiceplanvalue or a malformedcallback_audioarray — add it here once confirmed.
Notes
- Send either
message(converted to speech automatically) oraudio_url(played as-is) — not both. - For Hindi/English
messagetext, long text is automatically split at sentence boundaries and reassembled to keep the audio natural — no action needed on your end besides sending the full message. callback_audiois the simplest way to do basic call forwarding; usedtmf_flowwhen you need submenus, audio playback on a digit press, or to record the caller's response.- Inside a
dtmf_flowsubmenu, useaction: "back"to let the caller return to the parent menu. - Campaign status starts as
"Pending for Verification"— check back or use your delivery report for the final per-contact call outcome.
