Documentation
SIP integration
Point an IP-authenticated SIP trunk at the ingress host shown on your account, port 5060 over UDP or TCP, with no registration and no credentials, offering G.711 in the initial INVITE. Open Voice Shield authorizes the call by source IP, anchors the media so the audio can be recorded, and relays the INVITE on to a destination you configure — your own SBC, PBX or carrier.
The shape of the connection#
Open Voice Shield is a SIP proxy in the path of calls you choose to send through it. Your switch sends an INVITE to our ingress; we check the source address, anchor the media, and forward the same call to a destination you have configured. There is no B2BUA, no media injection and no re-origination — the far end sees your call, not ours.
- Signalling is a normal SIP hop. Your dialed number, your caller ID, your headers.
- Media is relayed through us in both directions, which is what makes the recording possible.
- The final response your switch sees is the far end's own response, unless we refused the call ourselves — see what your switch gets back.
One trunk, or one dial pattern
You do not have to move all your traffic. Most operators start with a single route — one campaign, one queue, one dial pattern — and keep the existing direct route as a fallback.
Where to send the INVITE#
The ingress address is per account. Read it from the Network page in the portal, or from the API:
GET /customer/network-info
API=https://your-ovs-host.example
curl -s $API/api/customer/network-info -H "Authorization: Bearer $TOKEN"
# {"ingress_host":"192.0.2.10","ingress_port":5060,"transports":["udp","tcp"]}
| Parameter | Value |
|---|---|
| Host | your ingress_host |
| Port | 5060 |
| Transports | udp, tcp |
| TLS towards us | not offered on the ingress. TLS outward, from us to your destination, is supported. |
| Request-URI user | the dialed number |
| From user | the caller ID (ANI). Automation rules act on this value. |
| Registration | none — see below |
The same host is the source address of everything we send onward, so your destination has to trust it. TCP is the safer choice when your INVITEs carry large SDP.
Authentication is by source IP#
There is no SIP account, no password and no registrar. A REGISTER is answered 403 Registration Not Supported. An INVITE is accepted only when its source address falls inside a CIDR entry on your whitelist, so add the public address your switch sends from — the address after NAT, not the private one on its interface.
| Rule | Detail |
|---|---|
| Format | CIDR. A single host is /32 (IPv4) or /128 (IPv6). |
| Widest accepted | /16 for IPv4, /48 for IPv6. Anything broader is refused 422 CIDR too broad. |
| Exclusivity | A range belongs to one account platform-wide. Overlapping a range held by another account returns 409. |
| Several matches | The longest prefix wins; the oldest entry breaks a tie. |
| How many | Up to 50 entries per account. |
| Per-entry destination | An entry can name its own destination, so one site's traffic can leave to a different place. |
| Turning one off | enabled: false keeps the entry and stops accepting calls from it. |
Check the address you actually send from
A switch behind NAT, a multi-homed SBC or a cloud instance with a separate egress address will send from something other than the address written in its configuration. The source address we see is the only one that counts.
Trunk settings to enter on your switch#
Every switch calls these something different — peer, trunk, carrier, gateway, endpoint. The settings are the same. Create an IP-authenticated entry with no registration and route the traffic you want analyzed through it.
| Setting | Value | Why |
|---|---|---|
| Peer host / proxy / SIP server | your ingress_host | Where the INVITE goes. |
| Port | 5060 | The only SIP port on the ingress. |
| Transport | UDP or TCP | Pick one. Both are accepted on the same port. |
| Authentication / credentials | none | Authorization is by source IP. |
| Registration | off | A REGISTER is answered 403. |
| Codecs offered | PCMU, PCMA | Anything else cannot be transcribed. See codecs. |
| DTMF | telephone-event (RFC 2833) may be offered | It is relayed like any other payload type. |
| SDP | early offer, in the initial INVITE | An INVITE with no SDP is answered 488. |
| SRTP / media encryption | off | The ingress relays plain RTP. |
| ICE | off | ICE attributes are removed from the SDP. |
| Session timers | optional | Re-INVITEs and UPDATEs are relayed; they do not extend the call limit. |
| Keepalive | SIP OPTIONS | Answered 200 OK from any address. |
| Max-Forwards | leave at the default | A request that arrives with Max-Forwards already at zero is answered 483. |
| Fallback route | your existing direct route | So a 503 takes the old path instead of failing the call. |
Firewall, both directions#
Signalling and media use different ports and the media leg is the one people forget. Media is plain RTP on a UDP range at the ingress address — 30000–40000 unless your operator tells you otherwise.
| Direction | Protocol and ports | Carries |
|---|---|---|
| Out, to the ingress host | UDP or TCP 5060 | Your INVITEs and your OPTIONS keepalive. |
| Out, to the ingress host | UDP 30000–40000 | Your RTP towards us. |
| In, from the ingress host | UDP 30000–40000 | The far end's RTP, relayed back to you. |
| In, from the ingress host | the SIP port of your destination | The call, relayed onward from our address. |
| In, from the ingress host | your destination's RTP range | The media, relayed onward from our address. |
If the destination is your own SBC or PBX, add the ingress host to its trusted peers or ACL before the first test call. Being rejected by your own equipment is the single most common first-call failure.
Codecs and media#
The ingress does not transcode. Whatever your switch and the far end agree on is what gets relayed — and what gets recorded.
| Codec | Relayed | Analyzed |
|---|---|---|
| G.711 µ-law (PCMU, payload type 0) | yes | yes |
| G.711 A-law (PCMA, payload type 8) | yes | yes |
| telephone-event (RFC 2833) | yes | not speech — ignored by the transcript |
| Comfort noise (payload type 13) | yes | ignored inside a G.711 stream |
| Anything else | yes | no — the call is relayed and billed, but produces no transcript and no analysis |
Offer G.711 or you get no verdict
The recording is decoded from the relayed G.711 stream, at 8 kHz, one channel per direction. A call that negotiates a compressed codec still completes normally — it simply has nothing to transcribe. Put PCMA and PCMU at the top of the offer on this trunk.
The media is anchored: the SDP your switch receives points at the ingress media address, in both directions, for the whole call. ICE is stripped, the origin and connection lines are rewritten, and the audio is captured while it is relayed. Nothing is injected into the audio and neither party hears anything added.
Where the call goes next#
A destination is a host, port and transport we relay the accepted call to — your SBC, PBX or carrier. Up to 20 per account, with udp, tcp or tls outward, independent of the transport you use towards us.
The destination for a given call is chosen in this order, first match wins:
- an active divert control on the caller's ANI, placed by one of your automation rules;
- a routing rule whose prefix is the longest leading match of the dialed number;
- the destination attached to the whitelist entry that matched the source IP;
- your default destination;
- failing all of those, back to the source address on 5060/udp.
Prefix routing#
A routing rule maps a leading digit string on the dialed number to one of your destinations. Use it to send a test range, a country, or a voice-agent number somewhere other than the default while everything else follows the normal path.
POST /customer/routing-rules
curl -s -X POST $API/api/customer/routing-rules \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"prefix":"1800","destination_id":"<destination id>","priority":100,"label":"toll-free to SBC B"}'
| Field | Rule |
|---|---|
| prefix | 1 to 15 digits. Matched against the leading digits of the dialed number. |
| Which rule wins | The longest matching prefix. On equal length, the highest priority, then the most recently updated rule. |
| priority | 0 to 100000, default 100. It is a tie-breaker only — it never beats a longer prefix. |
| enabled | false takes the rule out of matching without deleting it. |
| Duplicates | A second rule for the same prefix returns 409. |
| No match | Selection falls through to the whitelist entry's destination, then the default. |
Tech prefix#
Carriers that identify a trunk by a leading digit string want that string on the number they receive, not on the number you dial. Set tech_prefix on the destination and we prepend it to the Request-URI user before relaying: dialling 15551234567 through a destination with tech prefix 009 leaves us as 00915551234567.
- Characters 0-9, * and # only, up to 32 of them.
- It is a property of the destination, so every call routed there gets it.
- The call record keeps both the dialed number and the prefix that was applied.
- Clear it by sending an empty value.
Carrying your own reference on the call#
Two SIP headers on the initial INVITE are captured and stored on the call record, so a verdict can be joined back to the campaign, agent or ticket that produced it: X-Customer-ID and X-Customer-Name. Values are trimmed to 256 characters and appear as external_id and external_name on the call. The captured set is a platform setting — ask your operator if you need different headers.
What your switch gets back#
If we refuse the call, the response comes from us and comes fast, before any INVITE is sent onward. If we accept it, everything your switch sees after that — 180, 183, 200, a busy, a rejection — is the far end's own response, relayed unchanged.
| Response | Reason phrase | Means |
|---|---|---|
| 200 | OK | Answer to an OPTIONS keepalive. Sent from any source address — it proves the path, not the whitelist. |
| 402 | Payment Required | Prepaid balance will not cover a minute at your rate. |
| 403 | IP not whitelisted | The source address is not in any enabled CIDR entry on your account. |
| 403 | Account suspended | The account is not active. |
| 403 | Blocked by rule | An automation rule of yours has this caller ID under an active block. The attempt is written to your call records. |
| 403 | Registration Not Supported | A REGISTER arrived. We are a proxy, not a registrar. |
| 403 | Destination Not Allowed | The resolved destination points at loopback, link-local or the ingress itself. |
| 405 | Method Not Allowed | An out-of-dialog method other than INVITE, ACK, CANCEL, OPTIONS or REGISTER. |
| 481 | Call/Transaction Does Not Exist | A CANCEL or in-dialog request that matches no live transaction or dialog. |
| 483 | Too Many Hops | Max-Forwards reached zero, or an in-dialog request would route back to the ingress itself. |
| 486 | Busy Here | You are already at your plan's concurrent call limit. |
| 487 | — | Your own CANCEL was honoured. |
| 488 | Not Acceptable Here | The INVITE carried no SDP. Send an early offer. |
| 503 | Service Unavailable | The call could not be authorized or relayed. Take your fallback route. |
| 503 | Media Relay Unavailable | The media relay could not take the call, so it was refused rather than carried without recording. |
| 500 | Server Internal Error | An admission check failed for an unclassified reason. |
A malformed request is dropped without a reply. A retransmitted INVITE — same Call-ID and same From-tag — gets the answer already given to the original and does not consume a second port or a second balance check.
How a call ends#
A BYE from either side ends the call normally and is relayed. Two limits can also end it from our side, and both send BYE to both parties:
| Limit | Value | Behaviour |
|---|---|---|
| Credit cut-off | what your remaining balance buys, never less than 60 s | Measured from answer. Re-INVITEs do not extend it. |
| Maximum call lifetime | 4 hours by default | An absolute upper bound on any dialog. |
Run a test call#
- OPTIONS. Send SIP OPTIONS from the switch to sip:ping@<ingress_host>:5060. A 200 OK proves the path and the port.
- Confirm the source address. Place one call and, if it is rejected 403, compare the address in your own SIP trace with the CIDR entries on the account.
- Place a real call over the new route with at least 30 seconds of two-way speech, and talk on both legs — a leg that never speaks produces a one-sided transcript.
- Check the media. Both parties should have audio in both directions. One-way audio is a firewall rule on the RTP range, not a signalling problem.
- Read the call record a minute after hang-up: the dialed number, the destination that was chosen, the route prefix and tech prefix applied, the SIP log and the verdict are all on it.
GET /calls — the routing decision that was actually applied
curl -s "$API/api/calls?limit=1" -H "Authorization: Bearer $TOKEN"
# {"total":1,"items":[{"id":"...","ani":"15550001111","dialed":"15551234567",
# "dest_host":"203.0.113.10","dest_port":5060,"dest_transport":"udp",
# "route_prefix":"1800","dest_tech_prefix":null,"status":"completed",
# "sip_code":200,"end_reason":"bye","billsec":42,"analysis_status":"done"}]}
Before you send production traffic#
- The public egress address of every switch that will send to us is whitelisted.
- The ingress host is a trusted peer on your destination, for SIP and for RTP.
- UDP 30000–40000 is open outbound and inbound between you and the ingress.
- The trunk offers PCMA and PCMU, sends SDP in the INVITE, and does not register.
- A default destination exists, and any prefix rule you added resolves to the right one.
- The account has credit, and the plan has enough ports for your busy hour.
- Your fallback route is still in place for 503.
Next: Concepts explains what happens to the call after the BYE and how to read the verdict. If something is being rejected, Troubleshooting lists each code and the check that clears it.