ml-connector
Oracle NetSuiteProcore

Oracle NetSuite and Procore integration

Oracle NetSuite runs your enterprise financial and supply chain operations. Procore tracks project costs, commitments, and change orders on site. Connecting the two keeps your project budgets in agreement with your ledger. Vendors and purchase orders created in NetSuite flow into Procore, and cost actuals from the field feed back into NetSuite GL accounts without re-entry. ml-connector handles the different auth schemes on each side and moves the records on a schedule you control.

How Oracle NetSuite works

Oracle NetSuite exposes vendors, purchase orders, vendor bills, invoices, GL accounts, cost codes, departments, and locations through REST APIs secured by OAuth2 Client Credentials or token-based authentication. The REST endpoint base is https://<accountId>.suitetalk.api.netsuite.com/services/rest, and bulk reads use SuiteQL queries. NetSuite supports Event Subscriptions for real-time webhooks on supported record types, but webhook signatures are not HMAC-based and instead rely on IP allowlist plus a shared secret. OAuth tokens expire in 60 minutes with no refresh token in the M2M flow, so ml-connector refreshes on every call or caches in Redis.

How Procore works

Procore exposes vendors, purchase order contracts, requisitions, payment applications, budget line items, cost codes, change orders, and direct costs through REST APIs secured by OAuth2 Client Credentials via a Developer Managed Service Account. The endpoint base is https://api.procore.com/rest/v1.0/ for most resources. Procore webhooks support create, update, and delete events on commitments, requisitions, direct costs, and change orders, and return 2xx within 5 seconds. Most endpoints require company_id and project_id as path or query parameters. OAuth tokens expire in 5400 seconds (90 minutes).

What moves between them

The main flow moves purchase orders and vendors from NetSuite into Procore as requisitions and commitment records, then costs flow back from Procore direct costs and payment applications into NetSuite GL journals allocated to cost codes. Master data such as vendors, cost codes, and budgets are aligned bidirectionally so Procore project allocations land on valid NetSuite cost centers and GL accounts. Procore webhooks push cost actuals in real-time when available; if webhooks are disabled or lag, ml-connector polls NetSuite SuiteQL for bulk reads to catch up.

How ml-connector handles it

ml-connector stores NetSuite OAuth2 credentials encrypted and refreshes the token before every call, since tokens expire in 60 minutes without a refresh token. On the Procore side it obtains an OAuth2 token via the Developer Managed Service Account and refreshes every 80 minutes. It maps NetSuite vendors to Procore vendors by name, purchase orders to requisitions and commitments, and syncs GL account numbers and cost code IDs so cost actuals in Procore post to the right NetSuite accounts. Since NetSuite does not emit HMAC signatures on Event Subscriptions, ml-connector validates webhooks using the IP allowlist and shared secret from the NetSuite setup, and it also polls SuiteQL for any records missed. Procore requires company_id and project_id on most calls, so ml-connector stores those per customer. Every record carries a full audit trail and can be replayed if a downstream call fails.

A real-world example

A mid-sized general contractor manages operations and financials in NetSuite across ten active projects. The projects use Procore for daily cost tracking, change orders, and budget management on site. Before the integration, the accounting team received PDF cost reports from Procore weekly, manually reviewed vendor names and cost codes, and re-entered the costs into NetSuite GL to close the books. With NetSuite and Procore connected, vendors and purchase orders from NetSuite populate Procore requisitions automatically, and cost actuals from Procore direct costs post into NetSuite GL each day under the matching cost code. Month-end close is faster because the cost accounts are already up to date.

What you can do

  • Sync NetSuite vendors and purchase orders into Procore as vendors, requisitions, and commitment contracts.
  • Post Procore direct costs and payment applications back into NetSuite GL, allocated to cost codes and departments.
  • Map NetSuite GL accounts and cost codes to Procore cost codes so project actuals land on the right accounting dimensions.
  • Refresh OAuth2 tokens on both sides and handle the different token expiry schedules (60 minutes for NetSuite, 90 minutes for Procore).
  • Validate NetSuite webhooks via IP allowlist and shared secret, with fallback polling via SuiteQL for records missed by webhooks.

Questions

Which direction does data move between Oracle NetSuite and Procore?
The main flow is bidirectional. Purchase orders and vendors move from NetSuite into Procore as requisitions and commitments. Cost actuals such as direct costs and payment applications flow from Procore back into NetSuite GL accounts, mapped to the correct cost codes. Master data such as vendors, cost codes, and budgets are aligned in both directions.
How does the integration handle NetSuite's lack of HMAC signatures on webhooks?
NetSuite Event Subscriptions do not include HMAC signatures, so ml-connector validates webhook authenticity using the IP allowlist configured in NetSuite and a shared secret passed in the webhook URL or header. ml-connector also polls NetSuite SuiteQL on a schedule to catch any records that webhooks may have missed.
Do OAuth2 tokens need to be refreshed during the sync?
Yes. NetSuite OAuth tokens expire in 60 minutes with no refresh token in the M2M flow, and Procore tokens expire in 90 minutes. ml-connector refreshes both tokens before they expire, either on every call or by caching in Redis and refreshing on a timer, to ensure calls do not fail due to token expiry.

Related integrations

Connect Oracle NetSuite and Procore

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

Get started