ml-connector
Sage IntacctShipStation

Sage Intacct and ShipStation integration

Sage Intacct runs your accounting and finance. ShipStation runs your shipping and fulfillment. Connecting the two keeps your cost of goods sold accurate and your ledger reconciled. Every shipment that leaves your warehouse carries a freight charge, fulfillment fee, or carrier surcharge that needs to post to the right GL accounts and cost centers. With Sage Intacct and ShipStation connected, those costs flow automatically into your general ledger, matched to the sales invoice and allocated to the product line or warehouse that shipped it.

How Sage Intacct works

Sage Intacct is a cloud accounting ERP that exposes vendors, bills, general ledger accounts, dimensions, and AP payments through an XML gateway endpoint at https://api.intacct.com/ia/xml/xmlgw.phtml. Authentication is session-based: a caller provides senderId, senderPassword, companyId, userId, and userPassword to obtain a sessionid good for 50 minutes, which is cached and reused. Sessions are isolated per senderId and companyId pair. Intacct does not publish webhooks; all reads are polling-based, and the API requires strict control of XML serialization and avoidance of forbidden C0 control characters. HTTP responses are always 200 even when an operation fails internally, so the caller must parse the XML response body for errormessage tags and status flags.

How ShipStation works

ShipStation is a cloud shipping platform that exposes orders, customers, shipments, products, warehouses, and purchase orders via REST APIs in JSON. It offers two API versions: V1 (order CRUD, customer management, product and warehouse lookup) with Basic Auth using apiKey and apiSecret, and V2 (label creation, batch operations, inventory management) with API-Key header auth. V1 supports 40 requests per minute; V2 supports 200. ShipStation pushes webhook notifications (ORDER_NOTIFY, SHIP_NOTIFY, ITEM_SHIP_NOTIFY, FULFILLMENT_SHIPPED, FULFILLMENT_REJECTED) but the payload is a pointer only; the actual order or shipment data must be fetched with an authenticated GET. ORDER_NOTIFY fires only on new orders; order edits and changes require polling via a modifyDate filter. All V1 timestamps are in PST/PDT, not UTC.

What moves between them

The main flow is ShipStation into Sage Intacct. When a shipment is picked, packed, and shipped in ShipStation, ml-connector receives the webhook notification (SHIP_NOTIFY or FULFILLMENT_SHIPPED), fetches the full shipment details including carrier, tracking number, and cost, and posts the freight and fulfillment costs into Intacct's general ledger. If the shipment includes a surcharge or third-party carrier cost, those are posted to separate GL accounts so cost accounting can see the breakdown. Shipping orders and their line items are matched to Sage Intacct sales orders and invoices so the costs land on the right customer and product. The posting runs immediately when the webhook is received, with a fallback polling schedule every four hours to catch any missed notifications.

How ml-connector handles it

ml-connector obtains a Sage Intacct session once per deployment and caches the sessionid, automatically refreshing when the 50-minute window expires. On the ShipStation side, it registers a webhook receiver endpoint for SHIP_NOTIFY and FULFILLMENT_SHIPPED events and handles the webhook payload by fetching the full shipment record via authenticated V1 GET. Shipments are matched to Sage Intacct sales orders using the order number and customer lookup; if the match fails, the record is held for manual review. Freight and carrier costs from ShipStation are mapped to configurable GL accounts per carrier (UPS, FedEx, USPS, etc.) so the ledger distinguishes between freight types. Because ShipStation's webhook payloads arrive with only the resource URL, ml-connector fetches each shipment immediately to avoid losing data if the URL expires. Intacct's lack of native idempotency is handled by the control block uniqueid flag, so retried shipment postings do not create duplicate GL entries. All V1 timestamps from ShipStation are converted from PST/PDT to UTC before logging.

A real-world example

A mid-sized e-commerce retailer ships orders from two fulfillment centers via multiple carriers (FedEx Ground, UPS, USPS). Before the integration, the warehouse manager exported the weekly shipment report from ShipStation, extracted the freight costs per carrier, and manually entered journal entries in Sage Intacct. During month-end close, the finance team reconciled the freight expense account against the carrier invoices and often found mismatches caused by manual entry errors or missed shipments. With ShipStation and Sage Intacct connected, each shipment automatically posts its cost to the correct GL account and cost center for that fulfillment center. The freight expense account reconciles to ShipStation in minutes, and month-end close no longer requires the manual freight entry step.

What you can do

  • Post ShipStation shipping costs (freight, surcharges, carrier fees) into Sage Intacct's general ledger on receipt of shipment notifications or on a polling schedule.
  • Match ShipStation shipments to Sage Intacct sales orders and invoices so costs are allocated to the correct customer and product line.
  • Map ShipStation carriers to specific GL accounts so the ledger shows a breakdown of freight by carrier type (FedEx, UPS, USPS, etc.).
  • Handle Sage Intacct session authentication, session expiry and refresh, XML serialization, and C0 control character validation automatically.
  • Receive ShipStation webhook notifications in real time and poll every four hours as a fallback to catch missed shipments, with full audit trail and error replay.

Questions

What costs from ShipStation post into Sage Intacct?
Freight charges, fulfillment fees, and carrier surcharges. These are broken down by carrier type (FedEx, UPS, USPS, etc.) and posted to the GL accounts you configure. Insurance and other ancillary charges can also be included. Only outbound shipments are posted; returns and exchanges are tracked separately.
Does ml-connector use ShipStation webhooks or polling?
Both. ml-connector registers a webhook receiver for SHIP_NOTIFY and FULFILLMENT_SHIPPED events to catch shipments in real time, and it polls ShipStation every four hours as a fallback in case a webhook is missed or arrives late. The webhook payload is a pointer only, so ml-connector fetches the full shipment data via authenticated GET before posting to Intacct.
How does ml-connector handle Sage Intacct's session authentication and XML requirements?
ml-connector caches the sessionid for 50 minutes and automatically refreshes it when it expires, so the Intacct API is always ready. It handles XML escaping and strips forbidden C0 control characters before sending to Intacct. For retried postings, it uses Intacct's control block uniqueid flag to prevent duplicate GL entries.

Related integrations

Connect Sage Intacct and ShipStation

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

Get started