Add a Microsoft Teams user to an existing call using Call Automation
In this quickstart, we use the Azure Communication Services Call Automation APIs to add, remove, and transfer call to a Teams user.
Prerequisites
- An Azure account with an active subscription, for details see Create an account for free..
- A Microsoft Teams Phone license and a Teams tenant with administrative privileges. Teams Phone license is a must in order to use this feature, learn more about Teams licenses here. The Microsoft Teams user must also be
voice
enabled, see setting-up-your-phone-system. Administrative privileges are required to authorize Communication Services resource to call Teams users, explained later in Step 1. - A deployed Communication Service resource and valid connection string found by selecting Keys in left side menu on Azure portal.
- Acquire a PSTN phone number from the Communication Service resource. Note the phone number you acquired to use in this quickstart.
- An Azure Event Grid subscription to receive the
IncomingCall
event. - The latest Azure Communication Service Call Automation API library for your operating system.
- A web service that implements the Call Automation API library, follow this tutorial.
Step 1: Authorization for your Azure Communication Services Resource to enable calling to Microsoft Teams users
To enable calling through Call Automation APIs, a Microsoft Teams Administrator or Global Administrator must explicitly enable the Communication Services resources access to their tenant to allow calling.
Set-CsTeamsAcsFederationConfiguration (MicrosoftTeamsPowerShell) Tenant level setting that enables/disables federation between their tenant and specific Communication Services resources.
Set-CsExternalAccessPolicy (SkypeForBusiness) User policy that allows the admin to further control which users in their organization can participate in federated communications with Communication Services users.
Step 2: Use the Graph API to get Microsoft Entra object ID for Teams users and optionally check their presence
A Teams user’s Microsoft Entra object ID (OID) is required to add them to or transfer to them from a Communication Services call. The OID can be retrieved through 1) Office portal, 2) Microsoft Entra admin center, 3) Microsoft Entra Connect; or 4) Graph API. The following example uses Graph API.
A Microsoft Entra admin must grand consent before Graph can be used to search for users, learn more by following on the Microsoft Graph Security API overview document. The OID can be retrieved using the list users API to search for users. The following example shows a search by display name, but you can also search for other properties:
List users using Microsoft Graph v1.0:
Request:
https://graph.microsoft.com/v1.0/users?$search="displayName:Art Anderson"
Permissions:
Application and delegated. Refer to documentation.
Response:
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users",
"value": [
{
"displayName": "Art Anderson",
"mail": "artanderson@contoso.com",
"id": "fc4ccb5f-8046-4812-803f-6c344a5d1560"
}
Optionally, Presence for a user can be retrieved using the get presence API and the user ObjectId. Learn more on the Microsoft Graph v1.0 documentation.
Request:
https://graph.microsoft.com/v1.0/users/fc4ccb5f-8046-4812-803f-6c344a5d1560/presence
Permissions:
Delegated only. Application not supported. Refer to documentation.
Response:
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('fc4ccb5f-8046-4812-803f-6c344a5d1560')/presence/$entity",
"id": "fc4ccb5f-8046-4812-803f-6c344a5d1560",
"availability": "Offline",
"activity": "Offline"
Step 3: Add a Teams user to an existing Communication Services call controlled by Call Automation APIs
You need to complete the prerequisite step and have a web service app to control a Communication Services call. Using the callConnection object, add a participant to the call.
CallAutomationClient client = new CallAutomationClient('<Connection_String>');
AnswerCallResult answer = await client.AnswerCallAsync(incomingCallContext, new Uri('<Callback_URI>'));
await answer.Value.CallConnection.AddParticipantAsync(
new CallInvite(new MicrosoftTeamsUserIdentifier('<Teams_User_Guid>'))
{
SourceDisplayName = "Jack (Contoso Tech Support)"
});
CallAutomationClient client = new CallAutomationClientBuilder().connectionString("<resource_connection_string>").buildClient();
AnswerCallResult answer = client.answerCall(incomingCallContext, "<Callback_URI>"));
answer.getCallConnection().addParticipant(
new CallInvite(new MicrosoftTeamsUserIdentifier("<Teams_User_Guid>"))
.setSourceDisplayName("Jack (Contoso Tech Support)"));
const client = new CallAutomationClient("<resource_connection_string>");
const answer = await client.answerCall(incomingCallContext, "<Callback_URI>"));
answer.callConnection.addParticipant({
targetParticipant: { microsoftTeamsUserId: "<Teams_User_Guid>" },
sourceDisplayName: "Jack (Contoso Tech Support)"
});
call_automation_client = CallAutomationClient.from_connection_string("<resource_connection_string>")
answer = call_automation_client.answer_call(incoming_call_context = incoming_call_context, callback_url = "<Callback_URI>")
call_connection_client = call_automation_client.get_call_connection(answer.call_connection_id)
call_connection_client.add_participant(target_participant = CallInvite(
target = MicrosoftTeamsUserIdentifier(user_id="<USER_ID>"),
source_display_name = "Jack (Contoso Tech Support)"))
On the Microsoft Teams desktop client, Jack's call is sent to the Microsoft Teams user through an incoming call toast notification.
After the Microsoft Teams user accepts the call, the in-call experience for the Microsoft Teams user displays all the participants on the Microsoft Teams roster. Your application that is managing the call using Call Automation API remains hidden to Teams user on the call screen.
Step 4: Remove a Teams user from an existing Communication Services call controlled by Call Automation APIs
await answer.Value.CallConnection.RemoveParticipantAsync(new MicrosoftTeamsUserIdentifier('<Teams_User_Guid>'));
answer.getCallConnection().removeParticipant(new MicrosoftTeamsUserIdentifier("<Teams_User_Guid>"));
answer.callConnection.removeParticipant({ microsoftTeamsUserId: "<Teams_User_Guid>" });
call_connection_client.remove_participant(target_participant = MicrosoftTeamsUserIdentifier(user_id="<USER_ID>"))
Optional feature: Transfer to a Teams user from an existing Communication Services call controlled by Call Automation APIs
await answer.Value.CallConnection.TransferCallToParticipantAsync(new MicrosoftTeamsUserIdentifier('<Teams_User_Guid>'));
answer.getCallConnection().transferCallToParticipant(new MicrosoftTeamsUserIdentifier("<Teams_User_Guid>"));
answer.callConnection.transferCallToParticipant({ microsoftTeamsUserId: "<Teams_User_Guid>" });
call_connection_client.transfer_call_to_participant(target_participant = MicrosoftTeamsUserIdentifier(user_id = "<USER_ID>"))
Clean up resources
If you want to clean up and remove a Communication Services subscription, you can delete the resource or resource group. Deleting the resource group also deletes any other resources associated with it. Learn more about cleaning up resources.
Next steps
- Learn how to record your calls.
- Learn more about Call Automation and its features.
- Learn more about capabilities of Teams Interoperability support with Azure Communication Services Call Automation
- Learn about Play action to play audio in a call.
- Learn how to build a call workflow for a customer support scenario.