Skip to content

Teams technical integration

Ways to connect Teams and Tallyfy

Microsoft Teams integration relies on three main tools - Graph API, Adaptive Cards, and Power Automate. Pick whichever fits your setup.

The easiest route uses Power Automate as middleware between Teams and Tallyfy:

Trigger: When a message is posted to a channel
Action: HTTP POST to Tallyfy API
Action: Post Adaptive Card to Teams with workflow link

Adaptive Cards for task notifications

You can send rich, interactive cards to Teams channels whenever Tallyfy tasks get assigned:

{
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.4",
"body": [
{
"type": "TextBlock",
"text": "New Task Assigned",
"weight": "Bolder",
"size": "Medium"
},
{
"type": "FactSet",
"facts": [
{ "title": "Task:", "value": "${taskTitle}" },
{ "title": "Process:", "value": "${processName}" },
{ "title": "Due:", "value": "${dueDate}" },
{ "title": "Assigned by:", "value": "${assignedBy}" }
]
},
{
"type": "TextBlock",
"text": "${taskDescription}",
"wrap": true
}
],
"actions": [
{
"type": "Action.OpenUrl",
"title": "Open in Tallyfy",
"url": "${taskUrl}"
},
{
"type": "Action.Submit",
"title": "Mark Complete",
"data": {
"action": "complete",
"taskId": "${taskId}"
}
}
]
}

Microsoft Graph API integration

Post Tallyfy workflow updates to Teams channels through the Graph API:

const { Client } = require('@microsoft/microsoft-graph-client');
const postToTeamsChannel = async (channelId, teamId, message, card) => {
const client = Client.init({
authProvider: (done) => done(null, accessToken)
});
await client
.api(`/teams/${teamId}/channels/${channelId}/messages`)
.post({
body: {
contentType: 'html',
content: message
},
attachments: [{
contentType: 'application/vnd.microsoft.card.adaptive',
content: JSON.stringify(card)
}]
});
};
// Example: Post when Tallyfy workflow completes
const notifyWorkflowComplete = async (workflow) => {
const card = {
type: 'AdaptiveCard',
version: '1.4',
body: [{
type: 'TextBlock',
text: `✅ Workflow Complete: ${workflow.name}`,
weight: 'Bolder'
}, {
type: 'FactSet',
facts: [
{ title: 'Completed by:', value: workflow.completedBy },
{ title: 'Duration:', value: workflow.duration },
{ title: 'Tasks:', value: `${workflow.completedTasks}/${workflow.totalTasks}` }
]
}]
};
await postToTeamsChannel(channelId, teamId, 'Workflow completed', card);
};

Incoming webhooks

For simpler setups, Teams incoming webhooks work well:

const postToTeamsWebhook = async (webhookUrl, message) => {
await fetch(webhookUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
'@type': 'MessageCard',
'@context': 'http://schema.org/extensions',
summary: message.title,
themeColor: '0076D7',
title: message.title,
sections: [{
activityTitle: message.subtitle,
facts: message.facts,
text: message.body
}],
potentialAction: [{
'@type': 'OpenUri',
name: 'View in Tallyfy',
targets: [{ os: 'default', uri: message.url }]
}]
})
});
};

Bot Framework integration

Need richer interaction? Build a custom Teams bot:

const { TeamsActivityHandler, CardFactory } = require('botbuilder');
class TallyfyBot extends TeamsActivityHandler {
constructor() {
super();
this.onMessage(async (context, next) => {
const text = context.activity.text.toLowerCase();
if (text.includes('launch workflow')) {
const workflowName = text.replace('launch workflow', '').trim();
const workflow = await launchTallyfyWorkflow(workflowName);
await context.sendActivity({
attachments: [CardFactory.adaptiveCard(createWorkflowCard(workflow))]
});
}
if (text.includes('my tasks')) {
const tasks = await getTallyfyTasks(context.activity.from.aadObjectId);
await context.sendActivity({
attachments: [CardFactory.adaptiveCard(createTaskListCard(tasks))]
});
}
await next();
});
}
async handleTeamsTaskSubmit(context, taskModuleRequest) {
const { action, taskId } = taskModuleRequest.data;
if (action === 'complete') {
await completeTallyfyTask(taskId);
return { task: { type: 'message', value: 'Task marked complete!' }};
}
}
}

Authentication setup

Teams integration uses Azure AD OAuth 2.01. Here’s the setup in Azure portal:

  1. Register your app in Azure AD
  2. Add Microsoft Graph API permissions
  3. Set redirect URIs for your integration
  4. Use client credentials flow for server-to-server calls
const { ConfidentialClientApplication } = require('@azure/msal-node');
const msalConfig = {
auth: {
clientId: process.env.AZURE_CLIENT_ID,
clientSecret: process.env.AZURE_CLIENT_SECRET,
authority: `https://login.microsoftonline.com/${process.env.AZURE_TENANT_ID}`
}
};
const cca = new ConfidentialClientApplication(msalConfig);
const getGraphToken = async () => {
const result = await cca.acquireTokenByClientCredential({
scopes: ['https://graph.microsoft.com/.default']
});
return result.accessToken;
};

iPaaS alternatives

If you don’t want to write custom code:

  • Power Automate - Microsoft’s native automation platform
  • Zapier - pre-built Teams triggers and actions
  • Workato - enterprise automation with a Teams connector
  • Make - visual workflow builder with Teams integration

Vendors > Microsoft Teams

Microsoft Teams handles communication but lacks process management capabilities like request tracking and accountability so Tallyfy fills this gap by converting Teams messages into structured workflows with assigned owners and deadlines through Power Automate or custom integrations.

Middleware > Power Automate

Microsoft Power Automate serves as a no-code bridge between Tallyfy and your other business systems—including Office 365 and SharePoint and Dynamics—using a Premium connector with 13 actions and OAuth 2.0 authentication to automate data syncing and trigger Tallyfy processes from external events like emails or CRM updates.

Pro > Integrations

Tallyfy offers twelve distinct ways to connect with your existing business software — ranging from a full REST API and webhooks for developers to no-code middleware platforms like Zapier and Make for non-technical users — along with email integration and chat tools like Slack and upcoming BYO AI capabilities so every team can automate data sharing and eliminate manual copy-pasting between systems regardless of technical skill level.

Footnotes

  1. Industry-standard protocol for secure delegated authorization without sharing passwords