Skip to main content

SIP BYOC (Bring Your Own Carrier)

Overview

Bring Your Own Carrier (BYOC) allows SignalWire users to retain their own carriers for connectivity instead of the vendors that we partner with. This allows you to use any carrier you want while still utilizing the powerful programmatic control for SIP from SignalWire!

This might be a good fit for you if:

  • You like your current carrier but want to use our APIs to enhance your call flow
  • You want international origination from a country we don't yet support
  • The number cannot be ported into SignalWire
  • You want to keep control of the number rather than port it to SignalWire
  • You want to SIP trunk to/from a SIP Server (such as Kamailio)

Inbound BYOC

If you would like to do inbound BYOC (i.e. send your carrier traffic to SignalWire), you will need to create a domain application. Domain Apps allow you to send SIP traffic to a custom domain and use SignalWire APIs to manage the incoming request. You can do this under SIP -> Domain Apps -> Create a Domain App, or via the Domain Apps API.

A screenshot of the New Domain App page, showing fields in which the user can set the app name, app URL, and toggle an IP whitelist. The Settings section in this example is configured to handle using a Relay Application, with optional encryption and a selection of supported codecs and ciphers.
Whitelisting IPs

It's VERY important to whitelist the IPs that you want to allow through - if you do not select this option, anyone who has the URL could send traffic to your custom domain app.

Handling Inbound Calls

Using Compatibility API/XML

If you try directing traffic to your domain app without configuring it, SignalWire will not pick up the call. To have SignalWire pick up the call, so you can do something with it you will need to:

  1. Tell the Domain App where to go when a call comes in (by setting the "WHEN A CALL COMES IN" field);
  2. Give instructions to SignalWire of what to do with that call.

To address both of the steps above, we will need to create an XML Bin. The bare minimum of instructions you must provide for SignalWire to pick up the call is an empty response:

<?xml version="1.0" encoding="UTF-8"?>
<Response>
</Response>

This XML Bin example, with just an empty response, will "respond" to the call by picking it up. You'll probably want to do much more than this, such as dialing to another SIP endpoint, so we recommend learning more about the Verbs you can use.

Once you have the XML Bin the way you want it, you will need to get its URL and paste it in our Domain App's "WHEN A CALL COMES IN" field:

A screenshot of the Edit Domain App page within the SIP tab in a SignalWire Space. The field titled 'When a Call Comes in' under Settings has been circled in red.

Using Relay

To handle incoming calls using a Relay Application, you will need to:

  1. Give it a context (think of it as a traffic label) to send calls to. Let's use an office context as an example;
  2. Run code listening for calls on that office context and then do something with them.
import { Voice } from "@signalwire/realtime-api";

const client = new Voice.Client({
project: "<project-id>",
token: "<api-token>",
contexts: ["office"],
});

client.on("call.received", async (call) => {
console.log("Got call", call.from, call.to);

try {
await call.answer();
console.log("Inbound call answered");

await call.playTTS({ text: "Hello! This is a test call." });
} catch (error) {
console.error("Error answering inbound call", error);
}
});

In this example we're creating a Client and tying it to the office context. Then, we tell it to listen for call.received events, and when a new call comes in we answer it and say "Hello! This is a test call." to the caller.

To learn more about what you can do with Relay, have a look at our Relay Realtime SDK documentation.

Outbound BYOC

If you are using BYOC to do outbound calls from SignalWire, you will need a SIP URL from your carrier that we can use to route calls to the right SIP trunk. Once you have that, you can create a call using the Compatibility API or Relay using the SIP URL, SIP username, and SIP password. Let's look at some examples so you can see what we're talking about!

Outbound Call Examples

Using Compatibility API/XML

XML Bins

To start an outbound call using XML Bins you can use the Dial verb along with the SIP noun:

<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial
callerId="+11111111111">
<Sip
username="YourUsername"
password="YourPassword">
sip:user@domain.com;transport=udp?header1=foo&header2=bar
</Sip>
</Dial>
</Response>
cURL

To create an outbound call that executes the instructions from a XML Bin we can use the following format for a cURL command:

curl https://<YOURSPACENAME>.signalwire.com/api/laml/2010-04-01/Accounts/<YOURPROJECTID>/Calls.json \
-X POST \
--data-urlencode "Url=YourXMLBinURL" \
--data-urlencode "sip:YOUR SIP URL" \
--data-urlencode "From=+15550011222" \
--data-urlencode "SipAuthUsername=user" \
--data-urlencode "SipAuthPassword=pass" \
-u "YourProjectID:YourAuthToken"

Using Relay

RELAY Realtime SDK

RELAY Realtime SDK is our must recent version of RELAY, and dialing out to a SIP endpoint is simpler than ever:

import { Voice } from "@signalwire/realtime-api";

const client = new Voice.Client({
project: "<project-id>",
token: "<api-token>",
contexts: ["office"],
});

try {
const call = await client.dialSip({
from: "sip:xxx@yyy.zz",
to: "sip:ppp@qqq.rr",
timeout: 30,
});

// TODO: Add code to do something with the call object here
} catch (e) {
console.log("Call not answered.");
}
RELAY SDK (previous version)

RELAY SDK is our previous version of RELAY, and is now deprecated, but still supported. Calling out to a SIP endpoint is very similar to the implementation using the latest version:

const { RelayClient } = require("@signalwire/node");

const client = new RelayClient({
project: "<project-id>",
token: "<api-token>",
});

client.on("signalwire.ready", async (client) => {
const dialResult = await client.calling.dial({
type: "sip",
from: "sip:xxx@yyy.zz",
to: "sip:ppp@qqq.rr",
timeout: 30,
});

if (dialResult.successful) {
const { call } = dialResult;

// TODO: Add code to do something with the call object
}
});

client.connect();
Don't feel like using JavaScript?

Have a look at our SDKs Technical Reference portal to find .NET, GO, PHP, Ruby, and Python versions of Relay SDK (previous version).

How to Get Started

If you are interested in BYOC and need additional assistance getting started, reach out to support@signalwire.com! One of our support technicians can make sure everything gets squared away so you can get up and running in no time.

Check out our guide on how to integrate with Thinq as your carrier!

Sign Up Here

If you would like to test this example out, you can create a SignalWire account and space here.

Please feel free to reach out to us on our Community Slack or create a Support ticket if you need guidance!