Multi-entity ERP behavior

Each ERP handles multi-entity differently — how it structures entities, what GL data it returns at the "parent" level, whether consolidation is native or manual, and how intercompany transactions work. This guide documents those differences so you can design the right data pipeline for each ERP you support.

For integration-level guidance (which headers to set, which fields to filter), see the Multi-Entity Accounting guide.


GL scope at a glance

ERPParent GL = sum of all subsidiaries?Separate GL per entity?How to read one entity
NetSuite OneWorldYes — one GL across all subsidiariesNo separate GL per subFilter by subsidiary_id
Sage IntacctNo — each entity has own GL; top level has own GL (not a roll-up)Yesx-apideck-company-id selects entity
WorkdayYes — journals span all companiesNo separate GL per companyFilter by company_id
AcumaticaYes — all branches in one GLNo separate GL per branchFilter by branch field
Dynamics 365 BCNo — each company has own GLYesx-apideck-company-id selects company
XeroNo — each org has own GLYesx-apideck-company-id selects tenant
QuickBooks OnlineNo — each realm has own GLYesSeparate connection per realm
Exact OnlineNo — each division has own GLYesx-apideck-company-id selects division
Intuit Enterprise SuiteNo — each entity has own GLYesSeparate connection per entity
MYOBNo — each company has own GLYesSeparate connection per company

Quick comparison

AspectNetSuite OneWorldSage IntacctAcumaticaDynamics 365 BCXero
GL query at "parent"All subsidiaries mixedTop-level entity's own data onlyAll branches mixed; companies isolatedOne company per requestOne org per request
Entity isolationNo — filter by subsidiary_idYes — session-scoped per entityBranches: no. Companies: yesYesYes
Chart of accountsCan diverge per subsidiaryShared by defaultShared within tenantPer companyPer org
Native consolidationYes (batch)Yes (Global Consolidation module)Branches: real-time. Companies: batchNo native cross-companyNo
IntercompanyManual or scriptedAutomatic due-to/due-fromInter-branch: automatic. Inter-company: semi-automaticManualN/A
Base currencyCan differ per subsidiaryCan differ per entityMust be same within tenantPer companyPer org
Apideck mechanismFilter subsidiary_id on responsex-apideck-company-id headerFilter BranchID on response; separate connections for companiesx-apideck-company-id headerx-apideck-company-id header

NetSuite OneWorld

NetSuite exposes all subsidiaries through a single connection. GL list endpoints return records across all subsidiaries in one response — your app must filter by subsidiary_id.

NetSuite OneWorld connection
  │
  ├── GET /accounting/journal-entries
  │   └── Returns entries across ALL subsidiaries
  │       ├── Entry 1  subsidiary_id: "us-corp"   amount: $5,000
  │       ├── Entry 2  subsidiary_id: "uk-ltd"    amount: £3,200
  │       ├── Entry 3  subsidiary_id: "us-corp"   amount: $1,500
  │       └── Entry 4  subsidiary_id: "uk-ltd"    amount: £800
  │
  └── Your app must filter by subsidiary_id
      if you only need one entity's data

What the "parent" GL contains

There is no separate "parent-only" ledger in NetSuite OneWorld. The parent is the sum of the parts — all subsidiary transactions come back in one response. To get one subsidiary's data, filter by subsidiary_id. To get a consolidated view, you already have all the data but must still handle intercompany elimination and currency conversion.

Field quirks

On reads, NetSuite frequently populates company_id from the same subsidiary metadata. On some resources (vendors, purchase orders), company_id and subsidiary_id appear with the same value. On others, only company_id is set while subsidiary_id is empty. Checks are an exception: company_id may reflect a different NetSuite field than line-level subsidiary_id — do not assume they always match.

Chart of accounts

Can diverge per subsidiary. When building consolidation, you may need an account mapping layer if subsidiaries use different account numbers or structures.

Consolidation

NetSuite has a native consolidation process (batch), but from Apideck's perspective the data already arrives co-mingled. Your consolidation workflow:

  1. You already have all data in one response
  2. Group by subsidiary_id
  3. Eliminate intercompany balances
  4. Convert currencies to reporting currency

Intercompany

Manual or scripted — NetSuite does not automatically generate due-to/due-from entries. Intercompany journal entries must be created explicitly.


Sage Intacct

Sage Intacct uses fully isolated entity books. Each child entity has its own GL, trial balance, AP/AR sub-ledgers, close schedule, bank accounts, and optionally its own functional currency. The top-level entity is not a consolidated view.

Sage Intacct multi-entity structure
  │
  ├── Top-Level Entity (has its OWN GL — not a roll-up)
  │   ├── Holds shared config: chart of accounts, vendors, customers
  │   ├── Can hold corporate transactions (overhead, eliminations)
  │   └── Querying GL here returns ONLY top-level transactions
  │
  ├── Child Entity A (isolated GL, own trial balance)
  │   ├── GET /accounting/journal-entries
  │   │   with x-apideck-company-id: entity-a
  │   │   └── Returns only Entity A's journal entries
  │   └── Own close schedule, own bank accounts
  │
  └── Child Entity B (isolated GL, different currency possible)
      └── GET /accounting/journal-entries
          with x-apideck-company-id: entity-b
          └── Returns only Entity B's journal entries

What the "parent" GL contains

The top-level entity has its own GL — it is not a consolidated roll-up of child entities. Querying GL at the top level returns only the top-level entity's own transactions (typically corporate overhead, intercompany elimination entries). To see a child entity's data, you must scope to that entity via x-apideck-company-id.

API session scoping

In the Intacct API, entity selection happens via locationid in the session. Apideck maps x-apideck-company-id to this session scoping. Each entity-scoped session returns that entity's private data plus shared top-level config.

Chart of accounts

Shared by default across all entities. Account IDs are consistent everywhere. This is a significant advantage for consolidation — no account mapping layer is needed.

Consolidation

Intacct has a native Global Consolidation module that generates elimination entries and currency translation adjustments. However, consolidation data is only available after running the consolidation process — it is not real-time in the transactional API.

Your consolidation workflow via Apideck:

  1. List entities via GET /accounting/companies
  2. Iterate each entity via x-apideck-company-id
  3. Merge records (shared COA makes this straightforward)
  4. Eliminate intercompany balances
  5. Convert currencies to reporting currency

Intercompany

Automatic due-to/due-from entries when transactions span entities. When a journal entry in one entity affects another, Intacct creates the offsetting intercompany entries automatically.

Entity vs location

AspectEntityLocation
Own GL booksYesNo (shares entity's GL)
Own trial balanceYesNo (filtered view)
Own currencyYes (optional)No
API session scopeYes (x-apideck-company-id)No (dimension filter)

Acumatica

Acumatica has a bimodal architecture with three levels: Tenant > Company > Branch. GL behavior depends on which level you are working with.

Acumatica multi-entity structure
  │
  ├── Tenant (= Apideck connection)
  │   │
  │   ├── Company A (own actual GL ledger)
  │   │   ├── Branch A1 ─┐
  │   │   ├── Branch A2 ──┤── All share Company A's GL
  │   │   └── Branch A3 ─┘   BranchID on each record
  │   │
  │   └── Company B (own actual GL ledger — isolated from A)
  │       ├── Branch B1 ─┐
  │       └── Branch B2 ──┘── Share Company B's GL
  │
  └── Separate Tenant (= separate Apideck connection)
      └── Company C (completely isolated — different COA possible)

Branches (within a company)

All branches share a single GL ledger. When you query journal entries, you get all branches mixed together — filter by BranchID to isolate one branch. A query without branch filtering is already a consolidated view of all branches.

Companies (within the same tenant)

Each company has its own isolated actual ledger. Companies within the same tenant share the chart of accounts, base currency, and master data (customers, vendors, items). To get data from a different company, you need a separate connection or API session.

Companies in separate tenants

Fully isolated — can have different charts of accounts, different base currencies, and share no data.

What the "parent" GL contains

There is no "parent" concept in the NetSuite or Intacct sense. The question is which level you're querying:

  • Within a company: you get all branches' data mixed (the shared GL). This is already consolidated at the branch level.
  • Across companies: each company is isolated. You must iterate.

Chart of accounts

All companies within the same tenant must share the same COA structure and base currency. This makes cross-company consolidation within a tenant straightforward. Companies in separate tenants can have different COAs and require account mapping.

Branch configuration modes

Acumatica companies can be configured with three branch modes:

ModeP&LBalance sheetInter-branch balancing
Without branchesSingleSingleN/A
Branches not requiring balancingPer branchSharedNo automatic entries
Branches requiring balancingPer branchPer branchAutomatic due-to/due-from

All three modes share one GL ledger — the difference is whether inter-branch balancing entries are auto-generated.

Consolidation

  • Within a company (branches): Real-time — branches already share one GL. No consolidation process needed.
  • Across companies (same tenant): Batch consolidation process. A "consolidation company" pulls trial balances from source companies, applies account mapping and currency translation.
  • Across tenants: Formal GL consolidation with account mapping between different COAs.

Intercompany

  • Inter-branch: Automatic due-to/due-from entries when the company is configured with "branches requiring balancing."
  • Inter-company: Semi-automatic — transactions in one company can generate matching documents in another (e.g., AP bill in Company A creates AR invoice in Company B), but elimination entries are largely manual.

Dynamics 365 Business Central

Each company in Dynamics 365 BC is fully isolated. The company ID is part of the URL path for every API call.

What the "parent" GL contains

There is no parent/child relationship between companies. Each company is independent with its own GL, chart of accounts, and configuration. Apideck maps x-apideck-company-id to the company URL path.

Chart of accounts

Per company — can differ between companies within the same environment.

Consolidation

No native cross-company consolidation. To build a consolidated view, iterate all companies via x-apideck-company-id and merge in your application.

Intercompany

Manual — intercompany transactions must be posted in each company independently.


Xero

Each Xero organisation is fully isolated. One OAuth connection can grant access to multiple organisations, and x-apideck-company-id (mapped to Xero-Tenant-Id) switches between them.

What the "parent" GL contains

There is no parent/child relationship. Each organisation has independent books. A holding company organisation has its own P&L and balance sheet — it does not automatically consolidate subsidiary organisations.

Chart of accounts

Per organisation — can differ completely.

Consolidation

No native consolidation. Iterate all organisations via x-apideck-company-id and merge in your application. Account mapping is typically needed since organisations maintain independent COAs.

Dimensions

Xero has no separate department/location/subsidiary resources. Customers use up to two tracking categories to represent dimensions like "department" and "region."


Consolidation strategy by ERP pattern

Roll-up ERP (NetSuite, Workday)
  ┌──────────────────────────────────────────┐
  │  Data arrives mixed across all entities  │
  │                                          │
  │  To show one entity:                     │
  │  → Filter by subsidiary_id              │
  │                                          │
  │  To consolidate:                         │
  │  1. You already have all data            │
  │  2. Group by subsidiary/entity field     │
  │  3. Eliminate intercompany               │
  │  4. Convert currencies                   │
  └──────────────────────────────────────────┘

  Isolated ERP (Xero, QBO, Dynamics BC)
  ┌──────────────────────────────────────────┐
  │  Each API call returns one entity only   │
  │                                          │
  │  To show one entity:                     │
  │  → Already scoped — just read           │
  │                                          │
  │  To consolidate:                         │
  │  1. Iterate all entities                 │
  │  2. Tag each record with source entity   │
  │  3. Map COA (may differ per entity)      │
  │  4. Eliminate intercompany               │
  │  5. Convert currencies                   │
  └──────────────────────────────────────────┘

  Isolated with shared COA (Sage Intacct)
  ┌──────────────────────────────────────────┐
  │  Each entity isolated via session scope  │
  │                                          │
  │  To show one entity:                     │
  │  → Already scoped — just read           │
  │                                          │
  │  To consolidate:                         │
  │  1. Iterate all entities via             │
  │     x-apideck-company-id                 │
  │  2. Merge (shared COA — no mapping)      │
  │  3. Eliminate intercompany               │
  │  4. Convert currencies                   │
  └──────────────────────────────────────────┘

  Bimodal (Acumatica)
  ┌──────────────────────────────────────────┐
  │  Branches: shared GL (roll-up)           │
  │  Companies: isolated (separate sessions) │
  │                                          │
  │  To show one branch:                     │
  │  → Filter by BranchID                   │
  │                                          │
  │  To consolidate branches:                │
  │  → Already consolidated (shared GL)     │
  │  → Shared COA — no mapping needed       │
  │                                          │
  │  To consolidate across companies:        │
  │  1. Iterate all connections              │
  │  2. Shared COA within tenant — no        │
  │     mapping. Across tenants: map COA.    │
  │  3. Eliminate intercompany               │
  │  4. Convert currencies (cross-tenant)    │
  └──────────────────────────────────────────┘