Make and Receive Calls using the Devices and Calls API
These APIs require the following authentication scope which you should specify while requesting an access token as listed in the prerequisites further down:
webrtc.v1.write
: to make calls
Prerequisites
This article assumes you can make API calls successfully which requires:
- A GoTo Developer account
- An OAuth client with the scopes listed further above
- An access token for a user on a GoToConnect account
Flow of the API calls
You will first create the notification channel using the Notification Channel API. Refer to Create a notification channel
You will then use the channel ID to create a device. Refer to Creating a Device
Once the device has been created, you will then need to create an extension with the device ID of that given device. Refer to Creating a Device Extension
You will then be able to call the /calls
API to make and receive calls. Refer
to Make a call
Request to create a webhook notification channel
curl --request POST \
--url https://api.goto.com/notification-channel/v1/channels/d1d3332b-f33b-4cc2-b754-72fb2d0863d0@email.webhook.site \
--header 'Authorization: Bearer {ACCESS_TOKEN}' \
--header 'content-type: application/json' \
--data '{
"channelType": "Webhook",
"webhookChannelData": {
"webhook": {
"url": "https://webhook.site/d1d3332b-f33b-4cc2-b754-72fb2d0863d0"
}
}
}'
Response
The response is an HTTP 201 CREATED response containing the data for the notification channel created:
{
"channelId": "Webhook.6050752e-78dd-47af-8e22-552d3d6e3326",
"channelNickname": "d1d3332b-f33b-4cc2-b754-72fb2d0863d0@email.webhook.site",
"webhookChannelData": {
"webhook": {
"url": "https://webhook.site/d1d3332b-f33b-4cc2-b754-72fb2d0863d0"
},
"channelType": "Webhook"
},
"channelLifetime": 2147483647,
"resourceURL": "https://webrtc.dev.jive.com/notification-channel/v1/channels/d1d3332b-f33b-4cc2-b754-72fb2d0863d0@email.webhook.site/Webhook.6050752e-78dd-47af-8e22-552d3d6e3326",
"doNotDisturbAware": false
}
Request to create a device
Use the channel ID from previous step as input to create a new device.
curl --request POST \
--url https://api.goto.com/web-calls/v1/devices \
--header 'Authorization: Bearer {ACCESS_TOKEN}' \
--header 'content-type: application/json' \
--data '{
"clientInformation": {
"deviceId": "1234567809012111116",
"appId": "INTEGRATOR_APP_ID",
"appVersion": "2.3.1",
"platform": "INTEGRATOR"
},
"callbackReference": {
"incomingCallChannelId": "Webhook.6050752e-78dd-47af-8e22-552d3d6e3326",
"sessionManagementChannelId": "Webhook.6050752e-78dd-47af-8e22-552d3d6e3326"
}
}'
Response
The response is an HTTP 201 CREATED response containing the data for the device created:
{
"clientInformation": {
"deviceId": "1234567809012111116",
"appId": "INTEGRATOR_APP_ID",
"appVersion": "2.3.1",
"platform": "INTEGRATOR"
},
"callbackReference": {
"incomingCallChannelId": "Webhook.6050752e-78dd-47af-8e22-552d3d6e3326",
"sessionManagementChannelId": "Webhook.6050752e-78dd-47af-8e22-552d3d6e3326"
}
}
Request to create an extension under the device
Use the device ID from previous step as input to create a new extension.
curl --request POST \
--url https://api.goto.com/web-calls/v1/devices/1234567809012111116/extensions \
--header 'Authorization: Bearer {ACCESS_TOKEN}' \
--header 'content-type: application/json' \
--data '{
"organizationId": "INTEGRATOR_ORG_ID",
"extensions": [{"number": "0523"}]
}'
Response
The response is an HTTP 201 CREATED response containing the data for the extension under the device created:
{
"organizationId": "INTEGRATOR_ORG_ID",
"extensions": [
{
"number": "0523",
"sessionId": "0wwAUTEn693d1amuXdfoqjIEpq7xLHJahKMzixoqg9Io_ELbQGQGDkSM5BAGmgQtT_pXdYo44gXqJ_XDO5-iCJQ",
"resultCode": 201
}
]
}
Following a successful extension creation, you will also receive a greeting notification which confirms the extension is ready to receive calls.
The greetings
notification has the following structure:
{
"source": "WebRTC",
"type": "greetings",
"timestamp": "2020-04-16T21:18:57.008116-04:00",
"usage": "BACKGROUND",
"ttl": "120",
"content": {
"sessionId": "0wwAUTEn693d1amuXdfoqjIEpq7xLHJahKMzixoqg9Io_ELbQGQGDkSM5BAGmgQtT_pXdYo44gXqJ_XDO5-iCJQ",
"organizationId": "INTEGRATOR_ORG_ID",
"extensionNumber": "0523"
}
}
When your extension is called, you will receive the following notification.
{
"source": "WebRTC",
"type": "incoming",
"timestamp": "2020-04-16T21:18:59.300359-04:00",
"usage": "VOIP",
"ttl": "30",
"content": {
"sessionId": "0wwAUTEn693d1amuXdfoqjIEpq7xLHJahKMzixoqg9Io_ELbQGQGDkSM5BAGmgQtT_pXdYo44gXqJ_XDO5-iCJQ",
"organizationId": "INTEGRATOR_ORG_ID",
"extensionNumber": "0523",
"callId": "1b94f3561664ab3425318e3f69de3634",
"name": "Bob",
"number": "+5143334444"
}
}
You have to provide your local SDP and your inCallChannelId
to
the answer endpoint
{
"dialString": "+15559998888",
"sdp": "v=0\r\no=rtcweb 1 1 IN IP4 199.88.123.123\r\ns=-\r\nt=0 0\r\na=ice-lite\r\na=group:BUNDLE audio\r\na=msid-semantic: WMS ANAUOoBPqN08BQw7SeGk3EhjiTBWNaDXu47M\r\nm=audio 40342 UDP/TLS/RTP/SAVPF 111 126\r\nc=IN IP4 199.88.123.123\r\na=ice-ufrag:YoPy\r\na=ice-pwd:gv3wCs/e+Rn5YKunE/J7tRi7\r\na=fingerprint:sha-256 F5:F5:F5:F5:F5:F5:F5:F5:F5:F5:A1:A1:A1:A1:A1:A1:A1:A1:A1:A1:A1:A1:A1:A1:A1:A1:A1:A1:A1:A1:A1:A1\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=setup:passive\r\na=sendrecv\r\na=rtcp-mux\r\na=rtpmap:111 opus/48000/2\r\na=rtpmap:126 telephone-event/8000\r\na=maxptime:60\r\na=candidate:0 1 UDP 2113667327 199.88.123.123 40342 typ host\r\na=end-of-candidates\r\n",
"inCallChannelId": "Webhook.6050752e-78dd-47af-8e22-552d3d6e3326"
}
The call may also be declined or sent to voicemail instead with the reject endpoint:
{
"action": "SEND_TO_VOICEMAIL"
}
Request to make a call
The device ID and extension from the previous steps are used to create the call along with the Session Description Protocol (SDP).
To actually make and receive calls, you will have to generate an SDP from a WebRTC audio device. For instance, GStreamer provides such a feature: GStreamer SDP example
Please refer to the proper documentation and tools:
- https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection
- https://webrtc.github.io/samples/src/content/peerconnection/pc1/
curl --request POST \
--url https://api.goto.com/web-calls/v1/calls \
--header 'Authorization: Bearer {ACCESS_TOKEN}' \
--header 'content-type: application/json' \
--data '{
"deviceId": "1234567809012111116",
"organizationId": "INTEGRATOR_ORG_ID",
"extensionNumber": "0523",
"dialString": "+13142797222",
"inCallChannelId": "Webhook.6050752e-78dd-47af-8e22-552d3d6e3326",
"sdp": "v=0\r\no=- 1383702073071536301 0 IN IP4 0.0.0.0\r\ns=-\r\nt=0 0\r\na=ice-options:trickle\r\nm=audio 9 UDP/TLS/RTP/SAVPF 111\r\nc=IN IP4 0.0.0.0\r\na=setup:actpass\r\na=ice-ufrag:eY+OHWN3One9/3HEjO8hizCdC151zMuj\r\na=ice-pwd:6V4eSXF/FlGsg25aSo7z4/J4xZ4Q9XSb\r\na=rtcp-mux\r\na=rtcp-rsize\r\na=sendrecv\r\na=rtpmap:111 OPUS/48000/2\r\na=rtcp-fb:111 nack pli\r\na=fmtp:111 sprop-maxcapturerate=48000;sprop-stereo=0\r\na=ssrc:757366242 msid:user3302805192@host-5dce804e webrtctransceiver0\r\na=ssrc:757366242 cname:user3302805192@host-5dce804e\r\na=mid:audio0\r\na=fingerprint:sha-256 6C:A1:94:5A:63:3C:05:19:2A:C0:43:5F:A9:C4:F8:A8:6A:55:6A:88:B2:23:23:EA:B7:94:58:A3:E7:EF:57:20\r\na=candidate:1 1 UDP 2013266431 172.17.0.4 50127 typ host\na=candidate:2 1 TCP 1015021823 172.17.0.4 9 typ host tcptype active\na=candidate:3 1 TCP 1010827519 172.17.0.4 55307 typ host tcptype passive\na=candidate:1 2 UDP 2013266430 172.17.0.4 57628 typ host\na=candidate:2 2 TCP 1015021822 172.17.0.4 9 typ host tcptype active\na=candidate:3 2 TCP 1010827518 172.17.0.4 38989 typ host tcptype passive"
}'
Response
The response returned is an HTTP 201 CREATED containing the following response:
{
"id": "0wwAUTCbVnLBq9kdkBxMUMVB3EZ1fDrGynJk3WMpLFtljF9lmpAA-mTbDrbxxQSJGgDEjix3FdX5nY3ubg9KQkQ",
"number": "+13142797222",
"name": "-",
"isMuted": false,
"isOnHold": false,
"hasMedia": true,
"ringingInMedia": false,
"sdp": "v=0\r\no=rtcweb 1 1 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=ice-lite\r\nm=audio 19348 RTP/SAVPF 111\r\nc=IN IP4 216.115.212.139\r\na=ice-ufrag:PLMm\r\na=ice-pwd:RWzGxDSYDZxfWCau+uGWMsHp\r\na=fingerprint:sha-256 D1:D8:2F:9D:A8:CF:A0:3E:CF:86:09:92:03:7F:7E:0D:3C:D8:59:35:EC:EE:FC:E7:A7:B7:EC:B0:F0:4F:FF:DA\r\na=setup:passive\r\na=sendrecv\r\na=rtcp-mux\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=rtpmap:111 OPUS/48000/2\r\na=maxptime:60\r\na=candidate:0 1 UDP 2113667327 216.115.212.139 19348 typ host\r\na=end-of-candidates\r\na=ssrc:3014495467 cname:bf7ad5bd-418c-497b-9c94-c893a6137d6c\r\na=ssrc:3014495467 msid:65fd86aa-95b4-41a2-9087-f2f774e34003 f90729e8-5dcc-4062-acf2-c22e5dfc6d04\r\na=ssrc:3014495467 mslabel:65fd86aa-95b4-41a2-9087-f2f774e34003\r\na=ssrc:3014495467 label:f90729e8-5dcc-4062-acf2-c22e5dfc6d04\r\n",
"status": "CONNECTING",
"timestamp": "2023-09-06T16:21:15.051283Z",
"sipCallId": "1390857315202413322_1390857315202413322~0523~eb95191a-078b-4dea-afbf-de1c5acfbe13_B0NuCDOB95GVoQIoSiD13sR44mJ0XWeX",
"legId": "dd6a5d9a-da87-469c-b76f-1d45bc214588"
}
Subsequent events in relationship to the call will be sent to the provided inCallChannelId
.
Have a look at the callbacks on this operation, here is one example :
{
"source": "WebRTC",
"type": "ended",
"timestamp": "2020-04-16T21:18:59.300359-04:00",
"usage": "ALERT",
"ttl": "3600",
"content": {
"sessionId": "0iO2GMahypu5trGOzcfGlGQZLKpUWC2lxvgSLCd",
"organizationId": "INTEGRATOR_ORG_ID",
"extensionNumber": "1121",
"callId": "1b94f3561664ab3425318e3f69de3634",
"reasonCode": "BYE"
}
}