VOICE

Automated voice calls, triggered by your application

Deliver OTPs, alerts, appointment confirmations, and other transactional notifications as automated phone calls. Zoho CPaaS (formerly ZeptoMail) gives you programmable voice API, visual call flow builder, dedicated numbers, and in-depth call analytics.*

*Available in US, IN, EU and AU DCs


const url = "https://cpaas.zoho.com/v1.1/voice";

const requestBody = {
    "to": "<to>",
    "from": "<from>",
    "agent_key": "<agent_key>",
    "template_key": "<template_key>",
    "merge_info": {
        "<merge_key>": "<merge_value>"
    }
};

fetch(url, {
    method: "POST",
    headers: {
        "Accept": "application/json",
        "Content-Type": "application/json",
        "Authorization": "Zoho-oauthtoken <token>"
    },
    body: JSON.stringify(requestBody)
})
.then(response => response.json())
.then(resp => console.log(resp))
.catch(error => console.log(error, "error"));
                                            

curl "https://cpaas.zoho.com/v1.1/voice" \
    -X POST \
    -H "Accept: application/json" \
    -H "Content-Type: application/json" \
    -H "Authorization: Zoho-oauthtoken <token>" \
    -d '{
    "to": "<to>",
    "from": "<from>",
    "agent_key": "<agent_key>",
    "template_key": "<template_key>",
    "merge_info": {"<merge_key>": "<merge_value>"}}'
                                            

using System;
using System.Net;
using System.Text;
using System.IO;
using Newtonsoft.Json.Linq;

namespace Rextester
{
    public class Program
    {
        public static void Main(string[] args)
        {
            System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;
            var baseAddress = "https://cpaas.zoho.com/v1.1/voice";

            var http = (HttpWebRequest)WebRequest.Create(new Uri(baseAddress));
            http.Accept = "application/json";
            http.ContentType = "application/json";
            http.Method = "POST";
            http.PreAuthenticate = true;
            http.Headers.Add("Authorization", "Zoho-oauthtoken <token>");
            JObject parsedContent = JObject.Parse("{'to': '<to>','from': '<from>','agent_key': '<agent_key>','template_key': '<template_key>','merge_info': {'<merge_key>': '<merge_value>'}}");
            Console.WriteLine(parsedContent.ToString());
            UTF8Encoding encoding = new UTF8Encoding();
            Byte[] bytes = encoding.GetBytes(parsedContent.ToString());

            Stream newStream = http.GetRequestStream();
            newStream.Write(bytes, 0, bytes.Length);
            newStream.Close();

            var response = http.GetResponse();

            var stream = response.GetResponseStream();
            var sr = new StreamReader(stream);
            var content = sr.ReadToEnd();
            Console.WriteLine(content);
        }
    }
}
                                            

import requests

url = "https://cpaas.zoho.com/v1.1/voice"

payload = {
    "to": "<to>",
    "from": "<from>",
    "agent_key": "<agent_key>",
    "template_key": "<template_key>",
    "merge_info": {
        "<merge_key>": "<merge_value>"
    }
}
headers = {
    "accept": "application/json",
    "content-type": "application/json",
    "authorization": "Zoho-oauthtoken <token>",
}

response = requests.request("POST", url, json=payload, headers=headers)

print(response.text)
                                            

<?php

$curl = curl_init();

$payload = array(
    "to" => "<to>",
    "from" => "<from>",
    "agent_key" => "<agent_key>",
    "template_key" => "<template_key>",
    "merge_info" => array(
        "<merge_key>" => "<merge_value>"
    )
);

curl_setopt_array($curl, array(
    CURLOPT_URL => "https://cpaas.zoho.com/v1.1/voice",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "POST",
    CURLOPT_POSTFIELDS => json_encode($payload),
    CURLOPT_HTTPHEADER => array(
        "accept: application/json",
        "authorization: Zoho-oauthtoken <token>",
        "cache-control: no-cache",
        "content-type: application/json",
    ),
));

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
    echo "cURL Error #:" . $err;
} else {
    echo $response;
}
?>
                                            

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;

import org.json.JSONObject;

public class VoiceSendApi {
    public static void main(String[] args) throws Exception {
        String postUrl = "https://cpaas.zoho.com/v1.1/voice";
        BufferedReader br = null;
        HttpURLConnection conn = null;
        String output = null;
        StringBuffer sb = new StringBuffer();
        try {
            URL url = new URL(postUrl);
            conn = (HttpURLConnection) url.openConnection();
            conn.setDoOutput(true);
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Content-Type", "application/json");
            conn.setRequestProperty("Accept", "application/json");
            conn.setRequestProperty("Authorization", "Zoho-oauthtoken <token>");
            JSONObject mergeInfo = new JSONObject();
            mergeInfo.put("<merge_key>", "<merge_value>");
            JSONObject object = new JSONObject();
            object.put("to", "<to>");
            object.put("from", "<from>");
            object.put("agent_key", "<agent_key>");
            object.put("template_key", "<template_key>");
            object.put("merge_info", mergeInfo);
            OutputStream os = conn.getOutputStream();
            os.write(object.toString().getBytes(StandardCharsets.UTF_8));
            os.flush();
            br = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
            while ((output = br.readLine()) != null) {
                sb.append(output);
            }
            System.out.println(sb.toString());
        } catch (Exception e) {
            br = new BufferedReader(new InputStreamReader(conn.getErrorStream(), StandardCharsets.UTF_8));
            while ((output = br.readLine()) != null) {
                sb.append(output);
            }
            System.out.println(sb.toString());
        } finally {
            try {
                if (br != null) {
                    br.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                if (conn != null) {
                    conn.disconnect();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}           
                                            

HOW IT WORKS

One API call to trigger a voice call

Trigger a voice call with a single API request without the need for your own telephony infrastructure or call center setup. Build a voice call flow once and reuse it across every call type like OTPs, alerts, reminders.

templatevariablesroutedelivered

PRICING

Credit-based. No monthly minimums.

Credit-based model
Pay per call, per number
No monthly lock-ins

Voice channel also runs on a flexible credit system. Purchase credits and use them to pay for calls and numbers based on destination and duration. No monthly lock-ins.

View Pricing

When a call delivers better than a message

A voice call notification reaches users who may miss texts. They’re an important tool during time-sensitive transactions because they carry more urgency.

OTP and verification calls

Read one-time passwords digit by digit. It’s a reliable fallback when SMS doesn’t reach.

Appointment reminders

Spoken confirmation with a key press to confirm or cancel. No special app is required on the recipient’s end.

Critical system alerts

Escalate infrastructure failures, fraud triggers, and threshold breaches as calls when a notification won’t cut it.

Payment alerts

Read out a recent transaction details and collect a key press from the user to approve or flag the transaction. This is useful for high-value or unusual activity that may be time-sensitive.

Delivery updates

Notify recipients of a delivery attempt or missed pickup, with an IVR option to reschedule.

Feedback collection

Trigger a post-interaction call, read a question, and collect a numeric response. Easy and simple collection of structured feedback without a form.

Numbers and call flows, managed in one place

Zoho CPaaS comes with everything you need to set up and run transactional voice calls— from buying a number to defining what the call says.

Sender management

NUMBERS

Phone number management

Search and purchase numbers directly from Zoho CPaaS’s voice channel, filtered by country and type. Upload address proof documents required by telecom regulations right in the same interface. Each number is linked to an Agent for routing and tracking.

FLOWS

Visual voice flow builder

Zoho CPaaS has a user-friendly voice flow builder. Design call logic as a simple and visual node graph. Save each flow with an alias that the API references at runtime. You can export the flows built here or import your previous ones with ease. Flows are reusable across call types, only the runtime variables change per request.

Template control

ANALYTICS

Know exactly how every call performed

Call analytics in Zoho CPaaS are available at the Agent, flow template, and phone number level so you can track overall performance, isolate failures to a specific flow, or trace issues back to a particular number.

 

Delivery status

Every call is tracked across four outcomes: Answered, Unanswered, Failed, and Rejected, updated in real time as calls are dispatched and resolved.

 

Delivery overview graph

A time-series chart of call volume and outcomes across a configurable date range gives you a clear picture of how voice performance trends over time.

 

Delivery failure count and categories

Failed calls are broken down by category, like unanswered, unreachable, rejected, and others so you can spot systemic issues rather than chasing individual errors.

 

Delivery failure by phone number and Agent

Filter failure data by Agent and phone number to pinpoint exactly where failures are coming from, without sifting through aggregate reports.

 

Call logs

Every call dispatched through an Agent is captured in its Logs tab. It's a time-stamped record with status, destination, duration, and the flow used, with recording playback available where applicable.

Frequently asked questions

An automated outbound call triggered by a system event—an OTP request, delivery update, or fraud alert. The call follows a pre-built flow and is initiated via API, with no live agent involved.

Four types of numbers are available: Toll-free, Local, Personal, and Personal Unlimited. Search and purchase directly from the voice channel in Zoho CPaaS. Address proof documents are required before a number can be activated, in line with telecom regulations.

The template flow builder is a visual node editor where you can connect Speak, Collect digits, Transfer and End call nodes to define call flow logic. Each flow is saved with an alias that the API references at call time.

Yes. Create a separate Agent per application, link a dedicated number to each, and use each Agent’s API key in the respective codebase. Logs and analytics stay isolated per Agent while sharing one credit balance.

Start triggering voice calls in minutes.