NAV Navbar
http

Introduction

Welcome to the Gamma CRM API. You can use our API to integrate your CRM , ERP or any other enterprise system with Gamma's telephony service. The API is divided in events and requests.

Events inform you of the development of calls in your cloud telephony system. For instance the arrival of an incoming call, the stablishment of a call or the end of it. Events are sent from Gamma to you via HTTP/S. You need to implement an endpoint to manage these events. The URL of your endpoint as well as other configuration paramenters can be set by the request calls in this API.

Requests are sent from you to Gamma. They let you configure the API, manage ongoing calls and trigger new ones.

In order to use this API you must be customer of Gamma and subscribe the CRM Integration service. Go to Gamma for more information.

Authentication

The API requests are authorized with an Authentication token sent along with the request. All HTTP Requests should include an authentication header like the following

Authorization: VTCRM-Basic 83isocjid5hyd02sdjiembslw323

Failure to provide a valid authentication token will lead to a 401 HTTP Response

Requests API

At this time the requests API has six methods: the API configuration method, the extension list methods that comes in two flavors, the call triggering method, the call drop method and the call redirect method. By using the configuration method you can configure how the events API will notify you of the communication events that take place in realtime. The extension list methods provide information on the extensions setup at the PBX. By using the call triggering method you can start a call between one of the extensions in your cloud communications system and another extension or geographical number, fixed, mobile, national or international. The method supports the specification of callback parameters that will allow you to correlate the calls requested with the events reported by the Events API. Established calls can be dropped with the Call Drop method. Incoming calls, whether established or in alerting state, can be also cold forwarded using the Redirect Call Method.

API Configuration method

Use this request to configure the events API. You can configure the URL where you expect to receive the notifications of the communication events as well as the HTTP method of the notification requests, the headers and the parameters.

HTTP Request

POST https://config.work.oigaa.com/vtcrm/api/configure

curl "https://config.work.oigaa.com/vtcrm/api/configure"
  -H "Authorization: VTCRM-Basic 83isocjid5hyd02sdjiembslw323"

The above command takes a JSON payload structured like this:

  {
    "events_callback_url": "https://example.com/vtcrm/callback",
    "events_callback_headers": {
                "X-A-Header" : "A header value",    
                "X-Another-Header" : "Another header value" 
                },
    "events_callback_parameters": {
                "a_parameter" : "A parameter value",    
                "another_parameter" : "Another parameter value" 
                },
    "allowed_ip_address" : ["193.22.119.28","218.32.3.0/32"]
  }

Query Parameters

Parameter Mandatory Description
events_callback_url yes The URL of the events endpoint where you expect to receive the event notifications. Standard HTTP response codes are expected.
events_callback_headers no A json object whose attribute names/values will be sent as header names / values in each event callback request.
events_callback_parameters no A json object whose attribute names and values will be sent as request attribute names and values in each event callback request.
allowed_ip_addresses no A json array with the list of valid IP addresses and/or subnetworks in CIDR notation. If not specified the current addresses remain. If you want to eliminate the restriction specify the 0.0.0.0/0 subnet.

Extension list method

You can use this method to retrieve a list of all the extensions in your telephony system that have the API service activated.

HTTP Request

GET https://config.work.oigaa.com/vtcrm/api/getExtensionList

curl "https://config.work.oigaa.com/vtcrm/api/getExtensionList"
  -H "Authorization: VTCRM-Basic 83isocjid5hyd02sdjiembslw323"

The answer is a json array with the extensio numbers:

  [200,201,202,203,204,205,206]

Extended extension list method

If you want to have extended information on your extensions you can use this method that returns an array of extensions objects in JSON

HTTP Request

GET https://config.work.oigaa.com/vtcrm/api/getExtensionListJSON

curl "https://config.work.oigaa.com/vtcrm/api/getExtensionListJSON"
  -H "Authorization: VTCRM-Basic 83isocjid5hyd02sdjiembslw323"

The answer is a json array with the extensio numbers:

 [
  {
    "extension":201,
    "name":"Gines Gomez"
  },
  {
    "extension":202,
    "name":"Antonio Abajo"
  },
  {
    "extension":203,
    "name":"Tony Manero"
  },
  {
    "extension":204,
    "name":"Sandra Thomas"
  },
  {
    "extension":206,
    "name":"Peter Garrisson"
  },
  {
    "extension":9204,
    "name":"Incoming IVR"
  }
]

Trigger Call method

Use this request to trigger a call from your CRM, ERP or any other enterprise systems. Call triggering works as follows. Firts you use the call trigger method to tell Gamma which extension you want to dial to which destination. The destination can be another extension or a geographical number, fixed, mobile, national or international. Any number that you could dial from your phone is a valid number. You don't have to worry about the dial out prefix, if your PBX uses a dialout out prefix (for instance 0) the API will add it automatically in case it is not present.

When you make a call triggering request you can specify some data related to your application that you want back in your request. Every event generated by the call triggered by your request will include the data you specified allowing you to correlate request and events. The data can be sent back to your system as a set of headers and/or parameters. If you want to mark this call with a unique id specific to your system you can do it by adding the header X-VTCRM-External-Call-Id to the request_callback_headers. This will allow you to later on drop or redirect the call using your id instead of Gamma's call id.

HTTP Request

POST https://config.work.oigaa.com/vtcrm/api/call

curl -X "https://config.work.oigaa.com/vtcrm/api/call"
  -H "Authorization: VTCRM-Basic 83isocjid5hyd02sdjiembslw323"

The above command takes a JSON payload structured like this:

  {
    "extension": "203",
    "destination": "647460197",
    "request_callback_headers": {
      "X-Request-Header" : "A request header value",    
      "X-Another-Request-Header" : "Another request header value",
      "X-VTCRM-External-Call-Id" : "myApplicationCallid_1234"    
    },
    "request_callback_parameters": {
      "a_request_parameter" : "A request parameter value",    
      "another_request_parameter" : "Another request parameter value" 
    }
  }

Query Parameters

Parameter Mandatory Description
extension yes The extension that will perform the call
destination yes The destination number of the call
request_callback_headers no A json object whose attribute names/values will be sent as header names / values in each event callback request of the call triggered
request_callback_parameters no A json object whose attribute names and values will be sent as request attribute names and values in each event callback request of the call triggered

Drop Call method

Use this request to drop an ongoing call from your CRM. You have to send the id of the call that you want to drop. The callId is one of the attributes in the events API and it is present in all of the events related to the call.

HTTP Request

POST https://config.work.oigaa.com/vtcrm/api/drop

curl "https://config.work.oigaa.com/vtcrm/api/call"
  -H "Authorization: VTCRM-Basic 83isocjid5hyd02sdjiembslw323"

The above command takes a JSON payload structured like this:

  {
    "callId": "471900"
  }

Query Parameters

Parameter Mandatory Description
callId yes The id of the call as per the event API.

Redirect Incoming Call method

Use this method to make a cold transfer of an established incoming call to another extension. You have to send the id of the call that you want to redirect and the destination. The callId is present at every event generated by the Events API.

HTTP Request

POST https://config.work.oigaa.com/vtcrm/api/redirectIncoming

curl "https://config.work.oigaa.com/vtcrm/api/redirectIncoming"
  -H "Authorization: VTCRM-Basic 83isocjid5hyd02sdjiembslw323"

The above command takes a JSON payload structured like this:

  {
    "callId": "1542399572160",
    "destination" : "202"
  }

Query Parameters

Parameter Mandatory Description
callId yes The id of the call that you want to redirect.
destination yes The destination number where you want the call to be transferred.

Events API

Events inform your CRM system of what's going on in the network. Every incoming or outgoing call in your PBX will trigger one or more events that will allow you to keep your information systems synchronized in realtime time with your communications. It is worth noting that all event generation and notificacion takes place on the cloud and don't rely on your fixed and mobile phones being powered on or connected. If you need to open up your firewalls to receive events from Gamma the source IP address will be one in the subnet 193.22.119.0/24. Events are generated on a per-extension basis. That means means that when you receive an incoming call from an external number to the extension 203 for instance, you will receive a series of events related to such call, that will inform you of an incoming call whose destination is the extension 203. When the extension let's say, 202, performs an outgoing call to an external destination you will receive a series of events reporting an outgoing call with the extension 202 as source. When the extension 202 calls the extension 203 you will only receive the events related to the extension 203 which sees the call as incoming. Internal outgoing calls are not reported.

Events Callbacks

When you use the request API to configure how you want to receive the communication events you specify a callback URL as well as a set of headers and parameters. All parameters and headers that you specified will be present in each and every event notification request. They will be exactly the same across all requests unless you change them with a new call to the API configuration method.

Event callback notification

The events will be reported in order of arrival one by one. Every request will contain a X-VTCRM-PBXID header indicating to which PBX the event belongs to

POST https://callbackserver.yourdomain.com/vtcrm/callback

X-VTCRM-PBXID: yourPBXId

> Event data comes in the form of a JSON object with every notification

{
    "callId":"321296",
    "callLegId":"1541763052549.-478323",
    "displayedExternalNumber":"+34647460197",
    "displayedLabel":"647460197",
    "displayedNumber":"0647460197",
    "isIncoming":"true",
    "isRecording":"false",
    "eventTimestamp":"1541763052569",
    "state":"ringing",
    "stateCause":"causeNormal",
    "extension":"203"
}

Event Attributes

Parameter Always Present Description
callId yes The id of the call
callLegId yes The id of the call leg. A call can have various legs when there is a transfer, an parallel delivery, etc...
isIncoming yes Indicates wether the call is incoming or outgoing
displayedExternalNumber yes The long number of the entity being called for an outgoing call or calling in for incoming calls.
displayedLabel yes The label of the entity being called for an outgoing call or calling in for incoming calls.
displayedNumber yes The number of the entity being called for an outgoing call or calling in for incoming calls.
isRecording yes Indicates wether this call is being recorded or not
eventTimestamp yes The timestamp at which this event was created
state yes Status of the call leg. It can be "ringing", "talking" or "dropped". Calls triggered with the trigger call API produce an initial extra event with the state "prompting". Other events not related to the call status are "recordingAvailable" that signals the availability of a new call recording, "transcriptionAvailable" which indicates that the transcription of a recording is available and "appDataAvailable" that indicates the input of application data (DTMFs on an IVR for instance)
stateCause yes Reason for the call leg to be in this state
extension yes The extension that sends or receives the call
originallyFrom no If the call was transferred from a previous call it will contain the source of the incoming call
originallyTo no If the call was transferred from a previous call it will contain the destination of the incoming call
originalIsIncoming no If the call was transferred from a previous call it will tell you wether the original call was incoming or outgoing
originalCallId no The callId of the original call this call was transferred from
firstFrom yes The source of the original call of a chain of transfers
firstTo yes The destination of the original call of a chain of transfers
firstIsIncoming yes Indicates the direction of the first call of a chain of transfers
firstCallId  yes The callId of the first call of a chain of transfers

Incoming answered call example

The following example depicts the events generated related to the reception of an incoming call from the number 647460197 to the extension 203

> Incoming call from 647460197, the extension 203 rings.
{
   "callId":"471900",
   "callLegId":"1542399572160.-703374",
   "displayedExternalNumber":"+34647460197",
   "displayedLabel":"647460197",
   "displayedNumber":"0647460197",
   "isIncoming":"true",
   "isRecording":"false",
   "eventTimestamp":"1542399572176",
   "state":"ringing",
   "stateCause":"causeNormal",
   "extension":"203",
   "firstFrom":"0647460197",
   "firstTo":"203",
   "firstIsIncoming":"false",
   "firstCallId":"471900"
}

> The extension answers the call. The state changes from ringing to talking. 

{
   "callId":"471900",
   "callLegId":"1542399572160.-703374",
   "displayedExternalNumber":"+34647460197",
   "displayedLabel":"647460197",
   "displayedNumber":"0647460197",
   "isIncoming":"true",
   "isRecording":"false",
   "eventTimestamp":"1542399578197",
   "state":"talking",
   "stateCause":"causeNormal",
   "extension":"203",
   "firstFrom":"0647460197",
   "firstTo":"203",
   "firstIsIncoming":"false",
   "firstCallId":"471900"
}

> The extension drops the call. The state changes from talking to dropped. 

{
   "callId":"471900",
   "callLegId":"1542399572160.-703374",
   "displayedExternalNumber":"+34647460197",
   "displayedLabel":"647460197",
   "displayedNumber":"0647460197",
   "isIncoming":"true",
   "isRecording":"false",
   "eventTimestamp":"1542399582021",
   "state":"dropped",
   "stateCause":"causeNormal",
   "extension":"203",
   "firstFrom":"0647460197",
   "firstTo":"203",
   "firstIsIncoming":"false",
   "firstCallId":"471900"
}

Incoming missed call example

The following example depicts the events generated related to the reception of an incoming call from the number 647460197 to the extension 203 that is never answered


> Incoming call from 647460197, the extension 203 rings.

{
   "callId":"472362",
   "callLegId":"1542401480524.-704062",
   "displayedExternalNumber":"+34647460197",
   "displayedLabel":"647460197",
   "displayedNumber":"0647460197",
   "isIncoming":"true",
   "isRecording":"false",
   "eventTimestamp":"1542401480534",
   "state":"ringing",
   "stateCause":"causeNormal",
   "extension":"203",
   "firstFrom":"0647460197",
   "firstTo":"203",
   "firstIsIncoming":"true",
   "firstCallId":"472362"
}


> After receiving no answer the caller drops the call. The state changes directly from ringing to dropped.

{
   "callId":"472362",
   "callLegId":"1542401480524.-704062",
   "displayedExternalNumber":"+34647460197",
   "displayedLabel":"647460197",
   "displayedNumber":"0647460197",
   "isIncoming":"true",
   "isRecording":"false",
   "lastModificationTime":"1542401484054",
   "state":"dropped",
   "stateCause":"causeNormal",
   "extension":"203",
   "firstFrom":"0647460197",
   "firstTo":"203",
   "firstIsIncoming":"true",
   "firstCallId":"472362"
}   

Outgoing answered call

The following example depicts the events generated related to the emission of an outgoing call to the number 647460197 from the extension 203 that is answered


> Outgoing call to 647460197, the external number rings 

{
   "callId":"472367",
   "callLegId":"1542401510978.-704065",
   "displayedExternalNumber":"+34647460197",
   "displayedLabel":"647460197",
   "displayedNumber":"0647460197",
   "isIncoming":"false",
   "isRecording":"false",
   "eventTimestamp":"1542401510992",
   "state":"alerting",
   "stateCause":"causeNormal",
   "extension":"203",
   "firstFrom":"203",
   "firstTo":"0647460197",
   "firstIsIncoming":"false",
   "firstCallId":"472367"
}

> 647460197 answers the call

{
   "callId":"472367",
   "callLegId":"1542401510978.-704065",
   "displayedExternalNumber":"+34647460197",
   "displayedLabel":"647460197",
   "displayedNumber":"0647460197",
   "isIncoming":"false",
   "isRecording":"false",
   "eventTimestamp":"1542401516677",
   "state":"talking",
   "stateCause":"causeNormal",
   "extension":"203",
   "firstFrom":"203",
   "firstTo":"0647460197",
   "firstIsIncoming":"false",
   "firstCallId":"472367"
}

The call is dropped

{
   "callId":"472367",
   "callLegId":"1542401510978.-704065",
   "displayedExternalNumber":"+34647460197",
   "displayedLabel":"647460197",
   "displayedNumber":"0647460197",
   "isIncoming":"false",
   "isRecording":"false",
   "eventTimestamp":"1542401521090",
   "state":"dropped",
   "stateCause":"causeNormal",
   "extension":"203",
   "firstFrom":"203",
   "firstTo":"0647460197",
   "firstIsIncoming":"false",
   "firstCallId":"472367"
}


Outgoing unanswered call

The following example depicts the events generated related to the emission of an outgoing call to the number 647460197 from the extension 203 that is not answered


> Outgoing call to 647460197, the external number rings

{
   "callId":"472388",
   "callLegId":"1542401535786.-704094",
   "displayedExternalNumber":"+340647460197",
   "displayedLabel":"0647460197",
   "displayedNumber":"00647460197",
   "isIncoming":"false",
   "isRecording":"false",
   "eventTimestamp":"1542401535788",
   "state":"alerting",
   "stateCause":"causeNormal",
   "extension":"203",
   "firstFrom":"203",
   "firstTo":"0647460197",
   "firstIsIncoming":"false",
   "firstCallId":"472388"
}

> After receiving no answer the extension 203 drops the call. The state changes directly from ringing to dropped.
{
   "callId":"472388",
   "callLegId":"1542401535786.-704094",
   "displayedExternalNumber":"+340647460197",
   "displayedLabel":"0647460197",
   "displayedNumber":"00647460197",
   "isIncoming":"false",
   "isRecording":"false",
   "eventTimestamp":"1542401541347",
   "lineId":"-704094",
   "state":"dropped",
   "stateCause":"causeNormal",
   "extension":"203",
   "firstFrom":"203",
   "firstTo":"0647460197",
   "firstIsIncoming":"false",
   "firstCallId":"472388"
}

Call Transfer

When a call is transferred to a third extension it is considered finished and replaced by a new call.


> Notification of the end of the original call. Please note that stateCause is set to "causeTransfer"

{
   "callId":"1558393109565",
   "callLegId":"1559134729837.-2132992",
   "displayedExternalNumber":"0647460197",
   "displayedLabel":"0647460197",
   "displayedNumber":"0647460197",
   "isIncoming":"false",
   "isRecording":"false",
   "eventTimestamp":"1559134729837",
   "state":"dropped",
   "stateCause":"causeTransfer",
   "extension":"201",
   "firstFrom":"201",
   "firstTo":"0647460197",
   "firstCallId":"1558393109565",
   "firstIsIncoming" : "false"
}

> Notification of the creation of the transferred call. A few things to check out here.
The callId is the original callid with a suffix ".1" indicating that this is a first transfer.
There are four new attributes, originallyFrom, originallyTo, originalCallId and originalIsIncoming 
that provide information about the original call. 

{
   "callId":"1558393109565.1",
   "callLegId":"1559134772839.-2133134_1",
   "displayedExternalNumber":"201",
   "displayedLabel":"Ext 201",
   "displayedNumber":"201",
   "isIncoming":"true",
   "isRecording":"false",
   "eventTimestamp":"1559134772839",
   "state":"alerting",
   "stateCause":"causeNormal",
   "extension":"301",
   "originallyFrom":"201",
   "originallyTo":"0647460197",
   "originalIsIncoming":"false",
   "originalCallId":"1558393109565",
   "firstFrom":"201",
   "firstTo":"0647460197",
   "firstCallId":"1558393109565",
   "firstIsIncoming":"false"
}

> We have also firstFrom, firstTo and firstCallId that contain information 
of the original call. The difference with the originalXXX attributes is that if more transfers 
are chained these values will always retain the first call values. Consider a further transfer of 
the above example that generates the following event

{
   "callId":"1558393109565.2",
   "callLegId":"1559135218331.-2135163_1",
   "displayedExternalNumber":"301",
   "displayedLabel":"Ext 301",
   "displayedNumber":"301",
   "isIncoming":"true",
   "isRecording":"false",
   "eventTimestamp":"1559135218331",
   "state":"alerting",
   "stateCause":"causeNormal",
   "extension":"201",
   "originallyFrom":"201",
   "originallyTo":"301",
   "originalCallId":"1558393109565.1",
   "originalIsIncoming":"false"
   "firstFrom":"201",
   "firstTo":"0647460197",
   "firstCallId":"1558393109565",
   "firstIsIncoming":"false"
}

> See how the sequence of the callId now increased by one up to ".2" and the originalXXX 
attributes hold the values of the previous transferred call while the firstXXX attributes hold the 
values of the very first call.

Call Recording

Call recording can be activated on a per extension basis or generally for all the PBX depending on your product. A few minutes after a recorded call finishes the system will notify of its availability by means of an special event with the state "recordingAvailable". The actual exchange of the recordings (normally mp3 files) between Gamma and your systems is out of the scope of this API and will by agreed with each partner. It is worth noting though that the "recordingAvailable" event can be subject to the actual completion of the transfer so your application can safely count on the media being available to the users after the reception of the notification.


> Notification of the availability of a call recording
{
   "callId":"472388",
   "state":"recordingAvailable",
   "stateCause":"informative"
} 

Call Transcription

If you have activated Call recording you can get transcriptions of your calls provided that you have a valid Google Cloud to Speech account. After the availability of the recording is notified via the "recordingAvailable" event you will receive a second "transcriptionAvailable" event with the contents of the conversation as per the Google Speech format. If you want us to transcript your calls we will need a service key for your Google Speech account granted with the necessary permissions Google Speech API permissions. Permissions to modify files on a Google Storage bucket are required too for recordings longer than one minute. Please check out https://cloud.google.com/speech-to-text/docs/ for more info on the transcription formats and permissions necessary to operate.


> Notification of the availability of a call transcription
{
   "callId":"472388",
   "state":"transcriptionAvailable",
   "transcription" : {
                       "results": [
                         {
                           "alternatives": [
                             {
                               "transcript": "Hi, good Morning",
                               "confidence": 0.8930228
                             }
                           ],
                           "resultEndTime": "5.640s"
                         },
                         {
                           "alternatives": [
                             {
                               "transcript": " Good Morning sir, How can I help you ?",
                               "confidence": 0.9101991
                             }
                           ],
                           "resultEndTime": "10.220s"
                         },
                         {
                           "alternatives": [
                             {
                               "transcript": " I'd like some information.",
                               "confidence": 0.8818244
                             }
                           ],
                           "resultEndTime": "13.870s"
                         }
                      ]
                     }
   "stateCause":"informative"
} 

Call Data

You can setup an IVR to produce events with the contents of user input. Think for instance of an IVR that asks the caller for its ID. An example of call data representing the input the digits 435267232 on an IVR would be as follows


> Notification of new call data
{
   "callId":"1614639701402",
   "appData":"435267232",
   "state":"appDataAvailable",
   "stateCause":"informative",
   "callLegId":"1616752651791.-3682435",
   "displayedExternalNumber":"0941892961",
   "displayedLabel":"IncomingVTCRMIvr",
   "displayedNumber":"0941892961",
   "isIncoming":"true",
   "isRecording":"false",
   "extension":"9900",
   "firstIsIncoming":"true",
   "firstFrom":"0941892961",
   "firstTo":"999002929",
   "firstCallId":"1614639701402",   
   "eventTimestamp":"1616752779576"
}

Security

All requests to the API have to be authenticated with an Authorization Header. The authorization header contains the API key that identifies your communications service in Gamma and allows you to use it via this API. It is very important that you keep this key private and never share it with anyone. All requests that use the API key are sent over HTTPS thus avoiding the possibility of sniffing it out.

If you want to further secure your service you can specify a list of IP addresses/networks that you consider valid origins for the API requests made with your key. If a request from an unauthorized IP arrives it will be automatically declined regardless the fact that the key is valid. When we setup your account we will ask you for an initial list of IP addresses that you want to white list. After that you can manage the list using the API configuration method.

Regarding the event notifcations that you will receive from Gamma, if you need to do firewall arrangements the origin address of the requests will always be in the subnet 193.22.119.0/24. This network is owned and operated exclusively by Gamma. Last but not least we strongly recommend that you provide an HTTPS endpoint for event notification but you are entitled to use HTTP if you can't. Please keep in mind that the policy may change in the future so please consider setting up encryption as long as that is possible.

Errors

Standar HTTP errors are used in all the requests methods. The reason for the error can be clarified beyond the status code in the Reason Phrase

Error Code Meaning
400 Bad Request -- Your request is invalid. Check the reason phrase to know what is wrong.
401 Unauthorized -- Your API key is wrong.
403 Forbidden -- You are not allowed to carry out the action requested.
405 Method Not Allowed -- You used a method other than POST to access the API
429 Too Many Requests -- You're requesting too often. Slow down.
500 Internal Server Error -- We had a problem with our server. Try again later.
503 Service Unavailable -- We're temporarily offline for maintenance. Please try again later.