ml-connector
Sage 50Zuora

Sage 50 and Zuora integration

Sage 50 is your on-premise accounting system of record. Zuora manages your subscription billing and revenue recognition. Connecting them keeps customer master data and billing records in sync without manual re-entry. Customer records flow from Sage 50 into Zuora, and invoice details post back so your general ledger reflects what Zuora invoiced. The sync runs on a schedule you control, bridging the gap between desktop accounting and cloud billing.

How Sage 50 works

Sage 50 is a Windows desktop-installed accounting application with two regional editions: US (formerly Peachtree Accounting) and UK (formerly Sage Line 50). It exposes customers, vendors, invoices, purchase orders, general journal entries, and employee records through Windows SDKs only - no REST or cloud API. The US edition uses the .NET SDK or legacy COM/ODBC, while the UK edition uses Sage Data Objects (SDO) COM/ActiveX DLLs. Authentication is Windows-local via username and password against the Sage 50 user database, with access to company data files on the local machine or LAN. There are no webhooks, only polling by modified date or transaction date. Integration requires a Windows process with direct file access and exclusive access to the Sage 50 company database.

How Zuora works

Zuora is a REST API subscription billing platform accessible over HTTPS from any region via OAuth2 client credentials. The base URL is region-specific (rest.zuora.com, rest.sandbox.zuora.com, rest.eu.zuora.com, rest.ap.zuora.com) and must be captured per customer tenant. Zuora exposes accounts (customers), subscriptions, invoices, payments, product catalogs, and orders through REST v1 endpoints. Bearer tokens expire in one hour and must be refreshed via the OAuth token endpoint. Zuora also supports Callout Notifications (webhooks) for billing events (invoice posted, payment processed, subscription renewed), but the core integration uses REST polling. Rate limits are 50,000 requests per minute in production, with mandatory multi-entity headers for tenants with subsidiaries.

What moves between them

Customer records and billing data flow from Sage 50 to Zuora. ml-connector polls Sage 50 for new or modified customer records and sales invoices at a configurable interval (recommended 5-15 minutes for near-real-time or hourly for batch sync). Customer master data is mapped to Zuora Accounts, and invoice detail is posted as Zuora Invoice objects. No data flows back into Sage 50 from Zuora. The sync is one-way to support billing-only scenarios where Zuora is the source of truth for subscription orders and revenue, while Sage 50 remains the general ledger and customer master.

How ml-connector handles it

ml-connector stores Sage 50 SDK credentials (Windows username, password, company path for US edition or data path for UK edition) encrypted, and uses them to authenticate against the Sage 50 user database on the configured machine. On the Zuora side, it exchanges client_id and client_secret for an OAuth2 bearer token, captures the region-specific base URL, and refreshes the token every 55 minutes before expiry. Because Sage 50 has no webhooks and runs on a local desktop, ml-connector polls Sage 50 for modified customer and invoice records by LastModifiedDate or TransactionDate on a configurable schedule. Zuora API responses include region and rate-limit headers, so ml-connector backs off when it approaches the 50,000 RPM limit and logs every rate-limit event. Customer records map to Zuora Accounts by external ID, and invoices post with the customer reference already set. Zuora webhook payload is minimal, so any account updates from Zuora are fetched via REST callbacks rather than relying on the webhook body. Every record carries a full audit trail with source and target IDs, timestamp, and reason codes.

A real-world example

A mid-sized SaaS company runs Sage 50 for general ledger and AP/AR management and Zuora for recurring revenue and subscription billing. Before integration, the finance team exported customer lists from Zuora and manually created or updated matching customer records in Sage 50 each billing cycle, then exported invoices from Zuora and re-entered them as sales invoices for revenue recognition. Month-end close required chasing down which invoices had actually been created in the GL and which were still pending. With Sage 50 and Zuora connected, customer changes in Zuora flow back to Sage 50, and every subscription invoice posts automatically to AR. The finance team now starts close with all Zuora revenue already recorded in the GL.

What you can do

  • Sync customer master data from Sage 50 into Zuora as account records, with deduplication by external ID.
  • Post Zuora invoice details back to Sage 50 as sales invoice records for revenue recognition and AR aging.
  • Authenticate Sage 50 via local Windows credentials and SDK, and Zuora via OAuth2 client credentials.
  • Poll Sage 50 on a configurable schedule for new or modified invoices and customer records, with full retry logic.
  • Track all synced records with audit trails, including source/target IDs, sync timestamp, and error details.

Questions

How does ml-connector access Sage 50 if it has no cloud API?
ml-connector runs on a Windows machine or VM with Sage 50 installed and uses the Windows SDK (either .NET or COM/ODBC) to authenticate via local username and password against the Sage 50 user database. It accesses company data files directly from the local drive or LAN. This is the only way to integrate Sage 50, since it has no REST, SOAP, or web service layer.
What region does Zuora use, and how does ml-connector know which endpoint to call?
Zuora base URLs are region-specific (rest.zuora.com for US, rest.eu.zuora.com for Europe, rest.ap.zuora.com for Asia-Pacific). ml-connector captures the region per customer tenant at setup and uses the correct base URL on every API call. If a customer's region changes, the configuration is updated and all subsequent calls route to the new endpoint.
Does the sync run continuously, or on a schedule?
Sage 50 has no webhooks, so ml-connector polls on a schedule you set. The recommended interval is 5-15 minutes for near-real-time sync or hourly for batch-style reconciliation. Every poll checks Sage 50 for modifications since the last run, syncs only changed records, and logs the outcome to the audit trail.

Related integrations

Connect Sage 50 and Zuora

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

Get started