Building a real-time integration between SAP S/4HANA and Microsoft Teams involves decisions about APIs, authentication, user mapping, message delivery, and error handling. This guide walks through the architecture layer by layer.
Architecture Overview
At a high level, the integration has three components:
- SAP S/4HANA — the source of approval workflow events
- Integration middleware (the "Bridge") — hosted on Azure, translates between SAP and Microsoft APIs
- Microsoft Teams — the destination, where approvers interact with Adaptive Cards
The Bridge is the key component. It handles event ingestion from SAP, user identity mapping, Adaptive Card rendering, message delivery via the Graph API, and decision write-back to SAP.
Step 1: Connecting to S/4HANA
The first decision is how to get approval events out of SAP. There are several options:
Option A: OData API (Recommended)
S/4HANA exposes workflow task lists via OData services. The key service is API_TASK_SPI_REPLICATION for task push or the /sap/opu/odata/sap/API_PURCHASEREQ_PROCESS_SRV for pull-based approaches.
For real-time delivery, the Bridge polls the SAP OData API on a configurable interval (default: 30 seconds). Each poll checks for new workflow items assigned to mapped approvers.
GET /sap/opu/odata/sap/API_PURCHASEREQ_PROCESS_SRV/A_PurchaseReqItem
?$filter=PurchaseRequisition eq '10024891'
&$select=PurchaseRequisition,PurchaseRequisitionItem,
Material,PurchaseRequisitionPrice
Option B: SAP Event Mesh (BTP)
For S/4HANA Cloud customers, SAP Event Mesh provides real-time event delivery. The Bridge subscribes to sap/s4/beh/purchaserequisition/v1/PurchaseRequisition/Released/* topics. This is the lowest-latency option but requires BTP entitlements.
Option C: RFC/BAPI
For on-premise systems without OData exposure, the Bridge can call BAPIs directly via RFC. This requires an SAP Cloud Connector or VPN tunnel to the Azure network.
Authentication
The Bridge authenticates to SAP using one of:
- Basic Auth — simplest, suitable for dev/test
- OAuth 2.0 + Client Credentials — recommended for S/4HANA Cloud
- X.509 Certificate — recommended for on-premise via Cloud Connector
Credentials are stored in Azure Key Vault, never in application configuration.
Step 2: User Identity Mapping
This is often the most underestimated step. SAP users and Microsoft 365 users are different identity systems. The Bridge needs to know that SAP user JMARTINEZ maps to Microsoft 365 user j.martinez@contoso.com.
Azure AD Sync (Preferred)
If your organization stores SAP user IDs as an extension attribute in Azure AD (e.g., extensionAttribute1), the Bridge can query the Microsoft Graph API to resolve mappings automatically:
GET /users?$filter=onPremisesExtensionAttributes/
extensionAttribute1 eq 'JMARTINEZ'
&$select=id,displayName,mail
CSV Upload
For organizations without consistent AD attributes, the Bridge provides a CSV upload interface:
sap_user,microsoft_email
JMARTINEZ,j.martinez@contoso.com
SCHEN,s.chen@contoso.com
MBROWN,m.brown@contoso.com
Handling Unmapped Users
When a workflow item targets an unmapped SAP user, the Bridge queues the item and sends an alert to the admin. The approval stays in SAP's Fiori Inbox as a fallback. Nothing is lost.
Step 3: Building the Adaptive Card
Microsoft Teams Adaptive Cards are JSON-defined UI elements. The Bridge generates cards dynamically based on the approval type and document data.
A simplified Adaptive Card for a purchase requisition approval:
{
"type": "AdaptiveCard",
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.5",
"body": [
{
"type": "TextBlock",
"text": "SAP Approval Request",
"weight": "Bolder",
"size": "Medium"
},
{
"type": "FactSet",
"facts": [
{ "title": "Type", "value": "Purchase Requisition" },
{ "title": "Document", "value": "PR-10024891" },
{ "title": "Requestor", "value": "J. Martinez" },
{ "title": "Amount", "value": "$12,450.00" }
]
}
],
"actions": [
{
"type": "Action.Execute",
"title": "✓ Approve",
"verb": "approve",
"data": { "docId": "10024891", "docType": "PR" }
},
{
"type": "Action.Execute",
"title": "✕ Reject",
"verb": "reject",
"data": { "docId": "10024891", "docType": "PR" }
}
]
}
The Bridge uses pre-built templates for each approval type. Line-item details are fetched from SAP and injected into the template at delivery time.
Step 4: Delivering to Teams
The Bridge delivers Adaptive Cards via the Microsoft Graph API using proactive messaging. This requires a Teams bot registration in Azure AD.
Bot Registration
- Register a bot in the Azure Bot Service
- Create a Teams app manifest referencing the bot
- Install the app for target users (admin consent or user self-install)
Proactive Messaging
The Bot Framework SDK sends cards to users via their conversation reference:
POST /v3/conversations/{conversationId}/activities
Content-Type: application/json
{
"type": "message",
"attachments": [{
"contentType": "application/vnd.microsoft.card.adaptive",
"content": { /* Adaptive Card JSON */ }
}]
}
Rate Limiting
The Microsoft Graph API has rate limits for bot messaging. The Bridge implements exponential backoff and message queuing to handle high-volume approval scenarios (e.g., month-end invoice batches).
Step 5: Handling the Decision
When the approver clicks approve or reject, Teams sends an invoke activity back to the Bridge. The Bridge:
- Validates the user's identity (ensures the responder matches the assigned approver)
- Writes the decision back to SAP via OData or BAPI
- Updates the Adaptive Card to show the decision (card becomes read-only)
- Logs the complete audit trail: timestamp, user, decision, SAP document
SAP Write-Back
POST /sap/opu/odata/sap/API_PURCHASEREQ_PROCESS_SRV
/A_PurReqRelease
Content-Type: application/json
{
"PurchaseRequisition": "10024891",
"PurReqReleaseCode": "01",
"PurReqRelIndicator": "X"
}
Step 6: Error Handling and Resilience
Production integrations need to handle failure gracefully:
- SAP unavailable: Queue decisions in Azure Service Bus. Retry with exponential backoff. Alert admin if queue grows.
- Teams unavailable: Queue outgoing cards. Approval stays in Fiori Inbox as fallback.
- User not found: Log warning, route approval to Fiori Inbox, alert admin.
- Duplicate delivery: Idempotency keys prevent the same approval from being sent twice.
- Card expired: If the approval was already processed in SAP (via Fiori), update the Teams card to show "Already processed."
Infrastructure Decisions
The Bridge runs on Azure with the following components:
- Azure App Service (or Container Apps) — hosts the Bridge application
- Azure Key Vault — stores SAP credentials and certificates
- Azure Service Bus — message queuing for resilience
- Azure Table Storage — audit log persistence
- Azure Application Insights — monitoring and alerting
Everything runs in a single Azure region, matching the customer's data residency requirements.
What We Learned Building This
After building SAP Approvals for Teams, here are the key takeaways:
- User mapping is 50% of the effort. Getting SAP users to Microsoft identities right is harder than the API integration itself.
- Adaptive Cards have limitations. They're powerful but not infinitely flexible. Designing cards that show enough detail without overwhelming the approver requires iteration.
- Fallback to Fiori is non-negotiable. Any integration that replaces Fiori Inbox must gracefully fall back to it. Approvals can never be lost.
- Audit trails matter more than features. Enterprise customers care about compliance first, convenience second.
- Polling beats eventing for most customers. Event Mesh is technically superior, but polling OData is simpler and works for both cloud and on-premise.
Skip the Build — Use the Product
Everything described above is what SAP Approvals for Teams handles out of the box. We built this so you don't have to.
If you're considering building an SAP-to-Teams integration from scratch, book a demo first. It might save you six months.