top of page
maesn 2.png

Sage Active API Integration: GraphQL, X-OrganizationId, Cursor Pagination and ID-Based References Explained

  • Writer: Marius Pohle | Co-Founder
    Marius Pohle | Co-Founder
  • Feb 25
  • 6 min read

Sage Active is a cloud accounting platform for small businesses launched by Sage in 2023, available in France, Spain, and Germany. It is built for accounting firms and their clients, with a shared ledger model that enables accountants to work directly alongside their customers.


For software teams, Sage Active API is technically one of the more complex systems to integrate directly - it uses GraphQL instead of REST, requires a mandatory company identifier on every request, and has cursor-based pagination throughout. In this article, you will learn what that means in practice — and why, with Maesn, none of it matters.

Key Takeaways

  • Sage Active uses GraphQL. Instead of multiple fixed endpoints with GET/POST/PUT, everything goes through a single endpoint where the client defines exactly what data it needs using queries and mutations. This is more flexible but significantly more complex to build and maintain.

  • Every request requires the X-OrganizationId header. You cannot make any API call without the correct company identifier — which must be fetched after authentication.

  • Authentication uses OAuth 2.0, with an access token valid for 8 hours. The offline_access scope is required to receive a refresh token for long-lived integrations.

  • Pagination is cursor-based, a GraphQL standard. You cannot jump to specific pages — data must be traversed sequentially using cursors.

  • Creating objects requires pre-resolved internal IDs. Fields like unitOfMeasurementId cannot receive human-readable values like "KILOGRAM" — numeric IDs must be fetched and mapped first.

  • Sage Active is available in France, Spain, and Germany.

  • Maesn handles all of the above. One unified REST API — GraphQL complexity, X-OrganizationId injection, cursor pagination, and ID resolution are all abstracted in the Maesn Unified API.


Sage Accounting API Integration with Maesn
Sage Accounting API Integration with Maesn

Sage Active API Integration requires handling GraphQL

Many modern APIs use REST: multiple fixed endpoints where the HTTP method (GET, POST, PUT) determines the operation, and the server defines the response structure. Sage Active chose GraphQL, which changes the integration model fundamentally.

With GraphQL, there is a single endpoint. The client sends a query to retrieve data or a mutation to create or update data, and defines exactly which fields it wants in the response. This gives you precise control over data shape and avoids over-fetching — you only receive what you ask for. On paper, this is a developer-friendly design. In practice, it introduces significant integration complexity:

  • You need to maintain GraphQL query syntax, including the Hot Chocolate conventions Sage Active uses

  • Queries must be constructed and validated before they can be executed

  • Every update to the data model requires reviewing whether existing queries still return the expected structure

  • Teams already familiar with REST accounting integrations face a learning curve that can add weeks to initial development

Sage Active API Integration enforces a GraphQL complexity limit on all queries to prevent resource-intensive requests from overloading the server. Queries that exceed this limit are rejected. This means you cannot always fetch deeply nested data in a single query — you may need to split operations across multiple requests.


Maesn exposes a unified REST API for Sage Active that works the same way across all supported accounting systems

The GraphQL queries, mutations, Hot Chocolate conventions, and complexity management are handled entirely in the Maesn backend. You make standard REST calls to Maesn — Maesn translates these into the correct GraphQL operations for Sage Active and returns normalized data in the Maesn common data model.


Every Sage Accounting Request Requires X-OrganizationId

After completing the OAuth flow and obtaining an access token, you cannot immediately start making API calls. Sage Active requires a X-OrganizationId header on every single request — this is the internal company identifier that tells the API which organization's data you are accessing.

The flow works as follows:

  1. The end user authenticates via OAuth 2.0 and your system receives an access token

  2. You call the organizations endpoint to retrieve the list of organizations the authenticated user has access to

  3. The user selects the correct organization

  4. Maesn securely stores this X-OrganizationId and injects it automatically into all subsequent API requests for that tenant

Without this identifier, every API call returns an authorization error. For a multi-tenant SaaS product, this means you need a post-authentication step for every customer that fetches, presents, and stores the correct organization ID before any integration work can begin.


Maesn Requests the X-OrganizationId and Injects It Into Every Call Automatically

Maesn requests the X-OrganizationId flow as part of its interactive authentication setup. The end user authenticates once, selects the desired company, and Maesn securely stores and manages this context. All subsequent API calls are automatically enriched with the correct X-OrganizationId — your integration never touches this header directly.


OAuth 2.0 With 8-Hour Token Expiry — and offline_access Required for Refresh Tokens

Sage Active API Integration uses standard OAuth 2.0 for authentication. The access token is valid for 8 hours (expires_in: 28800 seconds), requiring a refresh strategy for long-running integrations.

Refresh tokens are only issued if you explicitly request the offline_access scope during the initial authorization request. Without it, your integration will require the user to re-authenticate every 8 hours. For a production SaaS integration, offline_access is effectively mandatory.

Two scopes control data access:

  • RDSA — read access to Sage Active data

  • WDSA — write access to Sage Active data

Following the Principle of Least Privilege, you should only request the permissions your application actually needs.


Maesn manages the full OAuth token lifecycle for Sage Active

This includes token refresh before expiry and secure per-tenant storage of access and refresh tokens. You register your app credentials once; Maesn handles everything else.


Sage Active API Integrations Require Cursor-Based Pagination - Data Must Be Traversed Sequentially

Sage Active uses cursor-based pagination, which is standard in GraphQL implementations. This differs fundamentally from the offset-based pagination used by most REST APIs.

In offset-based pagination, you request a specific page: GET /contacts?page=5&limit=100. In cursor-based pagination, you cannot request page 5 directly. Instead:

  • You request the first N items using the first parameter

  • The response includes a pageInfo object with endCursor (a pointer to the last item in the result) and hasNextPage (a boolean indicating whether more data exists)

  • To get the next page, you pass the endCursor value as the after parameter in your next query

The key limitation: you cannot jump to a specific position in the dataset. To reach record 500 in a dataset of 1,000, you must traverse all preceding pages sequentially. For large datasets, this means more API calls and more complex state management in your sync logic.


Maesn Exposes Standard Offset-Based Pagination — Cursor Traversal Handled in the Backend

Maesn standardizes pagination across all supported systems by exposing offset-based pagination in its unified REST API. When you request a list of contacts or invoices from Sage Active through Maesn, you work with standard page and limit parameters. Maesn handles the cursor-based traversal against the Sage Active GraphQL API entirely in the backend.


Creating Objects Requires Pre-Resolved Internal IDs — Human-Readable Values Are Not Accepted

When creating objects in Sage Active — such as items, invoices, or contacts — you cannot pass human-readable values for reference fields. Fields like unitOfMeasurementId require the internal numeric ID that Sage Active uses to identify that unit of measurement. Sending a readable string like "KILOGRAM" will result in a validation error.

This means you need additional API calls before any create operation: fetch the available reference data, cache the results, and build a mapping from readable values to internal IDs. For a multi-tenant product, this reference resolution must be done per tenant, since ID values are not universal.

This pattern applies to multiple object types across the Sage Active API — units of measurement are one example, but the same principle extends to other reference data such as tax codes, payment terms, and account references. Every write operation that involves a reference field requires prior resolution of the correct internal ID.


Maesn's Common Data Model Handles ID Resolution — No Internal Reference Lookups Required

Maesn removes most of this ID resolution complexity. You work with readable, semantic values in Maesn's unified data model; Maesn handles the internal ID lookup, caching, and mapping against the Sage Active API per tenant. You focus on your use case logic — Maesn handles the reference data layer.


Sage Active Covers France, Spain, and Germany — Each With Its Own Compliance Context

Sage Active is currently available in three markets: France, Spain, and Germany. Each market has its own tax regulations, VAT structure, and compliance requirements that affect how financial data is structured and reported. For SaaS teams serving customers across these markets, this means per-country differences in VAT rates, invoice requirements, and account structures — even though the underlying API is the same.

France, Spain, and Germany are all subject to the EU's upcoming mandatory e-invoicing rollout, with national timelines and formats varying per country. If your product creates or processes invoices for customers in these markets, planning for structured e-invoicing is increasingly relevant.


Maesn Handles Country-Specific Compliance — One Integration for France, Spain, and Germany

Maesn's integration configuration layer and common data model handle country-specific differences for Sage Active tenants. If you have specific compliance requirements for French, Spanish, or German customers, reach out to the Maesn team to discuss your use case.


Why Teams Use Maesn for Sage Active Integration

Building a direct integration with Sage Active means working with GraphQL and Hot Chocolate conventions, handling the X-OrganizationId selection flow per tenant, managing OAuth tokens and scopes, implementing cursor-based pagination traversal for all collection endpoints, and resolving internal IDs before every write operation — all before shipping your first feature.

Maesn abstracts this into a single unified REST API. You integrate once to Maesn and your product automatically works with Sage Active and every other accounting system in the Maesn portfolio, without system-specific branches in your code.

Sage Active API Integration with Maesn Unified API
Sage Active API Integration with Maesn Unified API

 
 

Browse more

DATEV API visual
Your SaaS
Maesn's magic
Your integrations

Start your API integration

Grow faster with Maesn by integrating your SaaS to DATEV and more with one unified API.

paywise.png
yokoy.png
hibob.png
Trusted by winning dev teams
bottom of page