ml-connector
XeroMicrosoft Teams

Xero and Microsoft Teams integration

Xero runs your invoicing, purchase orders, and general ledger. Microsoft Teams is where your team communicates. Connecting them keeps your finance team informed without leaving Teams. Invoices posted, payments received, purchase orders approved, and manual journal entries all flow to a designated channel as they happen, so the finance team sees transactions in context with their work chat rather than logging into Xero separately. ml-connector handles the credential exchange between the two cloud services and turns accounting events into readable formatted messages.

How Xero works

Xero exposes invoices, purchase orders, contacts, payments, accounts, tracking categories, manual journals, and bank transactions through the Xero Accounting API, a REST service returning JSON or XML at https://api.xero.com/api.xro/2.0/. All requests require OAuth2 (user consent) and the Xero-tenant-id header to target the specific organization. Access tokens expire after 30 minutes; refresh tokens last 60 days. Xero publishes webhooks for invoices, purchase orders, payments, and manual journals on CREATE and UPDATE events. Webhook payloads contain metadata only, requiring a follow-up GET call for the full record. Xero also supports delta sync via If-Modified-Since headers for polling. Concurrent call limits are 5 per tenant, 60 per minute per tenant, and 5000 per day; app-wide limits are 10000 per minute. Invoices and bills are differentiated by a Type field on the same endpoint.

How Microsoft Teams works

Microsoft Teams is accessed via the Microsoft Graph REST API at https://graph.microsoft.com/v1.0/, secured with OAuth2 through Microsoft Entra ID. Authentication uses client credentials flow with tenant_id, client_id, and client_secret. Teams is a communications platform without native accounting objects; integration focuses on routing messages to channels and teams. Microsoft Graph change notifications (webhooks) register via /subscriptions and expire after 3 days, requiring renewal. Webhook validation requires returning a validationToken within 10 seconds. Rich notifications can use encrypted payloads with a customer-supplied public key. Teams has a per-tenant limit of 10,000 active subscriptions. All application permissions require Azure AD admin consent. Teams webhooks validate via clientState match, not HMAC signature.

What moves between them

Financial events flow from Xero into Microsoft Teams channels. Xero webhooks trigger on new invoices (Type ACCREC), purchase orders, payments, and manual journals. ml-connector translates each event into a readable Teams message card showing the contact or vendor name, amount, date, and relevant tracking categories. Messages post to a configurable channel in real time. The flow is one-way: Teams is notification only, not a source of accounting data. If Xero webhooks are unavailable, ml-connector falls back to polling Xero's API on a schedule tied to the business workflow (e.g., every 15 minutes, or more frequently during day-end close).

How ml-connector handles it

ml-connector holds both OAuth2 credential sets encrypted. On startup, it refreshes the Xero access token (which expires every 30 minutes) and the Microsoft Entra ID token using the client credentials. When a Xero webhook arrives, ml-connector validates the webhook signature against the signing key registered in the Xero Developer portal (separate from the OAuth client secret). It then fetches the full record from Xero using the Xero-tenant-id header. The transaction details (invoice number, amount, contact name, tracking category) are formatted as a Teams adaptive card and posted to the registered channel. If the webhook endpoint returns a non-200 status, Xero retries; ml-connector is idempotent per webhook event ID so duplicate posts do not occur. Rate limits on both sides are respected: if Xero returns 429, ml-connector backs off before retrying; Teams rate limits are rarely hit at message-send volumes for typical workflows. Deleted records in Xero are not returned by default, so soft deletions may require separate polling logic if audit trail of deletions is needed. All messages are logged with full audit trail including timestamp, Xero event ID, and Teams message ID for compliance and troubleshooting.

A real-world example

A mid-sized professional services firm uses Xero for invoicing clients and tracking project expenses, and uses Microsoft Teams for day-to-day team communication. Before the integration, the finance team logged into Xero multiple times daily to check invoice status, payment receipts, and PO approvals, then manually typed summaries into a Finance channel to inform the rest of the team. With Xero and Microsoft Teams connected, every invoice posted, payment received, and purchase order created automatically appears in the Finance channel as a formatted card with amount, vendor, and project code. The team stays aware of cash flow and vendor commitments without context-switching out of Teams, and the finance manager can focus on reconciliation rather than notification chasing.

What you can do

  • Post new Xero invoices, purchase orders, and payments to Microsoft Teams channels in real time as they are created or updated.
  • Format transaction details including contact or vendor name, amount, tracking categories, and dates into readable Teams adaptive cards.
  • Validate Xero webhook signatures against the signing key from the Xero Developer portal and handle the OAuth2 credential exchange between Xero and Microsoft Entra ID.
  • Fall back to polling Xero on a configurable schedule if webhooks are unavailable or for delta sync via If-Modified-Since headers.
  • Maintain a full audit trail of every message posted, including Xero event ID, Teams message ID, and timestamp for compliance and troubleshooting.

Questions

How does the integration handle the 30-minute expiry of Xero access tokens?
ml-connector automatically refreshes the Xero access token before it expires using the long-lived refresh token. The refresh token is stored encrypted and remains valid for 60 days. Token refresh happens on startup and before each Xero API call, so expiry does not cause notification delays.
What happens if a Xero webhook signature validation fails?
ml-connector rejects the message and does not post to Teams. The webhook validation uses the signing key registered in the Xero Developer portal app settings, which is separate from the OAuth client secret. A rejected webhook is logged for audit and can be investigated without propagating incomplete or spoofed data to the team channel.
Can deleted records or manual corrections in Xero be reflected in Teams messages?
Xero does not return deleted records by default, so deletions may not trigger a notification. Manual corrections appear as UPDATE webhook events and post a new Teams message reflecting the corrected values. For full audit trail of corrections, ml-connector logs all versions in its database so the finance team can review change history outside Teams.

Related integrations

Connect Xero and Microsoft Teams

Free to use. Add your credentials, ping your real systems, and see if we fit.

Get started