Getting a single conversation

Hi,

I’m trying to fetch a single call using the Media - Calls API but are faced with a 403 forbidden error and a message that sends back my oauth token twice. The same issue occures when trying to fetch a single call record.

I’m testing this with the Postman Library. The error is the following: message: “’{tokenvalue}’ not a valid key=value pair (missing equal-sign) in Authorization header: ‘Bearer {tokenValue}’.” where {tokenValue} is the value of my bearer token.

Steps to reproduce:

  1. Get token using the password OAuth Flow

  2. Create a call and get the callId from the calls API: GET {{media_url}}/calls. This returns an array of calls with a callId in my example this is endpoints/200/calls/335

  3. Create a request to call state or call record api: GET {{media_url}}/calls/endpoints/200/calls/335

I’m not sure the full callId is the right parameter to pass here but at least the error is very unclear. Also when passing the PBX call Id for this call which is just plain ‘335’ i get a response with the status code 404 Not Found and the same goes for the return message ‘Not Found’ so that’s not the right call to make either.

Small update: when using the subscription on the ‘Call Records’ the API returns a GUID als a callId which does work when used to try to get that specific Call Record.

This makes me think that what is returned as a callId when using the ‘Call’ API isn’t actually the callId. It also looks more like a call path than an actual id.

Small update 2: same problem emerges when trying to do call control on the received call.

The error message you’re receiving typically occurs when you’re trying to hit an invalid path. /calls/endpoints/200/calls/335 isn’t a valid path, hence the error. You’ve correctly surmised that the correct callID should be the GUID. Can you please post the response for a single record when you run GET Calls? If there’s sensitive data there, feel free to message me directly.

When you’re trying to perform call control, are you using the GUID that you found from your subscription to the call record, or the “200/calls/335” value that you found from GET Calls?

Hi Budd,

Well I can’t use the GUID received from the call record since that is only posted after the call is finished (so this is not the ‘Call’ API but the ‘Call Record’ API).

This is what I get from the subscription:

{
    "publicationId": "53e94c08-74fc-45d6-974a-3026a0a5bb9b",
    "topic": "platform-api-media",
    "method": "PUT",
    "subject": "/2017-09-01/endpoints/200/calls/350",
    "content": {
        "_links": {
            "self": "/2017-09-01/endpoints/200/calls/350"
        },
        "from": "201",
        "fromName": "",
        "to": "200",
        "toName": "",
        "state": "ringing",
        "cause": "newCall",
        "direction": "inbound",
        "extraPbxData": {
            "alertingDevice": "200",
            "calledDevice": "200",
            "callTrackingID": "1618933141#42",
            "eventType": "deliveredEvent"
        },
        "createdOn": "2021-04-20T15:39:01.286Z",
        "callId": "endpoints/200/calls/350",
        "endpointId": "200",
        "accountId": "{{accountGuid}}",
        "siteId": "{{siteGuid}}",
        "timestamp": 1618933141287,
        "isCtiEvent": true,
        "principalId": "{{principalId}}",
        "callLegOwner": "{{principalId}}"
    },
    "publisher": {
        "accountId": "{{accountGuid}}",
        "principalId": "platform-api-mediaservice-eu-west-1-913011122217-eu"
    },
    "subscription": {
        "subscriptionId": "{{subscriptionGuid}}"
    },
    "notification": {
        "createdOn": "2021-04-20T15:39:01.362Z",
        "correlationId": "e5285ae5-47d4-4043-b921-108bc85c72ce"
    }
}

When I receive the Call Record after the call is finished, the callId there doesn’t match any guid from the above JSON.

Almost the same information is given from the GET request on the Call API.

{
    "count": 2,
    "_links": {
        "self": "/2017-09-01/calls"
    },
    "_embedded": {
        "items": [
            {
                "callId": "endpoints/200/calls/335",
                "accountId": "{{accountGuid}}",
                "siteId": "{{siteGuid}}",
                "direction": "inbound",
                "from": "201",
                "to": "200",
                "state": "ringing",
                "cause": "newCall",
               "createdOn": "2021-04-20T13:14:40.731Z",
                "extraPbxData": "{\"alertingDevice\":\"200\",\"calledDevice\":\"200\",\"callTrackingID\":\"1618924480#33\",\"eventType\":\"deliveredEvent\"}",
                "connectedParty": {},
                "_links": {
                    "self": "/2017-09-01/calls/endpoints/200/calls/335"
                }
            },
            {
                "callId": "endpoints/201/calls/335",
                "accountId": "{{accountGuid}}",
                "siteId": "{{siteGuid}}",
                "direction": "outbound",
                "from": "201",
                "to": "200",
                "state": "connected",
                "cause": "newCall",
                "createdOn": "2021-04-20T13:14:40.864Z",
                "extraPbxData": "{\"alertingDevice\":\"200\",\"calledDevice\":\"200\",\"callTrackingID\":\"1618924480#33\",\"eventType\":\"deliveredEvent\"}",
                "connectedParty": {},
                "_links": {
                    "self": "/2017-09-01/calls/endpoints/201/calls/335"
                }
            }
        ]
    }
}

Notice the self link here suggests to use the callId property as the actual callId in the URI (which obviously isn’t a GUID)

When you create the call using the API, does the response body not include the proper callID?

Hi Budd,

I think it’s a bit beside the point that somethings not right in the GET request and/or the notification of the calls. But I did a test and I get almost the same result.

 {
    "_links": {
        "self": "/2017-09-01/endpoints/200/calls/357"
    },
    "id": "357",
    "from": "200",
    "fromName": "",
    "to": "201",
    "toName": "",
    "state": "connected",
    "cause": "newCall",
    "direction": "outbound",
    "extraPbxData": {
        "callTrackingID": "1618944538#46",
        "eventType": "originatedEvent"
    },
    "createdOn": "2021-04-20T18:48:58.254Z",
    "callId": "357",
    "endpointId": "200"
}

As you can see both the id and callId are set to the id created by the PBX (357 - that’s the internal call record id of the call on the SMBC)

I believe the issue here is that the wrong resource is being used.
When you are trying to control a call that is on an on-premise endpoint you should use the Endpoint resource.

So if you want to get or update a that call state the route should be a GET or PUT on /endpoints/{endpointId}/calls/{callId}

In your example that would make the complete route.

https://media.dev.api.mitel.io/2017-09-01/endpoints/200/calls/335

Hi Tim,

So I should also be listining to the /endpoint notifications then? I however do receive the calls via the notifications on the /call resource.

What’s the difference between the 2 resources, when should we use the /call en when the /endpoint?

edit: also, is there a difference in API to call when it’s a call made using a local device or a local user his softphone or does that also count as a on-premise endpoint?

fyi: we are testing on a local SMBC linked to the dev cloudlink

What’s the difference between the 2 resources, when should we use the /call en when the /endpoint?

/calls - Used primarily for call control in the cloud. For something like MOWA where you have a cloud app running a softphone, some of the calls to this path will work but it’s designed more around future cloud PBX functionality.

/endpoints - Used for on-premise call control, such as for a MiVO400.

edit: also, is there a difference in API to call when it’s a call made using a local device or a local user his softphone or does that also count as a on-premise endpoint?

Best practice is to always using the /endpoint path, as the extension exists on the on-premise PBX even if a softphone is registered to it.

What would be the endpoint for MiVoice400?

Hi @Ashutosh!

With the MiVO400 (or any other on-premise PBX) you will need to use the /endpoint routes.

Hi Budd,

On initiating the Make Call from Device A to Device B using the Endpoint API, State A - Connected, State B - Ringing. Now if B answers the call how does A gets notified that B has answered, which API can be used on A for this? Similarly how an Device gets notified of an Incoming Call?
Do we need constantly poll for change in states of Endpoint?

Also, once the call is established is there any Media flow API work required for voice path? I didn’t see voice related APIs

Hi Sanjeev!

The information I’m providing here is pretty generic, I can give a bit more guidance if you can walk me through what you’re trying to accomplish in terms of both the desired outcome and workflow. Feel free to PM or email me that information if it’s sensitive in nature.

The Media API doesn’t actually handle any audio, it’s primarily used as a means of exercising call control. The audio is routed entirely through the PBX. There is technically an exception to this when using the /calls route, but that’s not relevant here. Here’s an oversimplified explanation of what happens:

  • The API receives a request to make a call from Device A to Device B
  • The API sends the relevant instructions to the CloudLink Gateway
  • The CloudLink Gateway converts the instructions into the appropriate CTI commands and tells the PBX what to do
  • The PBX initiates the call from Device A, then Device B rings
  • If Device B is answered (by a user, softphone app, or via the API), the audio connection is made between the two devices.

What’s nice is that you can get notifications for various events using the Notification API. Here’s some useful info:

Documentation - https://developer.mitel.io/api-reference/notifications
API Guide - https://developer.mitel.io/guides-resources/api-guides#notifications-api-guide

If you have a client that needs to know when a particular extension is ringing, you would create a Subscription using the Notification API that is set to filter for ringing events on a particular endpoint. You would then open a websocket to receive those events (WebSockets - Basic Workflow).

You could alternatively use webhooks if you are building a server side application. Your Subscription in that case could just filter for all ringing events on a range of endpoints, then process the data and push notifications out to the appropriate clients.

Thanks Budd for elaborate response. We got the required inputs.

Hi Budd,

When I initiate a call using postman, I get the status of origin phone as “connected” in response. How would I know if the destination phone has picked up my call?

One way of doing it would be to monitor the status of destination phone, if it changes from “ringing” to “connected”. But this approach would work only for internal calls, we cannot monitor the status of the destination phone if it is external call, say, to a cell phone.

We wanted to use a generic approach that would work for internal and external calls. Can you please provide your inputs around this?

With your developing on the MiVO400 platform, I’ve asked that development team for comment. I would expect that both endpoints would have a state of “ringing” while the call was, well…ringing.

I will also be reaching out to the Connect team to see if the behaviour is the same on their platform. I will provide an update here as soon as I can.

Hi @Ashutosh!

It looks like the behaviour you’re seeing is expected and is the industry standard for CSTA. Depending on the platform, there are occasionally additional events that are generated depending on if the originating device successfully dialed or not, but nothing that shows on the originating device that will tell you when the dialed device answers. When using the Media API, these ‘intermediate states’ are all aggregated up into the ‘Connected’ state anyways.

The short of this is, you’ll be able to code for internal calls because you can monitor the dialed endpoint to see when it answers. For external calls though, you won’t be able to monitor if the destination answers.