Skip to main content
Manage Session Initiation Protocol (SIP) trunks, which carry calls between Plivo and your phone system or voice-agent platform, and the calls that went over them. plivo sip-trunking is the same command as plivo sip. After logging in, list your trunks:
A working setup has four parts. To connect LiveKit, ElevenLabs, Retell or Vapi step by step, see Connect a SIP voice-agent platform.
SIP endpoints (registered devices and usernames) are a different product, under plivo voice endpoints on the Voice page.
Command syntax: replace <values> and omit [flags] unless adding options. Repeat a flag marked repeatable for each value. Global flags, and the paging flags --all, --limit and --offset on every list: see Configuration.

Safety rules

  • --dry-run previews changes. Dependency checks can still read account resources; no change is applied.
  • Passwords are read from stdin only (--password-stdin); there is no --password flag, and the CLI never prints the password back. Supply stdin from a secret manager or a variable populated without shell history, and avoid shell tracing.
  • Values are checked before any request. A --uri with a space, a bad port, an unknown transport, a malformed host or a password in it (user:password@host) is refused, and so is an --ip that is not one address or CIDR range. Repeat --ip for more than one; a comma-separated list is refused.
  • Plivo accepts IPv4 only, so an IPv6 address in a URI or an IP access control list is refused.
  • Plivo can never reach a private, loopback, link-local, carrier-grade NAT, benchmarking, multicast or reserved address. Such an address is refused as a URI host and in sip ip-acl create and update. A range that allows the whole internet is only warned about.
  • A trunk ID must be digits. A SIP call ID, and a URI, credential or IP access control list ID, must be a UUID. Any other value is refused before any request.
  • create needs --name on URIs, trunks and IP access control lists.
  • A delete needs --yes, and first reads everything that depends on the object: every number routed to a trunk, every trunk using a URI, credential or IP list. If something depends on it, the delete is refused with exit code 5 unless you add --force to --yes. If the check can’t read every page, the delete is refused.
  • --dry-run alone previews a delete. For an object something depends on, --dry-run lists the dependents and exits 5; --dry-run --force previews the delete.
Every delete below takes --force: delete even though something depends on it (with --yes).
Deleting a URI that is a trunk’s primary URI also deletes that trunk. Deleting a URI that is a trunk’s fallback URI only clears the fallback; the trunk stays. Deleting a trunk detaches every number routed to it, so inbound calls to those numbers stop.

Trunks

An inbound trunk needs a primary URI. An outbound trunk needs a credential or an IP access control list. After create, the CLI reads the trunk back and prints its trunk_domain: paste that into your platform for outbound calls. --secure turns on Transport Layer Security (TLS) for signaling and Secure Real-time Transport Protocol (SRTP) for audio. Secure trunking is billed per minute. sip trunks update flags take an explicit value so they can be reversed, for example --secure=false or --status disabled. It keeps an inbound trunk’s fallback URI when you change something else; pass --fallback-uri "" to remove it. Flags that don’t fit the trunk’s direction, such as --fallback-uri on an outbound trunk, and a --status other than enabled or disabled, are refused before any request.

Origination URIs

Give --uri as host[:port][;transport=tcp|tls], for example sip.example.com:5060;transport=tcp. With no transport, the URI uses UDP. Quote a URI that contains ;, or the shell cuts the command there. --transport adds ;transport= for you. A sip: or sips: prefix is rewritten to the host form, because the API refuses both schemes. sip: is dropped. sips: becomes ;transport=tls, on port 5061 when you give no port; sips: with another transport is refused. The CLI prints the URI it sent on stderr:
A URI with a user part, such as sip:user@host, is refused; give the host alone. A URI never holds a password: when the platform needs authentication, pass --authentication-needed, --username and the password on stdin with --password-stdin. After a URI delete, each trunk that used the URI is read back. The result says which trunks were deleted with it and which are still there. With -o json they are in trunks_deleted and trunks_kept, and any that could not be read are in trunks_unchecked.

Credentials

Pass the password on stdin; the CLI does not generate one. Plivo’s rules are checked before any request: the username is 5 to 20 letters and digits, and the password is 5 to 20 characters with at least one of ~!@#$%^&*()_+.
Flags on create and update: --name <value> (credential name), --username <value> (SIP username, required on create) and --password-stdin (required on both: every update rewrites the password).

IP access control lists

An IP access control list (ACL) allows calls from specified addresses. --ip takes IPv4 addresses or Classless Inter-Domain Routing (CIDR) ranges (repeatable). On update it replaces the whole list, so pass every address you want to keep.

Route a number to a trunk

plivo numbers update --trunk-id routes a number to an inbound trunk, taking it off the application it was attached to. It warns when the trunk is disabled, and refuses an outbound trunk. For an India (+91) number the CLI checks its compliance application first, and refuses a number without accepted know your customer (KYC) compliance; see Numbers.

Trunk calls

  • get and insights end with which side hung up: Plivo’s hangup cause, code and source. The platform’s final SIP response shows as “not available”, because no API returns it; the console’s SIP logs have it.
  • insights shows round-trip time, jitter, packet loss, post-dial delay and the Plivo quality score, with the carrier and region of each leg, as the API returns them.
  • diagnose asks Plivo’s AI assistant to explain the call. It reads trunk calls only; for a Voice API call use plivo voice calls diagnose. See Diagnose a call for the JSON result and exit codes.
Without --until, the search runs to now. --until needs --since and must come after it. A malformed --from-number or --to-number is refused before any request.

Test a SIP URI

plivo sip test --uri <value> checks from your machine that a SIP host answers, before you send calls to it. It needs no login and never sends an INVITE, so no call is placed. --uri (required) is the SIP URI to test, e.g. “sip.example.com;transport=tcp”. When you give a host without a port and it publishes a SIP SRV record, the test warns and names the record’s target, with the --uri to test it. It still tests the host you gave. See Check that the platform answers.