Sage integration: three products, three different APIs
There is no single Sage API, because Sage is not a single product. Sage Intacct exposes a REST API that Sage recommends for new work, alongside an older XML interface that still reaches parts of the feature set. Sage 200 exposes a REST API over its business data. Sage X3 uses GraphQL rather than REST. Scoping any Sage integration starts with establishing which of these you actually run.
"We're on Sage" is not enough information to scope an integration, and treating it as though it were is the most expensive mistake in this particular corner of ERP work.
Sage is a family of separate products. The three that matter for mid-market manufacturers and distributors expose three different interfaces, and an integration written for one transfers almost nothing to another.
| Product | Interface | Notes |
|---|---|---|
| Sage Intacct | REST API (recommended) + legacy XML | New objects and features arrive on REST; XML still reaches the full feature set |
| Sage 200 | REST API | Standard and Professional: customers, suppliers, stock, sales and purchase orders, nominal ledger |
| Sage X3 | GraphQL | Not REST — client code and connectors do not carry over |
So the first question in the first meeting is not about data or volumes. It is: which Sage?
Sage Intacct: the credential step that delays projects
The Intacct REST API authenticates with OAuth 2.0 bearer tokens. You register an application in the Sage Developer Portal, obtain a client id and client secret, and use the authorization code flow for user-delegated access. So far, ordinary.
What is not ordinary is what sits underneath it. Registering that application requires an active Sage Intacct Web Services developer licence, which carries a Web Services sender ID and password. OAuth authenticates the user; the sender ID identifies your application to Sage. The modern authentication layer does not remove the older credentialing requirement.
In planning terms this belongs on the timeline before the first line of code, in the same way an API application does for other vendors. Teams that treat OAuth as the whole story lose the first fortnight.
The failure that looks like bad credentials
There is a second, related step that produces the most confusing error in Intacct work: the company you are sending requests to must authorise your sender ID.
That authorisation happens in one of two places — the web sender id is added on the company's security settings, or an administrator approves the OAuth authorization request when it is raised. Until it is done, perfectly valid credentials still fail, and the message rarely points at the real cause. If you are debugging an Intacct integration where the tokens look right and the calls do not work, check this before anything else.
REST or XML?
Use REST for new work: it is what Sage recommends for client applications and where new objects and features are released. Keep the older XML interface in mind rather than dismissing it, because it reaches the full feature set, including areas REST has not covered. A mature Intacct integration is often both — REST for everything it supports, XML for the remaining gaps — and that is a normal outcome, not a design failure.
OData
There is no native OData surface. Where a reporting tool expects OData, it is provided by third-party products that sit in front of the API and translate. That is a legitimate approach, but treat it as an additional component with its own licence, hosting and failure modes rather than as a Sage capability.
Sage 200: the straightforward one
The Sage 200 REST API covers business management data across Standard and Professional: customers, suppliers, stock, sales orders, purchase orders and the nominal ledger.
For the work most mid-market companies actually want — a distributor ordering portal, a field application, a reporting layer — that surface covers the sales and inventory ground without unusual constraints. Of the three, this is the one where the integration effort is closest to the estimate.
Sage X3: GraphQL changes the client, not the rules
Sage X3 exposes a GraphQL API across manufacturing, distribution, procurement, finance and CRM.
The practical consequence is in the shape of the client code rather than in the integration rules. A GraphQL query declares exactly the fields it wants and can pull related records in one round trip, so the familiar REST pattern — fetch the order, then fetch each line, then fetch the customer — collapses into a single request. That is an advantage once the team is comfortable with it.
The cost is that nothing transfers. REST client libraries, connectors and code written for Intacct or Sage 200 are of no use here, and neither is the mental model. If a proposal quotes X3 work using experience from another Sage product, ask how the GraphQL layer was accounted for.
What stays true across all three
The product-specific detail is where the effort goes, but the integration rules do not change:
- Documents are posted through the API, not into the database. The API runs validation, ledger postings and document numbering. A direct database write leaves a record the application has never processed, and the discrepancy is found at period close.
- Reading from the database is a different question. Reporting queries against the data are lower risk and often the sensible way to avoid a large volume of API calls.
- Every write carries your own document reference. When a retry happens, the second request carrying the same reference updates the existing record rather than creating a second one.
- A queue sits in the seam. Maintenance windows and upgrades happen. Requests accumulate and replay in order rather than disappearing.
Questions to settle before estimating
- Which Sage product, and which edition? This determines the interface and most of the effort.
- For Intacct: is there a Web Services developer licence and sender ID already? If not, that lead time comes before development.
- Who administers the target company? Someone has to authorise the sender ID, and it is rarely the person commissioning the work.
- Does any reporting tool expect OData? If so, price the translation layer separately.
- For X3: does the team have GraphQL experience? If the estimate assumes REST, it is wrong.
Settling those five turns a Sage integration from an open-ended piece of work into an ordinary one.
If the target is a distributor-facing portal, the ordering rules — price read from the ERP, free stock rather than physical, credit limits checked before the write — are covered in B2B dealer portal ERP integration. For a comparable write-up on the other common mid-market system, see Odoo integration. To scope work on the Sage system you already run, tell us about your process; the first call takes 30 minutes and costs nothing, and the bands are on the pricing page.
Frequently asked questions
Is there one Sage API?
No. Sage is a family of separate products with separate interfaces, and they are not compatible with one another. Sage Intacct offers a REST API plus an older XML interface. Sage 200 offers a REST API covering customers, suppliers, stock, sales orders, purchase orders and the nominal ledger. Sage X3 uses GraphQL. An integration written for one of them tells you almost nothing about the work required for another.
Which API should a new Sage Intacct integration use?
The REST API. Sage recommends it for client applications and releases new objects and features there. The older XML interface still matters because it reaches the full feature set, including areas the REST API has not yet covered, so a mature integration sometimes uses both: REST for everything it supports and XML for the remaining gaps.
How does authentication work for the Sage Intacct REST API?
Through OAuth 2.0 with bearer tokens. You register an application in the Sage Developer Portal to obtain a client id and client secret, then use the authorization code flow for user-delegated access. This is a standard OAuth implementation, but it sits on top of a Sage-specific credentialing step that catches most teams out.
Do I still need a Web Services sender ID if I use OAuth?
Yes. Registering an application in the Sage developer workspace requires an active Sage Intacct Web Services developer licence, which carries a Web Services sender ID and password, or access through a trial account. OAuth does not remove that requirement — it authenticates the user, while the sender ID identifies your application to Sage. Budget time for obtaining it before development starts.
Why do Sage Intacct API calls fail even with valid credentials?
Usually because the target company has not authorised your sender ID. Each Sage Intacct company you send requests to must explicitly authorise it — either by adding the web sender id on the company's security settings, or by having an administrator approve the OAuth authorization request when it is raised. Until that is done, correct credentials still produce failures, and the error rarely names the real cause.
Does Sage support OData?
Not natively for Sage Intacct. OData access is achieved through third-party products that sit in front of the API and expose an OData surface. If a reporting tool in your stack expects OData, treat that as an extra component with its own licence, hosting and failure modes rather than as a built-in Sage capability.
How is Sage X3 different to integrate with?
Sage X3 exposes a GraphQL API rather than REST, covering manufacturing, distribution, procurement, finance and CRM operations. That changes the shape of the client code: queries declare exactly the fields they want and related records can be fetched in one round trip, so the usual REST pattern of many small calls does not apply. Existing REST client libraries and connectors written for other Sage products do not transfer.
What does the Sage 200 API cover?
The Sage 200 REST API provides access to business management data across Sage 200 Standard and Professional, including customers, suppliers, stock, sales orders, purchase orders and the nominal ledger. That covers the ground most distributor portals, field applications and reporting layers need on the sales and inventory side.
Can I write to the Sage database directly instead?
It is the wrong approach for the same reason it is in any ERP. Posting a document through the API runs the validation, ledger postings and document numbering that the product itself applies. A direct database write produces a record the application can display but has never processed, so the ledger does not balance and the discrepancy is found during a period close. Read-only reporting against the database is a separate question and is far less risky.
Let's talk about what you need.
The 30-minute discovery call is free and carries no commitment.