GoTo Developer

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:

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:

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"
  }
}