ml-connector
Sage 300Toast

Sage 300 and Toast integration

Toast runs a restaurant's point of sale, labor, and ordering. Sage 300 runs the back office accounting and ERP. Connecting the two moves sales and payment records from Toast into Sage's general ledger and accounts receivable, so your daily revenue and cash position are always reconciled. Toast's orders are voided or modified throughout the day, and ml-connector polls daily to capture the final state of each sale and post it once into Sage without re-keying.

How Sage 300 works

Sage 300 is an on-premise ERP installed on a customer's Windows IIS server with SQL Server as the backend. It exposes Accounts Payable, Accounts Receivable, General Ledger, Purchase Orders, Order Entry, and Inventory Control through REST and OData APIs at a customer-specific URL. Every request uses HTTP Basic Authentication with uppercase username and password sent in the Authorization header. Sage has no webhooks or change-data-capture, so all sync is pull-based via polling with OData $filter, $skip, and $top parameters. Master data endpoints support GET, POST, PUT, and DELETE, while transaction batches support GET and POST only. The API user must be created in Administrative Services with the Web API security group assigned.

How Toast works

Toast is a cloud-based POS and restaurant management platform that surfaces sales orders, payments, labor shifts, menu items, and configuration through REST APIs over HTTPS. Authentication uses OAuth2 Client Credentials, exchanging clientId and clientSecret for a bearer token that must be included with every request along with a Toast-Restaurant-External-ID header identifying the specific location. Toast supports both webhooks for order and menu changes and polling for historical reconciliation. Voided orders, checks, and payments are returned by the API and must be filtered client-side. Service charges may be classified as gratuity, affecting tax and tip reporting. Configuration API pagination restarts on conflict if settings change during a scan.

What moves between them

The main flow is Toast into Sage 300. After each business date closes, ml-connector polls Toast's orders and payments via the ordersBulk endpoint using Toast's configurable closeout hour, then posts daily sales and payment records into Sage 300 as transaction batches in the general ledger and accounts receivable. Revenue centers from Toast are mapped to corresponding GL accounts in Sage, and line-item discounts are posted to discount GL accounts. Voided orders and voided payments are excluded from posting. Toast supports multi-location restaurants, and each location is synced separately using its unique Toast-Restaurant-External-ID. Labor shifts and payroll data are reconciled on a separate schedule if needed.

How ml-connector handles it

ml-connector obtains a Toast OAuth2 bearer token by exchanging client credentials and caches it to avoid auth rate limits, refreshing only when the token expires. For each Toast restaurant location, it polls the ordersBulk endpoint on a schedule keyed to that restaurant's closeout hour, accounting for Toast's business-date logic where sales after the closeout hour belong to the next business date. Voided orders, voided checks, and voided payments are filtered out before posting. Revenue centers and sales categories in Toast are pre-mapped to GL accounts in Sage via configuration, so each line item posts to the correct account. Service charges that are flagged as gratuity are excluded from net sales postings. ml-connector then builds and posts daily transaction batches into Sage 300's general ledger using HTTP Basic Auth with the uppercase credentials. Because Sage is pull-only with no webhooks, and Toast orders can be modified throughout the day, the nightly reconciliation poll ensures the final state is posted exactly once. Rate limits are respected: Toast enforces 20 requests per second default, and historical orders older than 1 month are fetched at reduced rate with spacing between calls.

A real-world example

A regional restaurant group operates 12 locations under one Toast account, each with its own POS and closeout time. The operations team uses Sage 300 to manage AP invoices from suppliers, AR for franchise fees, and GL for consolidated daily reporting. Before the integration, a bookkeeper exported Toast sales and payment reports each morning, manually classified revenue by line item to GL accounts, and posted daily batches into Sage AR and GL by hand. With Toast and Sage 300 connected, each restaurant's sales and payments post automatically after closeout, mapped to the correct GL accounts by revenue center, and the bookkeeper receives a daily reconciliation report. Month-end GL reconciliation is now instant, and the manual export-and-post work is eliminated.

What you can do

  • Post Toast sales orders and payments into Sage 300 as daily transaction batches allocated to the correct GL accounts by revenue center.
  • Filter voided orders, checks, and payments before posting, and exclude gratuity service charges from net sales.
  • Map Toast revenue centers, sales categories, and discounts to Sage 300 GL accounts via configuration.
  • Handle Toast multi-location restaurants by polling each location separately using its unique Toast-Restaurant-External-ID and account for each location's configurable business-date closeout hour.
  • Authenticate Toast with OAuth2 bearer token (with caching to avoid rate limits) and Sage 300 with HTTP Basic Auth, polling daily to capture final transaction state.

Questions

How does ml-connector handle Toast orders that are modified or voided throughout the day?
Toast orders can be voided or modified up until closeout. ml-connector polls Toast daily after the restaurant's configurable closeout hour, capturing the final state of all orders and payments for that business date. Voided orders and voided payments are filtered out and not posted to Sage. Because Toast returns all orders (including voided), ml-connector filters client-side before building the daily transaction batch.
How are Toast revenue centers and discounts mapped to Sage 300 GL accounts?
Before the first sync, you configure a mapping table that pairs each Toast revenue center and sales category to a GL account number in Sage 300. ml-connector applies these mappings when building daily transaction batches, so each line item posts to the correct GL account. Discounts are mapped to a designated discount GL account, keeping revenue and allowances separate for P&L reporting.
Why does ml-connector cache the Toast OAuth2 token instead of authenticating on every request?
Toast enforces a rate limit of 20 requests per second. Authenticating on every request would quickly exceed the auth rate limit and cause request rejections. Token caching allows ml-connector to exchange credentials once and reuse the token for many API calls, refreshing only when the token expires or a request returns 401 Unauthorized.

Related integrations

Connect Sage 300 and Toast

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

Get started