ml-connector
Wave AccountingServiceNow

Wave Accounting and ServiceNow integration

Wave Accounting handles invoicing and expense tracking for small businesses, while ServiceNow manages procurement, accounts payable, and supplier lifecycle across the enterprise. Connecting Wave to ServiceNow brings customer invoices from Wave into your AP workflow without re-keying, keeping invoice records synchronized in a single source of truth. Wave's webhook delivery ensures near-real-time notification of new and updated invoices, and ml-connector handles the OAuth token management and destination table mapping so your finance team stays current on incoming obligations.

How Wave Accounting works

Wave Accounting exposes customers, invoices, products, accounts, transactions, and sales tax records through a single GraphQL endpoint at https://gql.waveapps.com/graphql/public. Authentication uses OAuth 2.0 Authorization Code flow with two-hour access tokens and refresh tokens (offline_access scope required). Wave requires a Pro subscription for third-party API access. The system pushes invoice and customer events via webhooks (invoice.created, invoice.updated, invoice.paid, customer.created, customer.updated, payment.created, product.created, product.updated) and expects a 200 response to confirm delivery within five minutes. Webhook signatures are verified with HMAC-SHA256. Bills and accounts payable are not exposed in the GraphQL API, and invoices cannot be patched - they are created, approved, sent, or deleted.

How ServiceNow works

ServiceNow is deployed on a customer-supplied instance subdomain (https://{instance}.service-now.com) and exposes finance records including Accounts Payable invoices, suppliers, cost centers, and GL accounts via REST APIs. Authentication options are OAuth 2.0 Client Credentials (recommended for machine-to-machine), OAuth 2.0 Authorization Code (user-delegated), or Basic Auth. OAuth tokens expire after 1800 seconds by default. Source-to-Pay (S2P) staging tables (sn_apo_invoice, sn_s2p_supplier_inbound_staging) are module-licensed add-ons. ServiceNow has no native outbound webhook registration - polling with sysparm_query filters is the standard pattern. All table operations require a service account with appropriate module roles and table-level permissions. Instance configuration and module licensing vary by customer.

What moves between them

Wave invoice and customer events flow into ServiceNow's Accounts Payable staging tables (sn_apo_invoice and supplier records). When Wave sends a webhook for an invoice.created or invoice.updated event, ml-connector transforms the Wave invoice, customer (mapped to supplier), and line items into ServiceNow S2P staging format and posts to the instance. Customer records flow as supplier records. Payments are tracked but do not reverse AP invoices - ServiceNow matching rules determine reconciliation. The sync is one-way from Wave to ServiceNow; Wave remains the source of truth for invoices.

How ml-connector handles it

ml-connector registers a webhook endpoint with Wave and listens for invoice, customer, and payment events. When an event arrives, it validates the HMAC-SHA256 signature using Wave's x-wave-signature header and a 5-minute replay window. It extracts the Wave invoice or customer record via a GraphQL follow-up query if the webhook payload is sparse, and refreshes the Wave OAuth access token when the 2-hour expiry approaches. The invoice and customer are then transformed to match ServiceNow's S2P staging table schema (sn_apo_invoice fields like invoice_number, invoice_date, amount_due; supplier records with name, address, tax_id). ml-connector posts the transformed records to the customer's unique ServiceNow instance using the OAuth Client Credentials bearer token (or Basic Auth if configured). If the post fails due to missing supplier or GL account references, ml-connector logs the record, retries with exponential backoff, and flags the record for manual review in the audit trail. ServiceNow instance URL, OAuth credentials, and module configuration are per-customer; Wave OAuth app credentials are shared by the integration. The polling fallback uses a sysparm_query with sys_updated_on to fetch new Wave transactions if webhooks are disabled.

A real-world example

A small business selling professional services uses Wave Accounting to invoice clients and track monthly expenses. The finance team at their mid-market parent company uses ServiceNow for procurement, AP, and spend analysis. Before integration, invoices from Wave had to be manually entered into ServiceNow's AP module by a clerk, creating delays and data entry errors. With Wave and ServiceNow connected, each invoice Wave creates flows automatically into ServiceNow's AP staging tables, where it is matched against purchase orders and supplier master records. The parent company's finance team can now see Wave invoices in their AP dashboard the moment they are issued, and month-end close includes Wave invoices with no re-keying.

What you can do

  • Ingest Wave invoices via webhook or polling and post them to ServiceNow Accounts Payable staging tables.
  • Map Wave customers to ServiceNow suppliers and preserve customer name, address, and tax identification.
  • Validate Wave webhook signatures (HMAC-SHA256) and handle OAuth token refresh automatically.
  • Transform Wave invoice line items to match ServiceNow S2P invoice and line-item schema.
  • Track payment events in Wave and log them in ServiceNow audit for reconciliation support.

Questions

How does ml-connector handle Wave's OAuth tokens and refresh them?
ml-connector caches the Wave access token and monitors its 2-hour expiry. When the token nears expiration or a GraphQL call returns an authentication error, ml-connector uses the refresh token (offline_access scope) to obtain a new access token without re-authenticating the user. This ensures uninterrupted webhook and polling access.
What happens if Wave sends a webhook but the ServiceNow instance is unreachable or the supplier does not exist?
ml-connector validates the webhook signature and logs the record in its audit trail. If the ServiceNow POST fails (e.g., missing supplier master record), ml-connector retries with exponential backoff and exponential jitter. If retries are exhausted, the record is flagged as 'pending manual review' and an alert is sent to the finance team.
Can ml-connector sync Wave purchases or bills to ServiceNow?
No. Wave's GraphQL API does not expose bills or accounts payable records, only invoices created by the Wave business and sales transactions. ml-connector syncs only invoices and customers. Expenses tracked in Wave transactions can be polled but do not have a direct AP invoice format.

Related integrations

Connect Wave Accounting and ServiceNow

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

Get started