Multi-entity accounting and tracking dimensions
This guide explains how Apideck's Accounting API handles multiple companies or legal entities and tracking dimensions (departments, locations, subsidiaries, and custom categories). Understanding both helps you build integrations that match how each accounting platform works.
For an in-depth look at how specific ERPs (NetSuite, Sage Intacct, Acumatica, etc.) structure entities, return GL data, and handle consolidation natively, see the Multi-Entity ERP Behavior guide.
Two layers: data scope vs tagging
Layer 1 — Data boundary (which entity's books?)
This answers: When I list ledger accounts, invoices, or journal entries, whose data am I seeing?
For connectors that support per-request company switching, you choose the entity by sending the x-apideck-company-id HTTP header on Accounting API requests. The value is an identifier returned by GET /accounting/companies for that connection.
If you omit the header, requests typically use the default company stored on the connection (for example, the organisation or entity chosen during setup or OAuth).
Layer 2 — Tracking dimensions (how is this transaction segmented?)
This answers: How should this invoice or line appear in management reporting—by department, location, legal entity tag, or custom category?
Common fields on transaction headers and line items:
| Concept | API fields (typical) | Role |
|---|---|---|
| Department | department_id | Cost center / org unit |
| Location | location_id | Site, region, or logical place |
| Subsidiary | subsidiary_id | Legal entity tag on the transaction |
| Custom segments | tracking_categories[] | Classes, projects, grants—platform-dependent |
Note
For most connectors, department, location, and tracking categories are tags for reporting. They do not by themselves switch which company's list endpoints return.
Subsidiary is special: it often acts as a dimension on the transaction, and on some platforms it is tightly tied to which legal entity owns that transaction. It is still distinct from the x-apideck-company-id header, which controls read scope where that feature is supported.
How the two layers work together
When both apply, you might scope reads to Company A with the header, while line items still carry their own department_id, location_id, or tracking_categories. Line-level dimension values usually override header-level values for that line—useful when one document splits costs across teams or projects.
Switching companies with x-apideck-company-id
What to do
Step 1 — List available companies:
Step 2 — Use a company ID on subsequent requests:
This returns invoices for Acme UK Ltd. only. Same connection, same consumer—just a different company context.
Note
Connection metadata may also expose a default company identifier (for example in connection metadata after setup). The header overrides that default when the connector supports multi-company switching.
Virtual Webhooks limitation
Virtual Webhooks currently only sync data from the default company configured during connection setup. The x-apideck-company-id header is not supported for webhook subscriptions. If you need events from multiple companies, either create separate connections per company or poll the API with the header on a schedule.
Which pattern does your connector use?
Connectors that support per-request company switching
| Connector | What "company" represents | Downstream mechanism |
|---|---|---|
| Xero | Organisation | Xero-Tenant-Id header |
| Sage Intacct | Entity | Session follows selected entity |
| Sage Business Cloud | Business | Business context switch |
| Dynamics 365 BC | Company | Company in URL path |
| Exact Online | Division | Division-based routing |
Exact Online variants
Choose the service_id that matches your product—exact-online, exact-online-nl, or exact-online-uk. All three use the same division-based pattern for GET /accounting/companies and x-apideck-company-id.
Always confirm current behavior in the Apideck Accounting API reference for your connector; capabilities evolve.
Connectors that need one connection per company
Some integrations bind one OAuth token (or one company) to a single legal entity. In those cases x-apideck-company-id does not switch companies—you create one connection per company.
- QuickBooks Online — One company per connection (realm)
- MYOB — One company per connection
Other connectors (not in the header-switching table)
Many other accounting service_id values follow different rules:
| Pattern | What to expect | Examples |
|---|---|---|
| One ledger per connection | Use another Vault connection for another company | FreshBooks, Zoho Books, KashFlow, FreeAgent, Banqup, Visma Netvisor, Procountor, Access Financials |
| Entity on records | Entity may appear on payloads or query parameters | Campfire, Dualentry |
| Rich dimensions, scoped connection | One company per connection; branches are dimensions on records (all branches returned together — filter by BranchID) | Acumatica, MYOB-Acumatica |
| Enterprise dimensions | company_id / subsidiary_id / worktags carry entity meaning | Intuit Enterprise Suite, Workday |
For any connector, confirm multi-company flags, required fields, and resource coverage in the Accounting API reference and the connector's page on developers.apideck.com/connectors.
Xero: multiple organisations vs app partnership
These are two separate ideas:
If you are scaling to many end-customer connections, plan for Xero's commercial and certification requirements in addition to multi-org switching. See Xero's App Partner program, Apideck's Xero connector documentation, and Xero API pricing and the App Partner Program.
Does the parent GL include subsidiaries? (Roll-up behavior)
A common question when integrating with multi-entity ERPs: when I read GL data at the parent level, do I get a roll-up of all subsidiaries, or just the parent's own ledger?
This depends entirely on how the downstream ERP returns data. Apideck does not aggregate or consolidate — it returns what the ERP gives.
What this means for your integration:
| If the ERP... | Then to show one entity's GL... | And to show a consolidated GL... |
|---|---|---|
| Rolls up (NetSuite, Workday) | Filter the response by subsidiary_id or equivalent | Use the full response, then eliminate intercompany + convert currencies |
| Rolls up branches, isolates companies (Acumatica) | Filter by BranchID; separate connections for separate companies | Within a company: use the full response. Across companies: iterate connections and merge |
| Isolates (Xero, QBO, Exact, Dynamics BC, Sage Intacct) | Just read — the response is already scoped | Iterate all entities, merge, eliminate intercompany + convert currencies |
Note
For details on how each ERP structures entities internally, what the "parent" GL actually contains, and how native consolidation works, see the Multi-Entity ERP Behavior guide.
Tracking dimensions — quick reference
Master data endpoints
Where dimensions appear on transactions
Support varies by resource and by connector. At the unified API level, several resources accept department_id, location_id, subsidiary_id, and/or tracking_categories on the header and/or line items—not always all four on every resource.
Typical patterns by resource:
| Resource | Header dimensions | Line-item dimensions |
|---|---|---|
| Invoices & bills | department, location, tracking categories | All four including subsidiary |
| Journal entries | Varies | Primarily on lines |
| Credit notes | department, location | Often fewer subsidiary fields than invoices |
Refer to the request body schema for each operation in the API reference for the exact combination.
How popular platforms map to unified fields
Note
Xero has no separate department/location/subsidiary resources. Many customers use their two tracking categories to represent "department" and "region." Workday uses worktags for most dimensions—company_id and subsidiary_id behave differently there.
company_id vs subsidiary_id on transaction records
The unified API exposes both company_id and subsidiary_id in places, but connectors treat them differently:
Note
For legal-entity tagging on create/update, prefer subsidiary_id unless documentation for your connector explicitly requires company_id.
Frequently asked questions
How do I read GL data for one specific entity?
What is the difference between x-apideck-company-id and subsidiary_id?
They may align for a given document (same entity everywhere) or differ in advanced cases (for example intercompany entries where lines reference different entities).
Should I use company_id or subsidiary_id on create/update payloads?
Prefer subsidiary_id for legal-entity tagging on transactions.
| Connector | Recommendation |
|---|---|
| NetSuite | company_id often mirrors subsidiary_id (same value). Pick one consistent field after checking the response shape per resource. |
| Workday | Not interchangeable — use what the resource schema specifies. |
| Others | company_id is easily confused with connection settings or the header. Default to subsidiary_id. |
How do I consolidate GL data across entities for one customer?
This is application-level logic — Apideck provides the per-entity data, your platform handles mapping, conversion, and elimination.
Can one API call represent multiple legal entities?
That is intercompany or cross-entity posting. It is only possible where the downstream system allows it. NetSuite and Workday are common examples; many SMB-oriented systems isolate entities per connection or per organisation.
Consolidating GL data across entities
A common use case is reading GL data from multiple legal entities and merging it into a single view — for consolidated reporting, intercompany elimination, or multi-entity dashboards. This section explains how entity data maps to Apideck's consumer model and what to consider when designing consolidation logic.
How entities map to consumers and connections
In Apideck, a consumer represents your customer. One consumer can have multiple connections, and some connections give access to multiple companies. Understanding this hierarchy is key to consolidation:
All five entities belong to one consumer (acme-corp). To build a consolidated view you need to iterate across all of them — some via the header, some via separate connections.
Reading GL data across all entities
Example: iterating entities for one consumer
Header-switching connector (e.g. Xero):
Connection-per-company connector (e.g. QuickBooks):
Key considerations for consolidation
Charts of accounts differ per entity
Each legal entity may have its own chart of accounts with different account numbers, names, and structures. Your consolidation logic needs a mapping layer:
See the Ledger Account Mapping guide for how to build a mapping interface.
Note
Some ERPs share the chart of accounts across all entities (Sage Intacct, Acumatica within a tenant), making consolidation simpler — no mapping needed. See the ERP Behavior guide for specifics.
Currency handling
Multi-entity setups often span currencies. The Accounting API returns amounts in each entity's base currency. Your consolidation must:
- Identify each entity's base currency (from company or ledger account metadata)
- Apply exchange rates to convert to your reporting currency
- Handle exchange rate differences as a separate consolidation line
Intercompany elimination
When entities transact with each other (e.g. Acme US invoices Acme UK), those balances appear in both entities' books. For a true consolidated view, you need to:
- Identify intercompany transactions (by counterparty, tracking category, or a naming convention)
- Eliminate matching receivables/payables so they do not double-count
Note
Apideck does not perform consolidation, currency conversion, or intercompany elimination — these are application-level responsibilities. The API provides the per-entity data you need to build these workflows.
Current limitations (good to plan for)
- NetSuite — List endpoints may aggregate across subsidiaries; do not assume header-based scoping behaves like Xero or Sage Intacct.
company_id/subsidiary_idduplication varies by resource. company_idvssubsidiary_id— Redundant same-value pairs are primarily a NetSuite quirk. Workday intentionally uses both fields differently. Most SMB connectors scope company via connection or headers, not both body fields.- Sage Intacct — Each entity is isolated; the top-level entity is not a consolidated roll-up.
company_idin settings is for auth/session, not dimension tagging. - Acumatica — Branches share one GL (roll-up), but separate companies are isolated. All companies within a tenant share the same COA and base currency.
- Connector matrix — Not every connector exposes all four dimension types or CRUD for every dimension resource; always check the connector's Accounting coverage.
- Connectors omitted from examples — Regional variants, niche ERPs, and new connectors may differ; treat the API reference as the source of truth when this guide does not name your
service_id.
Related resources
- Apideck Accounting API
- Multi-Entity ERP Behavior — deep dive into how each ERP structures entities, returns GL data, and handles consolidation
- Tracking dimensions in accounting integrations (blog)
If you need a connector-specific implementation checklist (auth, required fields, sandbox), use Apideck's connection and connector guides for that service in the developer portal.