ml-connector
Microsoft Dynamics 365 F&OJira

Microsoft Dynamics 365 F&O and Jira integration

Microsoft Dynamics 365 F&O runs finance, procurement, and supply chain. Jira tracks the work that resolves problems. Connecting the two turns Dynamics events such as a posted vendor invoice, a confirmed purchase order, or a workflow approval into Jira issues, so the people who handle exceptions see them in the same board they already use. When the Jira issue is worked and its status changes, ml-connector reads that back to advance the matching Dynamics workflow or record the outcome. Jira holds no financial data, so no ledger or vendor records are copied into it; only the identifiers and context needed to act.

How Microsoft Dynamics 365 F&O works

Microsoft Dynamics 365 F&O exposes vendors, vendor invoices, purchase orders, customers, main accounts, and posted journal entries as OData v4 entities at a tenant-specific environment host under the /data/ root. It authenticates with OAuth 2.0 client credentials through Microsoft Entra ID, with a bearer token scoped to that environment host that expires in about an hour. For push, the Business Events framework dispatches a lightweight JSON payload to an HTTPS endpoint when an action such as a posted invoice or confirmed purchase order occurs; the payload carries a ControlNumber for dedup and identifiers, not the full record, so a follow-up OData read is needed for detail.

How Jira works

Jira is Atlassian's project and issue tracker, not a finance system, so it has no vendor, invoice, purchase order, GL account, or payment objects. It exposes issues, projects, users, comments, and worklogs through the Cloud Platform REST API v3, using JSON over standard HTTP methods. Authentication is OAuth 2.0 three-legged with a cloudId resolved from the accessible-resources endpoint, or basic auth with an account email and API token; client credentials are not supported. Jira pushes issue, comment, and workflow events through outbound webhooks signed with HMAC-SHA256 in an X-Hub-Signature header, and REST-registered webhooks expire after 30 days.

What moves between them

The primary flow runs from Microsoft Dynamics 365 F&O into Jira. When a Dynamics business event fires, such as a vendor invoice posted, a purchase order confirmed, or a workflow document rejected, ml-connector creates a Jira issue in the mapped project and issue type with the Dynamics document number, vendor or customer, amount, and a link back to the record. The return flow runs from Jira into Dynamics: when the issue is transitioned or commented, ml-connector reads that change and advances the corresponding Dynamics workflow step or writes the resolution. No financial masters move into Jira, since it has no place to hold them.

How ml-connector handles it

ml-connector stores both credential sets encrypted. For Dynamics it requests a client credentials token from Entra ID scoped to the environment host and refreshes it before the hourly expiry, and it accepts that host as a per-customer field because there is no shared base URL. For Jira it runs the three-legged OAuth exchange, resolves the cloudId from accessible-resources, and rotates the refresh token on each use. Dynamics business event payloads are stubs, so the handler takes the ControlNumber and identifiers and calls back to OData for the full record before building the issue. Jira has no idempotency key for issue creation, so ml-connector writes the Dynamics document key into a custom field and JQL-searches it before creating, which stops a re-delivered event from opening a duplicate; the Dynamics ControlNumber and a BullMQ jobId guard the same boundary. Custom field IDs differ per Jira site, so they are discovered at connect time, never hardcoded. Inbound Jira webhooks are verified against the X-Hub-Signature HMAC before processing and a refresh job re-arms them before the 30-day expiry. Both sides return HTTP 429 under load, so ml-connector honors Retry-After with backoff and jitter, and every record carries a full audit trail and can be replayed if a downstream call fails.

A real-world example

A mid-sized manufacturer with about 600 staff runs Microsoft Dynamics 365 F&O for procurement and accounts payable, and its operations and finance teams live in Jira. Before the integration, a posted vendor invoice that failed three-way match or a purchase order stuck in approval was caught only when someone happened to open the Dynamics workflow queue, so exceptions sat for days and the AP team chased status over email. With the two connected, each Dynamics invoice or purchase order exception opens a Jira issue in the AP project tagged with the vendor and document number, and when the assignee resolves and transitions it, the matching Dynamics workflow step advances. Exceptions are now visible the moment they occur, ownership is clear, and the email chasing is gone.

What you can do

  • Create Jira issues from Microsoft Dynamics 365 F&O business events such as posted invoices, confirmed purchase orders, and rejected workflow documents.
  • Read Jira issue transitions and comments back to advance the matching Dynamics workflow or record the outcome.
  • Bridge Dynamics Entra ID client credentials and Jira three-legged OAuth with its resolved cloudId.
  • Write the Dynamics document key into a Jira custom field and JQL-check it so a re-read event never opens a duplicate issue.
  • Verify inbound Jira webhooks by HMAC-SHA256, refresh them before the 30-day expiry, and keep a full audit trail on every record.

Questions

Which direction does data move between Microsoft Dynamics 365 F&O and Jira?
The primary flow is Dynamics into Jira, where business events become tracked issues carrying the document number, vendor, and amount. The return flow is Jira into Dynamics, where an issue transition or comment advances the matching workflow step. Jira holds no financial records, so vendor, invoice, and GL masters are never copied into it.
Why are Dynamics business events not enough on their own to build a Jira issue?
A Dynamics business event payload is a lightweight stub that carries a ControlNumber and key identifiers, not the full record. ml-connector takes those identifiers and makes a follow-up OData call to retrieve the vendor, amount, and document detail before it creates the Jira issue. The ControlNumber also serves as a dedup key so a re-delivered event is ignored.
How does the integration stop duplicate Jira issues when an event repeats?
Jira has no idempotency key for issue creation, so ml-connector writes the Dynamics document key into a Jira custom field and JQL-searches that field before creating anything. If a matching issue already exists it updates rather than duplicates. The Dynamics ControlNumber and a BullMQ jobId guard the same boundary, since custom field IDs are discovered per site at connect time and never hardcoded.

Related integrations

Connect Microsoft Dynamics 365 F&O and Jira

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

Get started