Skip to main content
Test your WebSocket connection without placing a phone call. For a voice agent listening locally on port 7860:
A WebSocket is a persistent connection that carries audio frames between Plivo and your voice agent. Three checks run from your machine, place no call and don’t change your Plivo account:
  • plivo voice streams test: your WebSocket endpoint, with Plivo-shaped audio frames.
  • plivo voice streams simulate: your answer URL and its XML, as Plivo requests them, then the WebSocket in its <Stream>. It still requests your own webhook, so your server runs its normal handler.
  • plivo voice streams readiness: a number, or a caller ID for an outbound call, is ready for a streamed call. Then it simulates the call.

Test a WebSocket endpoint

plivo voice streams test [flags] opens a WebSocket to your server and sends synthetic frames in Plivo’s format: one start frame, a media frame every 20 ms for --duration seconds, then one stop frame. It reports connection latency, frames sent and, with --bidirectional, whether your server sent audio back and how fast. Plivo’s backend is not involved, so you can run it in continuous integration (CI).
  • The input is a 1 kHz tone, not speech. If no playAudio returns, an agent that waits for speech may stay silent even when it works on real calls.
  • A wss:// URL that reaches a server without TLS fails with a hint to use ws:// for a local server.
  • On normal completion the test sends stop before closing. A failed write ends it with exit code 3, and so does an endpoint that closes the stream before stop; the error gives the frame it closed at and the close code and reason.

Signed like a real stream

When you are logged in, the test signs the WebSocket upgrade as Plivo signs a stream, with X-Plivo-Signature-V3 keyed with your profile’s auth token, so an endpoint that checks Plivo’s signature lets it in. --profile signs for another account; logged out, the upgrade is unsigned. An endpoint that refuses the upgrade with 401 or 403 fails the test with AUTH_FORBIDDEN and exit code 2.

Read the result in a script or CI

With -o json, the test prints one result on stdout and its progress on stderr. --expect-audio makes it exit 1 when no playAudio comes back, so it can gate a CI job.

Simulate a call to your answer URL

voice streams simulate does what Plivo does when a call reaches your answer URL, without placing a call. Requires Plivo CLI v1.3.2 or later.
  1. It requests --answer-url with the fields Plivo sends (CallUUID, From, To, Direction, CallStatus), signed with X-Plivo-Signature-V3 when you are logged in.
  2. It checks the reply: a 2xx within Plivo’s 15 seconds, its content type, and Plivo XML with a <Stream>.
  3. It opens the WebSocket in the <Stream> and streams a tone in its contentType, as voice streams test does.
  • Only the answer document is read: no <Redirect> or action URL is followed. A Plivo-hosted answer URL, such as a flow built in the console, is refused with nothing sent, because a request there would run it for real.
  • A pass means your server answers your machine as Plivo needs. It doesn’t prove that Plivo can reach your server, or that a caller hears the audio.
  • Exit codes: 0 on a pass, 1 when a check fails, 2 when the WebSocket refuses the upgrade, 3 when a host can’t be reached or the WebSocket closes before the stop frame.
  • With -o json it prints checks[] and the stream summary under stream, with the same fields as voice streams test. When a check fails it prints only the error, with checks[] in error.context.

Check a number is ready for a call

voice streams readiness checks what a streamed call needs on your account, then simulates the call as voice streams simulate does. It places no call and changes nothing. Requires Plivo CLI v1.3.2 or later. Inbound: give the number.
It checks that the number is on your account with voice enabled, that an Indian (+91) number has an accepted compliance application, and that the number is routed to an application with an answer URL, then simulates the call with the application’s method. A missing fallback answer URL or hangup URL, and a development tunnel, are warnings. A host Plivo can’t reach, such as your own machine or a private address, fails.
The simulated call’s checks and result: ready follow. Outbound: give the caller ID, the number to call and the answer URL.
The caller ID must be a number on your account with voice enabled, or a verified caller ID. An Indian caller ID needs an accepted compliance application and can call only Indian numbers. The account needs cash credits. Geo permissions and the concurrent call limit have no API, so info lines say where to check them in the console. The simulated call follows, as for inbound.
  • A Plivo-hosted answer URL, such as a flow built in the console, is not requested in either direction: the result is unknown. --dry-run makes the account reads but sends nothing to the answer URL.
  • With -o json it prints checks[] and the simulation. When a check fails it prints only the error, with both in error.context.

The audio contract

The XML attribute and the WebSocket frame spell the audio format differently, which is easy to get wrong. <Stream> has one combined contentType attribute holding the codec and sample rate. There is no sampleRate attribute on <Stream>.
The WebSocket start frame spells them out separately, under mediaFormat:
A codec defines how audio samples are encoded; the sample rate is samples per second, in hertz (Hz). The l16 media type is audio/x-l16, not audio/l16. Exactly three combinations are supported: There is no mu-law 16 kHz stream. Any other pair is rejected before the connection opens, with BAD_FLAG and exit code 1, so a bad combination fails on your laptop instead of as a dropped stream mid-call. --codec l16 sends real little-endian 16-bit pulse-code modulation (PCM) audio, so an agent that decodes the payload sees a genuine waveform.