Microsoft Dynamics 365 F&O and Asana integration
Microsoft Dynamics 365 F&O runs procurement and finance. Asana runs the work and approval tracking around them. Asana has no invoice or purchase order objects of its own, so this connection treats Asana tasks as the place where procurement work is tracked, with the financial detail carried in custom fields. When a purchase order is confirmed or a vendor invoice is posted in Dynamics, ml-connector creates an Asana task that carries the document number, vendor, and amount, and when that task is completed it can write status back to Dynamics. The general ledger and the invoices themselves stay in Dynamics where they belong.
What moves between them
The main flow runs from Microsoft Dynamics 365 F&O into Asana. When a purchase order is confirmed or a vendor invoice is posted or approved, the business event triggers ml-connector to read the full record from OData and create or update an Asana task whose custom fields hold the PO or invoice number, vendor account, amount, and due date. The task lives in a project that maps to the procurement workflow or department. Status flows back the other way: when an Asana task is completed, or its approval custom field changes, the webhook prompts ml-connector to update the matching Dynamics record. Users are read from Asana into Dynamics on a schedule so assignees resolve to known people. Invoices and ledger entries are never written into Asana, since Asana has no such objects.
How ml-connector handles it
ml-connector stores both credential sets encrypted. On the Dynamics side it requests an Entra ID client-credentials token scoped to the customer environment host and refreshes it on expiry, and it accepts the tenant-specific operations.dynamics.com host as a credential since there is no shared base URL. It subscribes a Business Events HTTPS endpoint for purchase order and vendor invoice events; because those payloads are stubs carrying a ControlNumber rather than full data, the handler calls back to OData to fetch the record, and it dedupes on the ControlNumber so a redelivered event does not create a second task. On the Asana side it completes the webhook handshake by echoing the X-Hook-Secret, then verifies the HMAC-SHA256 signature on every event POST, and it always passes opt_fields so task responses are not sparse. Custom field GIDs are resolved per workspace and mapped to Dynamics document keys, since field names can be renamed. Asana has no idempotency key, so the stored task GID and a BullMQ jobId prevent duplicate creates. Asana webhooks self-delete after 24 hours of failed delivery or missed heartbeats, so ml-connector re-verifies the subscription and re-registers when needed. Dynamics returns HTTP 429 with a Retry-After header under service protection, and Asana does the same per token, so both sides back off and retry, with a full audit trail and replay on every record.
A real-world example
A mid-sized manufacturer of roughly 400 employees runs Microsoft Dynamics 365 F&O for procurement and finance, and the purchasing team already lives in Asana for day-to-day work. Before the integration, when a purchase order was confirmed or a vendor invoice landed in Dynamics, a buyer manually opened an Asana task to chase the receipt or the approval, copying the PO number and amount by hand, and the two systems drifted apart whenever someone forgot. With the systems connected, each confirmed PO and posted invoice creates an Asana task automatically with the document number and amount in custom fields, the right project, and the right assignee. When the buyer completes the task, the status is written back to Dynamics. The manual task creation is gone and nothing falls through the cracks.
What you can do
- Create or update an Asana task when a Dynamics purchase order is confirmed or a vendor invoice is posted, carrying the document number, vendor, and amount in custom fields.
- Write Asana task completion and approval custom field changes back into the matching Microsoft Dynamics 365 F&O record.
- Read the full Dynamics record from OData after each lightweight business event, deduplicating on the ControlNumber.
- Bridge Entra ID OAuth2 client credentials on the Dynamics side and the Asana token, resolving custom field GIDs per workspace.
- Verify Asana HMAC-SHA256 webhooks, re-register them after auto-deletion, and retry both sides on HTTP 429 with a full audit trail.
Questions
- Can Asana store the actual invoices and purchase orders from Dynamics?
- No. Asana has no native invoice, purchase order, payment, or general ledger objects. ml-connector represents each Dynamics document as an Asana task and carries the document number, vendor, and amount in workspace-scoped custom fields. The invoices and the ledger stay in Microsoft Dynamics 365 F&O, which remains the source of truth.
- How does the integration know when something happens in Dynamics?
- Dynamics 365 F&O pushes outbound events through its Business Events framework for actions such as purchase order confirmed and vendor invoice posted. Those payloads carry only identifiers like the ControlNumber, not full record data, so ml-connector calls back to the OData service to fetch the complete record before creating an Asana task. It deduplicates on the ControlNumber because delivery order is not guaranteed and an event can arrive more than once.
- What happens if an Asana webhook stops working?
- Asana automatically deletes a webhook after 24 consecutive hours of failed delivery or missed heartbeats. ml-connector periodically checks that its webhook still exists for the workspace target URL and re-registers it when needed, completing the X-Hook-Secret handshake again. Every event is HMAC-SHA256 verified before it is processed, and any failed write back to Dynamics is retried and recorded in the audit trail.
Related integrations
More Microsoft Dynamics 365 F&O integrations
Other systems that connect to Asana
Connect Microsoft Dynamics 365 F&O and Asana
Free to use. Add your credentials, ping your real systems, and see if we fit.
Get started