ml-connector
Sage 100Asana

Sage 100 and Asana integration

Sage 100 runs accounting, purchasing, and inventory on the customer's own server. Asana runs the requests, approvals, and project work that lead up to a purchase. Connecting the two means a purchasing request that is approved in Asana becomes a real purchase order in Sage 100 without anyone re-keying it. The purchase order number, vendor, and posting status then flow back to the Asana task so the requester can see where it stands. ml-connector handles the very different systems on each side and moves the data on the cadence you set.

How Sage 100 works

Sage 100 is on-premises and has no cloud API. Full access to vendors, purchase orders, AP invoices, and GL accounts comes through the Business Object Interface, a COM layer that runs on the Sage 100 server and is reached through a local agent that exposes HTTPS. A separate SOAP web service covers only sales orders and customers. Authentication is a Sage 100 username and password plus a three-character company code passed on every call, or an API key to the local agent. Sage 100 has no webhooks, so records are read by polling on the DateLastUpdated fields. GL accounts are segmented strings such as 1000-01-00, and AP work requires the APDivisionNo prefix.

How Asana works

Asana is a cloud product with a JSON REST API at app.asana.com over standard HTTP verbs. A connector authenticates with a long-lived Personal Access Token or an OAuth 2.0 bearer token, both sent as Authorization: Bearer. The core objects are tasks, projects, users, and custom fields; Asana has no native invoice, purchase order, or GL account objects, so financial data such as a cost code or vendor is carried in customer-defined custom fields resolved by GID. Asana pushes change events by webhook, signed with HMAC-SHA256 keyed on the secret from the registration handshake, and list reads use offset pagination up to 100 records per page.

What moves between them

The main flow runs from Asana into Sage 100. When a purchasing task reaches an approved state in Asana, ml-connector reads its custom fields for the vendor, cost code, and line detail and creates a purchase order in Sage 100 through the local agent, against a valid vendor and segmented GL account. The reverse flow writes the new Sage 100 purchase order number, vendor name, and posting status back into the Asana task's custom fields so the requester sees progress. The Asana user roster is read so requesters and approvers can be matched to Sage 100 records. Asana task webhooks trigger the work in near real time, and a scheduled poll of Sage 100 picks up status changes since Sage 100 cannot push.

How ml-connector handles it

ml-connector stores both credential sets encrypted. For Asana it sends the bearer token on every call and requests opt_fields so custom fields come back populated rather than as sparse objects. For Sage 100 it calls the customer's local Windows agent over HTTPS, which wraps the Business Object Interface, and it passes the company code and APDivisionNo on every purchase order write. Because Asana custom field GIDs are workspace-scoped and can be renamed, fields are mapped by GID, not by name. Asana provides no idempotency key, so the connector stores the Asana task GID and the Sage 100 purchase order key and skips re-creating one that already exists. The Asana webhook is verified by recomputing the HMAC-SHA256 signature, and because Asana silently deletes a webhook after 24 hours of failed delivery the connector periodically checks that it still exists and re-registers it. Sage 100 record-locking errors are retried with backoff, and every record carries a full audit trail and can be replayed.

A real-world example

A regional construction firm of about 200 staff runs Sage 100 on a server in its head office for purchasing and accounts payable, and runs project work and field requests in Asana. Before the integration, a project manager filled out an Asana task to request materials, an approver checked a box, and then someone in accounting re-typed the whole thing into Sage 100 as a purchase order, often days later and sometimes against the wrong cost code. With Sage 100 and Asana connected, an approved Asana request becomes a Sage 100 purchase order automatically, mapped to the right vendor and job cost account, and the PO number flows back to the task. Approvers see the order is placed, and accounting stops re-keying requests by hand.

What you can do

  • Turn an approved Asana purchasing task into a Sage 100 purchase order through the on-prem local agent.
  • Write the Sage 100 purchase order number, vendor, and posting status back to the Asana task's custom fields.
  • Map Asana custom fields to Sage 100 vendors, cost codes, and segmented GL accounts by GID.
  • Bridge Asana bearer-token auth to Sage 100 username, company code, and local agent API key.
  • Trigger on Asana task webhooks, poll Sage 100 for status, and keep a full audit trail with replay.

Questions

Can Asana create purchase orders or invoices in Sage 100 directly?
Asana has no native purchase order, invoice, or GL account objects, so the request lives as a task with custom fields. ml-connector reads an approved task's custom fields and creates the actual purchase order in Sage 100 through the local agent, which reaches the Business Object Interface. The financial record is created and validated in Sage 100, not in Asana.
Why does Sage 100 need a local agent for this integration?
Sage 100 is on-premises and has no cloud API, and full access to vendors and purchase orders is through the Business Object Interface, a COM layer that only runs on the Sage 100 server. A lightweight Windows agent on that server exposes those operations over HTTPS so ml-connector can reach them. Without the agent only sales orders and customers are reachable through the SOAP service.
How are updates kept current when Sage 100 cannot push events?
Asana sends a signed webhook when a task changes, so requests move into Sage 100 in near real time. Sage 100 has no webhooks, so ml-connector polls it on a schedule using the DateLastUpdated fields to pick up posting status. Because Asana deletes a webhook after 24 hours of failed delivery, the connector checks the webhook still exists and re-registers it when needed.

Related integrations

Connect Sage 100 and Asana

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

Get started