This README documents sipgate.io, a real-time telephony API by sipgate. There's a demo page, code examples, and a newsletter.
- sipgate.io
- Requirements
- The POST request
- New call
- Answer
- Call hangup * Hangup causes
- DTMF
- The XML response
- Dial
- Play
- Gather
- Reject
- Hangup
- onAnswer
- onHangup
- More to come
- Code Examples
- FAQ
- Troubleshooting
- sipgate.io Log
- How do I inspect network traffic?
- A word about security
- HTTP vs. HTTPS
- Authentication
- Emergency calls
- Help us make it better
- Book sipgate.io in your team account (incurs monthly cost) or request access to our developer program (free!)
- After receiving the confirmation mail enter an URL for incoming/outgoing calls in sipgate team settings
- Create a free sipgate basic account
- Book the sipgate.io feature
- Enter an URL for incoming/outgoing calls in the dashboard
- Order a simquadrat SIM
- Book the sipgate.io feature
- Enter an URL for incoming/outgoing calls in the dashboard
When enabled, sipgate.io sends POST requests with an application/x-www-form-urlencoded
payload for each of call involving your sipgate account. Depending on the type of request it contains the following parameters:
Parameter | Description |
---|---|
event | "newCall" |
from | The calling number (e.g. "492111234567" or "anonymous" ) |
to | The called number (e.g. "4915791234567" ) |
direction | The direction of the call (either "in" or "out" ) |
callId | A unique alphanumeric identifier to match events to specific calls (This callId is the same as the session_id , should you initiate the call via the sipgate XML-RPC API) |
user[] | The sipgate user(s) involved. It is the name of the calling user when direction is "out" , or of the users receiving the call when direction is "in" . Group calls may be received by multiple users. In that case a "user[]" parameter is set for each of these users. It is always "user[]" (not "user" ), even if only one user is involved. |
You can simulate this POST request and test your server with a cURL command:
curl -X POST --data "event=newCall&from=492111234567&to=4915791234567&direction=in&callId=123456&user[]=Alice&user[]=Bob" http://localhost:3000
Optional Parameter | Description |
---|---|
diversion | If a call was diverted before it reached sipgate.io this contains the originally dialed number. |
If you set the "onAnswer" attribute sipgate.io will push an answer-event, when a call is answered by the other party.
Parameter | Description |
---|---|
event | "answer" |
callId | Same as in newCall-event for a specific call |
user | Name of the user who answered this call. Only incoming calls can have this parameter |
from | The calling number (e.g. "492111234567" or "anonymous" ) |
to | The called number (e.g. "4915791234567" ) |
direction | The direction of the call (either "in" or "out" ) |
answeringNumber | The number of the answering destination. Useful when redirecting to multiple destinations |
You can simulate this POST request and test your server with a cURL command:
curl -X POST --data "event=answer&callId=123456&user=John+Doe&from=492111234567&to=4915791234567&direction=in&answeringNumber=21199999999" http://localhost:3000
Optional Parameter | Description |
---|---|
diversion | If a call was diverted before it reached sipgate.io this contains the originally dialed number. |
If you set the "onHangup" attribute sipgate.io will push a hangup-event when the call ends.
Parameter | Description |
---|---|
event | "hangup" |
cause | The cause for the hangup event (see table below) |
callId | Same as in newCall-event for a specific call |
from | The calling number (e.g. "492111234567" or "anonymous" ) |
to | The called number (e.g. "4915791234567" ) |
direction | The direction of the call (either "in" or "out" ) |
answeringNumber | The number of the answering destination. Useful when redirecting to multiple destinations |
You can simulate this POST request and test your server with a cURL command:
curl -X POST --data "event=hangup&cause=normalClearing&callId=123456&from=492111234567&to=4915791234567&direction=in&answeringNumber=4921199999999" http://localhost:3000
Optional Parameter | Description |
---|---|
diversion | If a call was diverted before it reached sipgate.io this contains the originally dialed number. |
Hangups can occur due to these causes:
Cause | Description |
---|---|
normalClearing | One of the participants hung up after the call was established |
busy | The called party was busy |
cancel | The caller hung up before the called party picked up |
noAnswer | The called party rejected the call (e.g. through a DND setting) |
congestion | The called party could not be reached |
notFound | The called number does not exist or called party is offline |
forwarded | The call was forwarded to a different party |
If you "gather" users' dtmf reactions, this result is pushed as an event to the url specified in the "onData" attribute with the following parameters:
Parameter | Description |
---|---|
event | "dtmf" |
dtmf | Digit(s) the user has entered. If no input is received, the value of dtmf will be empty. |
callId | Same as in newCall-event for a specific call |
You can simulate this POST request and test your server with a cURL command:
curl -X POST --data "event=dtmf&dtmf=1&callId=123456" http://localhost:3000
After sending the POST request sipgate.io will accept an XML response to determine what to do. Make sure to set application/xml
in the Content-Type
header of your response.
sipgate.io currently supports the following responses for incoming and outgoing calls:
Action | Description |
---|---|
Dial | Send call to voicemail or external number |
Play | Play a sound file |
Gather | Collects digits that a caller enters with the telephone keypad. |
Reject | Reject call or pretend to be busy |
Hangup | Hang up the call |
Additional to actions, the response can specify urls which shall be called by sipgate.io on certain call-events. Specify these urls via xml-attributes in the response-tag.
Url | Description |
---|---|
onAnswer | Receives a POST-request as soon as someone answers the call. The response to that request is discarded. |
onHangup | Receives a POST-request as soon as the call ends for whatever reason. The response to that request is discarded. |
Redirect the call and alter your caller id (call charges apply). Calls with direction=in
can be redirected to up to 5 targets.
Attribute | Possible values | Default value |
---|---|---|
callerId | Number in E.164 format | Account settings |
anonymous | true, false | Account / phone settings |
Possible targets for the dial command:
Target | Description |
---|---|
Number | Send call to an external number (has to be in E.164 format) |
Voicemail | Send call to voicemail (feature has to be booked) |
Example 1: Redirect call
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial>
<Number>4915799912345</Number>
</Dial>
</Response>
Example 2: Send call to voicemail
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial>
<Voicemail />
</Dial>
</Response>
Example 3: Suppress phone number
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial anonymous="true">
<Number>4915799912345</Number>
</Dial>
</Response>
Example 4: Set custom caller id for outgoing call
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial callerId="492111234567">
<!-- Originally dialed number, extracted from POST request -->
<Number>4915799912345</Number>
</Dial>
</Response>
Example 5: Redirect incoming call to multiple destinations
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial>
<Number>4915799912345</Number>
<Number>492111234567</Number>
</Dial>
</Response>
When the call is answered, the resulting answer-event reports the answering destination in a field called answeringNumber
.
Play a given sound file.
Target | Description |
---|---|
Url | Play a sound file from a given URL |
Example 1: Play a sound file
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Play>
<Url>http://example.com/example.wav</Url>
</Play>
</Response>
Please note: Currently the sound file needs to be a mono 16bit PCM WAV file with a sampling rate of 8kHz. You can use conversion tools like the open source audio editor Audacity to convert any sound file to the correct format.
Linux users might want to use mpg123
to convert the file:
mpg123 --rate 8000 --mono -w output.wav input.mp3
Gather collects digits that a caller enters with the telephone keypad. The onData attribute is mandatory and takes an absolute URL as a value.
Attribute | Possible values | Default value |
---|---|---|
type | dtmf | dtmf |
onData | absolute URL | - |
maxDigits | integer >= 1 | 1 |
timeout (ms) | integer >= 1 | 2000 |
Nesting Rules
The following verbs can be nested within <Gather>
:
- Play The timeout starts after the sound file has finished playing. After the first digit is received the audio will stop playing.
Example 1: DTMF with sound file and additional parameters
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Gather onData="http://localhost:3000/dtmf" maxDigits="3" timeout="10000">
<Play>
<Url>https://example.com/example.wav</Url>
</Play>
</Gather>
</Response>
Pretend to be busy or block unwanted calls.
Attribute | Possible values | Default value |
---|---|---|
reason | rejected, busy | rejected |
Example 1: Reject call
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Reject />
</Response>
Example 2: Reject call signaling busy
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Reject reason="busy" />
</Response>
Hang up calls
Example: Hang up call
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Hangup />
</Response>
Example: Request notification for call being answered
<?xml version="1.0" encoding="UTF-8"?>
<Response onAnswer="http://localhost:3000/answer" />
Example: Request notification for call hangup
<?xml version="1.0" encoding="UTF-8"?>
<Response onHangup="http://localhost:3000/hangup" />
Stay tuned...
To get you started we maintain server examples for:
There are also examples in:
The transferred call is a new call. Scenario: Jennifer calls Doc Brown and Doc Brown transfers the call to Marty and Marty picks up. Here's what sipgate.io sends to your server:
- newCall (user: Doc, callId: 12111955)
- answer (user: Doc, callId: 12111955)
- [Doc dials *3 <Marty's extension>]
- newCall (user: Marty, callId: 21102015, diversion: <Doc's number> from: <Jennifer's number>)
- answer (user: Marty, callId: 21102015, diversion: <Doc's number> from: <Jennifer's number>)
- hangup (user: Doc, callId: 12111955)
As you can see, the callId
changes with the transfer.
This is what sipgate.io sends, in case Marty does not pick up:
- newCall (user: Doc, callId: 12111955)
- answer (user: Doc, callId: 12111955)
- [Doc dials *3 <Marty's extension>]
- newCall (user: Marty, callId: 21102015, diversion: <Doc's number> from: <Jennifer's number>)
- hangup (user: Marty, callId: 21102015)
The forwarded call is handled as a new call. Let's assume the previous scenario: Jennifer calls Doc Brown but his line is busy so the call is forwarded to Marty who in turn picks up the call.
Here are the pushes sipgate.io will send to your server:
- newCall (user: Doc, callId: 12111955)
- hangup (cause: forwarded, callId: 12111955)
- newCall (user: Marty, callId: 21102015, diversion: <Doc's number> from: <Jennifer's number>)
- answer (user: Marty, callId: 21102015, diversion: <Doc's number> from: <Jennifer's number>)
- hangup (user: Marty, callId: 21102015)
The answer is: It depends.
If you transfer or forward a call within the same sipgate account then the answer is no. But if you forward or transfer a call to a different sipgate account or an external number then those pushes are being billed to your account.
You can enable logging for debugging purposes from your dashboard. You will find each request and the corresponding response in the logging table.
You can use ngrep
to inspect the incoming requests on your side:
sudo ngrep -dany -Wbyline port 3000
We strongly encourage you to use a HTTPS server. Although we support plain HTTP connections we do not recommend pushing sensitive call details over unencrypted connections. By default sipgate.io does not accept self-signed certificates. If you use simquadrat or sipgate basic, you can allow self-signed certs in your dashboard. In sipgate team you cannot make an exception.
Furthermore, you can add your public certificate to protect the connection against man-in-the-middle attacks. Your certificate is validated by our server.
In order to work your certificate has to be in the following format
-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAJC1HiIAZAiIMA0GCSqGSIb3Df
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVx
aWRnaXRzIFB0eSBMdGQwHhcNMTExMjMxMDg1OTQ0WhcNMT
A .... MANY LINES LIKE THAT ....
JjyzfN746vaInA1KxYEeI1Rx5KXY8zIdj6a7hhphpj2E04
C3Fayua4DRHyZOLmlvQ6tIChY0ClXXuefbmVSDeUHwc8Yu
B7xxt8BVc69rLeHV15A0qyx77CLSj3tCx2IUXVqRs5mlSb
vA==
-----END CERTIFICATE-----
sipgate.io supports HTTP Basic Authentication. You can include your username and password within the URL (e.g. https://username:password@example.com:8080
).
sipgate.io does not process emergency calls. Emergency calls are immediately put through to emergency services.
Please tell us how we can improve sipgate.io. If you have a specific feature request, found a bug or would like to add an example, please use GitHub Issues or fork these docs and send a pull request with your improvements.