Skip to main content
This page covers the essential APIs for building AI voice agents: initiating calls, handling incoming calls, and streaming audio.

Calls API Essentials

Audio streaming requires an active call. Use the Calls API to initiate outbound calls or configure incoming call handling.

Make an Outbound Call

POST https://api.plivo.com/v1/Account/{auth_id}/Call/
ParameterRequiredDescription
fromYesCaller ID (your Plivo number) in E.164 format
toYesDestination number in E.164 format
answer_urlYesURL returning XML when call is answered
answer_methodNoGET or POST (default: POST)
import plivo

client = plivo.RestClient('<auth_id>', '<auth_token>')
response = client.calls.create(
    from_='+14151234567',
    to_='+14157654321',
    answer_url='https://yourserver.com/answer',
    answer_method='POST'
)
print(response)
Your answer_url should return XML with the <Stream> element to start audio streaming:
<?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Stream bidirectional="true" keepCallAlive="true">
        wss://yourserver.com/websocket
    </Stream>
</Response>

Handle Incoming Calls

Configure your Plivo phone number’s Answer URL in the console to point to your server. When a call arrives, Plivo sends a POST request with:
ParameterDescription
CallUUIDUnique call identifier
FromCaller’s phone number
ToYour Plivo number
Directioninbound
Your server returns XML to start the audio stream.

Hang Up a Call

DELETE https://api.plivo.com/v1/Account/{auth_id}/Call/{call_uuid}/
client.calls.delete(call_uuid='call-uuid-here')

Transfer a Call

Redirect an active call to fetch new XML (e.g., to change behavior mid-call):
POST https://api.plivo.com/v1/Account/{auth_id}/Call/{call_uuid}/
ParameterDescription
legsWhich leg to transfer: aleg, bleg, both
aleg_urlURL to fetch new XML for A leg
client.calls.transfer(
    call_uuid='call-uuid-here',
    legs='aleg',
    aleg_url='https://yourserver.com/new-flow'
)
For the complete Calls API reference, see Voice API - Calls.

Audio Streams API

The Audio Streams API lets you receive raw audio from active calls over a WebSocket connection in near real-time. Use it for real-time transcription, voice AI, call analytics, or custom audio processing.

API Endpoint

https://api.plivo.com/v1/Account/{auth_id}/Call/{call_uuid}/Stream/

The Audio Stream Object

AttributeTypeDescription
stream_idstringUnique identifier for the audio stream
call_uuidstringUUID of the call being streamed
service_urlstringWebSocket URL receiving the stream
bidirectionalbooleanWhether stream supports two-way audio
audio_trackstringAudio direction: inbound, outbound, both
content_typestringAudio codec and sample rate
start_timestringWhen streaming started
end_timestringWhen streaming ended
bill_durationintegerStreaming duration in seconds
billed_amountstringCost in USD

Example Response

{
    "api_id": "f7615566-13c5-11ee-b552-0242ac110005",
    "stream_id": "20170ada-f610-433b-8758-c02a2aab3662",
    "call_uuid": "78737f83-4660-490d-98e1-025dfe4b5c8f",
    "service_url": "wss://mysocket.com/wss/v2/1/demo/",
    "audio_track": "both",
    "bidirectional": false,
    "content_type": "audio/x-l16;rate=8000",
    "start_time": "2023-06-21 18:53:16+05:30",
    "end_time": "2023-06-21 18:53:43+05:30",
    "bill_duration": 27,
    "billed_amount": "0.00300",
    "rounded_bill_duration": 60
}

Start an Audio Stream

Initiate streaming for an active call.
POST https://api.plivo.com/v1/Account/{auth_id}/Call/{call_uuid}/Stream/

Parameters

ParameterTypeRequiredDescription
service_urlstringYesWebSocket URL (wss://) to receive audio
bidirectionalbooleanNoEnable two-way audio. Default: false
audio_trackstringNoTrack to stream: inbound, outbound, both. Default: inbound
stream_timeoutintegerNoMax duration in seconds. Default: 86400 (24 hours)
content_typestringNoAudio format. Default: audio/x-l16;rate=8000
status_callback_urlstringNoURL for stream status events
status_callback_methodstringNoGET or POST. Default: POST
extra_headersstringNoCustom headers: key1=val1,key2=val2

Audio Formats

Content TypeDescription
audio/x-l16;rate=8000Linear PCM, 8kHz (default)
audio/x-l16;rate=16000Linear PCM, 16kHz
audio/x-mulaw;rate=8000G.711 mu-law, 8kHz
When bidirectional is true, audio_track cannot be outbound or both.
import plivo

client = plivo.RestClient('<auth_id>', '<auth_token>')

response = client.calls.create_stream(
    'call_uuid_here',
    service_url='wss://yourserver.example.com/audiostream',
    bidirectional=False,
    audio_track='both',
    stream_timeout=3600,
    content_type='audio/x-l16;rate=16000'
)
print(response)

Retrieve an Audio Stream

Get details of a specific audio stream.
GET https://api.plivo.com/v1/Account/{auth_id}/Call/{call_uuid}/Stream/{stream_id}/
response = client.calls.get_stream('call_uuid', 'stream_id')

List All Audio Streams

Get all audio streams for a call.
GET https://api.plivo.com/v1/Account/{auth_id}/Call/{call_uuid}/Stream/
response = client.calls.get_all_streams('call_uuid')

Response

{
    "api_id": "87399872-13cb-11ee-9da1-0242ac110003",
    "meta": {
        "limit": 20,
        "offset": 0,
        "total_count": 1
    },
    "objects": [
        {
            "stream_id": "4543157e-60d3-4c3a-b9d8-189c47686bf0",
            "call_uuid": "816e0b22-6913-4b43-88a9-6d3054b77df9",
            "service_url": "wss://example.com/stream",
            "audio_track": "both",
            "bidirectional": false,
            "start_time": "2023-06-26 08:14:29+05:30",
            "end_time": "2023-06-26 08:14:50+05:30"
        }
    ]
}

Stop a Specific Audio Stream

Stop streaming for a specific stream.
DELETE https://api.plivo.com/v1/Account/{auth_id}/Call/{call_uuid}/Stream/{stream_id}/
client.calls.delete_specific_stream('call_uuid', 'stream_id')
Response: HTTP 204 No Content

Stop All Audio Streams

Stop all active streams on a call.
DELETE https://api.plivo.com/v1/Account/{auth_id}/Call/{call_uuid}/Stream/
client.calls.delete_all_streams('call_uuid')

Bidirectional Streaming

When bidirectional=true, your WebSocket server can send audio back to the call.

Sending Audio to Call

Send a JSON message to the WebSocket:
{
    "event": "playAudio",
    "media": {
        "contentType": "audio/x-l16",
        "sampleRate": "8000",
        "payload": "<base64-encoded-audio>"
    }
}
FieldValues
contentTypeaudio/x-l16, audio/x-mulaw
sampleRate8000, 16000
payloadBase64-encoded raw audio

Status Callback Events

Notifications sent to status_callback_url:
EventDescription
Stream connectedAudio streaming has started
Stream stoppedStreaming stopped intentionally
Stream timeoutstream_timeout duration reached
Stream failedConnection failed or dropped