Here is the problem. You have the need to send a large number of Teams messages for your users and you cannot do that using the standard Power Automate Teams connector as it has a limit on the number of calls you can do per sec/min/hour/day/month.

You also cannot use the Graph API as you will end up blocked by the limits of that API as well.

Well, the Bot Framework REST API has a big limit and can be leveraged to support those scenarios. I’m documenting here a way to send high number of messages using an Azure Logic App, leveraging the Bot Framework REST API.

Here are the steps you need to follow…

Creating the Teams Application

  1. Open as admin
  2. Select apps and click New App.
  1. Name the bot and click Add.
  1. Copy the App ID on a notepad. You will need that number in the future.
  2. Fill the basic information for the bot providing at least Short name, App ID (Auto Generated), Short description, Long description, Developer or company name, Website (Valid HTTPS URL), Privacy policy url, Terms of use url. Once all of the above information is entered, click Save.
  3. Click Branding and provide appropriate icons for the user bot. Those will be the icons seen by users in Teams when interacting with the bot.
  4. Click App features and then click Bot.
  5. Make sure the Select an existing bot is selected and click on the Create a new bot link under the combo box.
  1. Click New Bot on the top of the page and provide a name for the bot. I’m using Broadcaster. Click Add.
  1. Once the bot is created, select Client Secrets on the left rail and then click “Add a client secret for your bot”.
  2. Copy and save the client secret generated. You will need that value to configure the calls to the bot.
  3. Click On the “< Bots” on the upper left corner and copy the Bot ID. Together with the secret that information will be required to configure the calls to the bot.
  4. Go back to the created Teams app in the Developer Portal, in App features, click Bot and then Select the created bot. Set the scope to Personal, select the “Only send notifications (one-way conversations” under What can your bot do? section, and then click Save.
  1. Now select App package under Publish and click Download app package. You will use the zip file downloaded to deploy the bot for your users.
  2. This solution will only work for users that have the bot installed.

Using Azure Logic Apps to Send Messages to the Bot

  1. Logon to Azure admin portal as administrator
  2. Type logic app on the search box and click Create.
  1. Give a name for your logic App, select the resource group where you will place the resource, select the region and plan type, then click Review+Create. Then click Create and wait until the deployment concludes.
  2. Click Go to resource when finished to go to the Logic Apps Designer.

We will be running the logic app manually and for that I’ll be setting a recurrence trigger each 12 months (logic apps don’t have a button trigger like power automate), but you can use whatever trigger you want to start the flow. You can even improve the solution to use information from other systems and trigger the flow accordingly to your requirements.

  1. Select the recurrence trigger and set it to 12 months of interval/frequency (in my case). Insert an Initialize variable action to create a variable to host the UPN of the user that you will send the proactive message. Remember, you can get that information from a system, from a parameter, you can loop from a list of users, from a database, etc. I’m just demonstrating how to send a proactive message to a specific user here.
  1. Insert another Initialize variable action to create a variable to host the Bot App ID. That is the value you collected when you created the zip file with the application. Paste the value on the action to initialize the variable with the value.
  2. Now we need to perform a few requests to the Graph API to get the chat ID of the conversation between the Bot we created and the user. That conversation is created when the bot application is deployed to users.

You may be thinking, well you will be doing a few Graph API calls for each user instead of just one to send the message. You will be facing issues with the Graph API limits sooner than when using the API to send proactive messages directly. Well no.

You need to perform those steps just one time for each user and store the chat ID for each one. Then you will need to recover that value (of chat ID) from the database in all subsequent calls. That way, the first time you send a message to a specific user, the calls to the graph API will obtain the chat ID and store to the database… future calls will get the value from there and send the message directly to the Bot Framework REST API.

For the sake of simplicity I’m not including the steps to store and recover that information from the database. If you need more info on that leave a comment and I’ll write another article showing how to improve the solution storing/recovering the chat ID from the database.

Here is how to get the information we need from the Graph API.

  1. Create an HTTP GET call to geth the teamsAppId for the bot with the following information:
Method: GET
URI:{variables('UserUPN')}/teamwork/installedApps?$expand=teamsApp&$filter=teamsApp/externalId eq '@{variables('BotAppManifestId')}'
Authentication type: Active Directory OAuth
Tenant: <The Id of your Tenant, you can get the value in Azure AD>
Client ID: <You saved this from the previous steps, it is the Id of you bot>
Credential Type: Secret
Secret: <The secret value you saved for the bot>

Note that my variables are named UserUPN and BotAppManifestId.

  1. Now we will create another request to get the chatId based on the teamsAppID. The chat ID is specific for each user and for each bot. Use the following information to create the HTTP action.
Method: GET
Authentication type: Active Directory OAuth
Tenant: <The Id of your Tenant, you can get the value in Azure AD>
Client ID: <You saved this from the previous steps, it is the Id of you bot>
Credential Type: Secret
Secret: <The secret value you saved for the bot>

We will be leveraging the Bot Framework REST API to send proactive messages to users via the bot we defined in the previous steps. The initial step to be able to use the endpoints from Bot Framework is to generate an access token which is then added to the Authorization header of each API request.

  1. Make sure you have the Bot ID and secret value you obtained when the bot was created in the previous steps.
  2. To request an access token, you need to make an HTTP request per the following details:
Method: POST
Headers: Content-Type application/x-www-form-urlencoded
Body: grant_type=client_credentials&client_id=[botId]&client_secret=[botSecret]&scope=
  1. Add a HTTP Action in your Power Automate flow to add the above details for generating the token. Replace the [botId] and [botSecret] with the values stored from the previous steps.
  1. The access token generated will be valid for 24 hours, if the token expires you will need to make another request. Since we are generating the token in each logic app execution, that will be needed only if you have your application running for more than that.

Ok. Time to send the proactive message. You will need to choose a specific service URL.

The service URL is the base URI for all Bot framework API requests. In Teams the service URL will change based on user’s region [EMEA, America, APAC, India etc]. We will be posting a message using the endpoint for the Americas.

Find below some URL’s based on regions:

RegionService URL
  1. Create another HTTP POST request to send a simple proactive message to our bot. Information needed is documented below.
Method: POST
Authorization: Bearer @{body('Get_Auth_Token')?['access_token']}
Body: {
    "locale": "en-EN",
    "type": "message",
    "text": "Hello!",


Disclaimer – The information contained in this blog post doesn’t represent the official Microsoft guidance or best practices. It is just the view of the author on current alternatives, implementations and workarounds for common issues and/or business needs. Please refer to official Microsoft documentation and evaluate carefully any steps, code or procedures documented herein. The author doesn’t offer any warranty. Use this information at your own risk.