ml-connector
Wave AccountingProcore

Wave Accounting and Procore integration

Wave Accounting keeps your books; Procore tracks your projects and costs. Connecting the two means your open invoices and vendor data in Wave flow into Procore as payment applications, your project costs from Procore come back into Wave as cost allocations, and commitments and budget changes are automatically recorded without manual re-keying. ml-connector handles the GraphQL to REST bridge and the OAuth token lifecycle on both sides.

How Wave Accounting works

Wave Accounting exposes businesses, customers, invoices, vendors, accounts, products, and transactions through a GraphQL API endpoint at https://gql.waveapps.com/graphql/public. It uses OAuth 2.0 Authorization Code flow with access tokens that expire in 2 hours and refresh tokens for long-lived sessions. The connected business must have a Wave Pro subscription. Wave publishes webhooks for invoice creation, updates, and payment events, and returns HTTP 200 to acknowledge delivery and 500 to request retry. Webhook signatures are validated with HMAC-SHA256 using the x-wave-signature header. Bills and purchase orders are not exposed through the Wave GraphQL API.

How Procore works

Procore exposes vendors, purchase order contracts, requisitions, payment applications, direct costs, budget line items, cost codes, and change orders through REST APIs at https://api.procore.com/rest/v1.0/ and v2.x/. It authenticates via OAuth 2.0 client credentials through a Developer Managed Service Account, with tokens expiring in 1.5 hours. Most endpoints require both company_id and project_id path or query parameters. Procore supports webhooks for real-time push on commitment, requisition, direct cost, and budget changes, returning custom headers for security rather than HMAC signatures. Webhooks must return HTTP 2xx within 5 seconds, and webhook delivery is not retried on timeout.

What moves between them

Wave unpaid invoices flow into Procore as vendors and payment applications on a daily schedule. Procore commitments, requisitions, and budget changes flow back into Wave as accounts payable and accrual journal entries at the same cadence. Wave customers are mapped to Procore cost codes so that invoices are allocated to the correct project and cost type. Reference data such as vendors and cost codes are aligned in both directions. GL account codes from Wave are matched to Procore cost codes based on customer and invoice type.

How ml-connector handles it

ml-connector stores Wave's OAuth refresh token and uses it to obtain a fresh access token every 2 hours before expiry, then runs the same cycle for Procore's client credentials. On the Wave side, it fetches unpaid invoices via GraphQL and transforms them into Procore vendor and payment application records, mapping Wave customer IDs to Procore cost codes. On the Procore side, it polls commitments and budget changes and transforms them into Wave journal entries that debit the accrual account and credit the GL account for the cost code. Webhook verification uses the Wave signature check before processing any webhook event. Procore webhooks are polled rather than pushed due to Procore's 5-second return timeout. Line-item amounts are validated against Procore budget remaining before posting to prevent over-commitment, and retries use exponential backoff for any call that returns 429 or 5xx.

A real-world example

A mid-sized construction firm uses Wave Accounting for its books and Procore to manage multiple active projects. Before integration, the finance team received notifications of Procore commitments and budget changes via Procore, then manually keyed the corresponding accrual entries into Wave at month-end. Project managers would request invoice approval in Procore without visibility into whether Wave had recorded the vendor. With Wave and Procore connected, Procore commitments flow into Wave as accruals immediately, and all unpaid invoices in Wave appear as Procore vendors and requisitions, so project budgets are always anchored to what Wave considers open. The firm no longer has to reconcile two separate vendor lists or manually accrue commitments.

What you can do

  • Sync Wave unpaid invoices into Procore as vendors and payment applications, mapped to the correct projects and cost codes.
  • Flow Procore commitments, requisitions, and budget changes back into Wave as accounts payable and accrual journal entries.
  • Map Wave customer accounts to Procore cost codes so invoices land on the correct project and cost type.
  • Handle Wave OAuth token refresh (2-hour expiry) and Procore client credentials, with automatic retry on 429 and 5xx responses.
  • Validate invoice amounts against Procore budget before posting and track full audit history on every record.

Questions

Which direction does data flow between Wave Accounting and Procore?
Unpaid invoices and vendors flow from Wave into Procore as payment applications and vendors. Procore commitments, requisitions, and budget changes flow back into Wave as journal entries that accrue the cost. Reference data such as customers and cost codes are aligned in both directions so that invoices post to the correct project.
How does ml-connector handle Wave's GraphQL API and Procore's REST API?
ml-connector stores the OAuth credentials for both systems and refreshes them before expiry (Wave refreshes every 2 hours, Procore every 1.5 hours). It fetches data from Wave's GraphQL endpoint, transforms it to Procore REST format for posting, and does the reverse for budget and commitment data flowing back into Wave as journal entries.
What happens if a Wave invoice exceeds the remaining budget in Procore?
ml-connector validates each invoice amount against the available budget for the Procore project and cost code before posting it as a payment application. If the invoice would exceed budget, the record is flagged in the audit trail and an alert is sent to the operations team for review.

Related integrations

Connect Wave Accounting and Procore

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

Get started