ml-connector
Sage 100Procore

Sage 100 and Procore integration

Sage 100 runs construction project accounting, invoicing, and inventory. Procore runs the project workflow, from requisitions through budget tracking and cost allocation. When Sage 100 and Procore are connected, vendors and cost codes stay in sync, purchase orders and requisitions flow to where they are needed, and change orders and payment applications post into the general ledger without manual re-entry. ml-connector bridges the on-premises Sage 100 architecture with Procore's cloud API, handling authentication on both sides and moving data on a schedule you control.

How Sage 100 works

Sage 100 is an on-premises Windows-based ERP with no native REST API or cloud interface. It exposes a limited set of sales orders and customer data through SOAP Web Services (eBusiness Web Services), but accounts payable, general ledger, purchase orders, and vendor management require the BOI COM layer, which must be wrapped by a local Windows agent on the customer server. Authentication is username and password per SOAP call with no tokens or OAuth. The system uses polling only - no webhooks or push events - and requires polling on DateLastUpdated or DateCreated fields. Data is locked by company code (a three-character identifier per customer), and GL accounts use a multi-segment format that varies by customer configuration. The system has concurrent write limits due to COM record-locking, requiring exponential backoff on write conflicts.

How Procore works

Procore is a cloud-based construction management platform that exposes vendors, purchase orders, requisitions, cost codes, budget line items, and payment applications through REST APIs. All calls use OAuth 2.0 client credentials via a Developer Managed Service Account, with tokens expiring every 1.5 hours. Access is controlled by tool permissions on the DMSA app in the Developer Portal, with no additional OAuth scopes. The platform supports webhooks for real-time push of create, update, and delete events across commitments, requisitions, direct costs, and vendors. Webhooks must be publicly accessible HTTPS endpoints that return a 2xx response within five seconds. Most endpoints require a company_id path parameter, and project-scoped endpoints also require project_id.

What moves between them

The primary flow is from Procore into Sage 100. Vendors from Procore are synced into Sage 100 AP as new suppliers, and purchase orders and requisitions from Procore projects are posted into Sage 100 AP and GL. Change orders and payment applications in Procore become journal entries or manual checks in Sage 100. Cost codes in Procore are mapped to Sage 100 GL account segments during setup. Reference data flows bidirectionally: vendor master data and GL accounts from Sage 100 validate cost codes and budget line items in Procore on a daily refresh cycle. Requisitions are read from Procore and written to Sage 100 on a three-times-daily schedule.

How ml-connector handles it

ml-connector stores Sage 100 agent credentials encrypted and connects to the local agent using the supplied agent endpoint and authentication method (API key or mTLS). It polls the agent for new vendors, POs, and GL changes on a schedule, respecting the Windows COM record-locking limits by backing off and retrying on lock conflicts. For Procore, ml-connector authenticates once per token expiry (every 90 minutes) using OAuth 2.0 client credentials and stores the bearer token encrypted. It can receive Procore webhooks in real-time, but also polls the REST API as a fallback for reliability. Cost codes in Procore are mapped to Sage 100 GL account segments at setup time; during sync, the integration validates that every requisition and purchase order references a valid GL account and vendor in Sage 100 before posting. Change order amounts and payment applications are transformed into Sage 100 journal entry format with proper GL coding and company code. Every record carries a full audit trail showing the source record ID, the target posting, and any validation errors, so failed records can be reviewed and replayed when corrected.

A real-world example

A regional construction company operates a fleet of residential and commercial projects tracked in Procore. Their finance office runs Sage 100 for all AP, GL, and accounting. Before integration, requisitions and change orders from project managers arrived as PDF exports or emails, and the accounting team manually entered each one into Sage 100 AP and allocated costs to the correct GL accounts and job codes - a process that took two to three days per pay cycle and introduced data-entry errors. Vendor adds in Procore were not reflected in Sage 100, causing invoices to post under wrong vendor codes. With Sage 100 and Procore connected, new vendors sync automatically, requisitions and purchase orders flow into AP on the day they are approved, change orders post as GL entries with correct cost allocations, and the accounting team can close the books the day after project documents are finalized.

What you can do

  • Sync vendors, purchase orders, and requisitions from Procore into Sage 100 AP and GL with full cost coding.
  • Validate every requisition and purchase order against Sage 100 vendors and GL account segments before posting.
  • Receive Procore change order and payment application events in real-time and post them as journal entries in Sage 100.
  • Handle Sage 100 on-premises agent authentication and the local Windows COM record-locking retry loops transparently.
  • Exchange vendor master data and GL accounts between Sage 100 and Procore daily to keep cost codes and budget allocations valid.

Questions

What is the local agent and why does Sage 100 need it?
Sage 100's eBusiness Web Services SOAP interface exposes only sales orders and customers. To access accounts payable, general ledger, purchase orders, and vendor data, the integration must call the BOI COM layer, which runs only on a Windows machine inside the customer network. The local agent is a lightweight Windows service that wraps these COM calls and exposes them via HTTP or mTLS to ml-connector, which runs it as a background service on or near the Sage 100 server.
How does ml-connector handle Sage 100's lack of webhooks and COM write-locking?
Sage 100 has no webhooks or event stream, so ml-connector polls the agent for new records on a schedule - typically AP invoices and purchase orders every 15 minutes, vendors hourly, and GL accounts daily. When writing to Sage 100, the COM layer enforces record-locking: ml-connector detects lock conflicts and backs off with exponential jitter before retrying, ensuring high-frequency operations do not overwhelm the system.
How are Procore cost codes and budget line items mapped to Sage 100 GL accounts?
Cost codes in Procore map to Sage 100 GL account segments during initial setup - for example, a Procore cost code for 'Labor - Building 2' maps to a Sage 100 GL segment like '5100-04-00'. During sync, every requisition, purchase order, and change order from Procore is validated against the Sage 100 GL accounts that exist under the mapped segments, ensuring journal entries post to real accounts in the general ledger.

Related integrations

Connect Sage 100 and Procore

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

Get started