ml-connector
FreshBooksToast

FreshBooks and Toast integration

Toast runs a restaurant's operations: orders, payments, labor, inventory. FreshBooks runs the accounting. Connecting the two keeps your sales and payment records in sync between the POS and the general ledger. Toast order and payment events flow into FreshBooks as invoices and journal entries, with each restaurant location mapped to a FreshBooks client so cost and revenue stay organized by location. Toast voided orders and non-revenue items are automatically filtered out. ml-connector handles the OAuth bridge on both sides and moves the data on a schedule you control.

How FreshBooks works

FreshBooks is a cloud accounting platform that exposes invoices, bills, payments, expenses, chart of accounts, items, clients, and journal entries through REST APIs. It authenticates with OAuth 2.0 user-delegated authorization (not Client Credentials), so the credential set is tied to a specific user's FreshBooks account. FreshBooks uses account-specific URLs and namespaces (accounting/account/<accountId>) for most resources. Webhook support is not documented as a primary sync method, so records are typically read by polling or via manual triggers. FreshBooks' invoice and payment status fields are computed by the system and cannot be written directly.

How Toast works

Toast is a cloud restaurant management platform (POS, ordering, payments, labor, inventory) that exposes sales orders, checks, payments, menu items, employees, shifts, and configuration through REST APIs. It authenticates with OAuth 2.0 Client Credentials, exchanging clientId and clientSecret for a bearer token, with every request also carrying a Toast-Restaurant-External-ID header to specify the location. Toast supports both webhooks (for orders, payments, and menu changes via HMAC-SHA256) and polling. Webhooks are not guaranteed, so Toast recommends nightly reconciliation polls by business date. Multi-location restaurants must iterate across all locations (retrieved via /partners/v1/restaurants) and handle each restaurant's configurable closeoutHour so sales are attributed to the correct business date.

What moves between them

Toast order and payment events flow into FreshBooks. When a Toast webhook arrives for order_updated or payment events, ml-connector maps the order total to a FreshBooks invoice or journal entry, keyed to the FreshBooks client matching that Toast restaurant location. Toast voided orders (voided==true) and fundraising items are filtered out before posting. Payments and labor shifts can also be polled nightly by business date as a reconciliation safety net, since Toast webhooks are not guaranteed delivery. The flow is primarily one-way: Toast into FreshBooks. FreshBooks invoices and payments remain read-only to Toast.

How ml-connector handles it

ml-connector stores FreshBooks user credentials encrypted (the user-delegated OAuth token) and Toast credentials (Client Credentials clientId and clientSecret) encrypted per Toast location. For FreshBooks, it refreshes the OAuth token when a request returns 401, avoiding token expiry outages. For Toast, it caches the bearer token and re-authenticates only when the token expires, to avoid hitting the auth rate limit. When a Toast webhook arrives, ml-connector verifies the HMAC-SHA256 signature via the Toast-Signature header, then maps the order. Each Toast restaurant location is matched to a FreshBooks client by location name or external ID. Order line items map to FreshBooks items (by menu item name or SKU), and the order total is posted as an invoice or journal entry to the chart of accounts account specified for sales revenue. Voided orders and checks (checked via voided==true) are never posted. Service charges and fundraising items (flagged in selections) are excluded from net sales per Toast constraints. Multi-location restaurants require a separate Toast-Restaurant-External-ID per location; ml-connector retrieves all accessible locations via /partners/v1/restaurants and syncs each one. Payment records carry Toast externalId for deduplication (Toast does not document Idempotency-Key support). Business dates account for each restaurant's configurable closeoutHour, so a 1 AM sale on June 12 belongs to June 11 if closeoutHour is 3 AM. Nightly reconciliation polls run via GET /ordersBulk?businessDate=YYYYMMDD as a safety net, since Toast webhooks are not guaranteed. Every record carries a full audit trail and can be replayed if a downstream post to FreshBooks fails.

A real-world example

A restaurant operator runs Toast on 3 locations (flagship, airport kiosk, catering) and FreshBooks for accounting. Before integration, the manager exported daily sales reports from Toast each morning, manually created invoices in FreshBooks for each location, and entered the splits by menu category. Month-end reconciliation took hours because Toast and FreshBooks numbers rarely matched (timezone confusion, voided orders, service charges). With Toast and FreshBooks connected, each day's sales post automatically to FreshBooks as invoices, split by location and menu category. The manager can now see the numbers match the same day, and month-end is a data verification task instead of re-keying. Voided orders never make it to FreshBooks, and the system accounts for each location's closeout hour.

What you can do

  • Post Toast order sales to FreshBooks as invoices or journal entries, mapped by restaurant location and menu category.
  • Map each Toast restaurant location to a FreshBooks client so revenue and cost are organized by location.
  • Authenticate Toast with OAuth 2.0 Client Credentials and FreshBooks with user-delegated OAuth, storing both credential sets encrypted.
  • Filter out Toast voided orders, fundraising items, and service charges before posting to FreshBooks.
  • Poll Toast nightly by business date for orders and payments as a reconciliation safety net when webhooks are delayed or lost.

Questions

How does ml-connector handle Toast's multi-location requirement?
ml-connector retrieves all accessible Toast locations via /partners/v1/restaurants and stores a separate Toast-Restaurant-External-ID for each location. Every webhook and poll request includes the location ID in the header. Each location is mapped to a FreshBooks client by name or external ID, so sales from the flagship location post to one FreshBooks client and sales from the airport kiosk post to another.
What happens to voided orders and service charges in Toast?
Voided orders (where voided==true) are never posted to FreshBooks. Fundraising items flagged in selections and service charges classified as gratuity are also excluded from net sales before the order total is sent to FreshBooks. This ensures FreshBooks GL accounts reflect only genuine revenue.
Why does Toast require nightly reconciliation polls if webhooks are available?
Toast webhooks are not guaranteed delivery, and the recommendation is to implement nightly reconciliation as a safety net. ml-connector polls Toast by business date each night via GET /ordersBulk?businessDate=YYYYMMDD to catch any orders or payments that webhooks may have missed, and compares the results to what was already posted to FreshBooks to avoid duplicates.

Related integrations

Connect FreshBooks and Toast

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

Get started