# 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](/guides/multi-entity-accounting).

---

## GL scope at a glance

| ERP | Parent GL = sum of all subsidiaries? | Separate GL per entity? | How to read one entity |
|-----|--------------------------------------|-------------------------|------------------------|
| **NetSuite OneWorld** | Yes — one GL across all subsidiaries | No separate GL per sub | Filter by `subsidiary_id` |
| **Sage Intacct** | No — each entity has own GL; top level has own GL (not a roll-up) | Yes | `x-apideck-company-id` selects entity |
| **Workday** | Yes — journals span all companies | No separate GL per company | Filter by `company_id` |
| **Acumatica** | Yes — all branches in one GL | No separate GL per branch | Filter by branch field |
| **Dynamics 365 BC** | No — each company has own GL | Yes | `x-apideck-company-id` selects company |
| **Xero** | No — each org has own GL | Yes | `x-apideck-company-id` selects tenant |
| **QuickBooks Online** | No — each realm has own GL | Yes | Separate connection per realm |
| **Exact Online** | No — each division has own GL | Yes | `x-apideck-company-id` selects division |
| **Intuit Enterprise Suite** | No — each entity has own GL | Yes | Separate connection per entity |
| **MYOB** | No — each company has own GL | Yes | Separate connection per company |

---

## Quick comparison

| Aspect | NetSuite OneWorld | Sage Intacct | Acumatica | Dynamics 365 BC | Xero |
|--------|-------------------|--------------|-----------|-----------------|------|
| **GL query at "parent"** | All subsidiaries mixed | Top-level entity's own data only | All branches mixed; companies isolated | One company per request | One org per request |
| **Entity isolation** | No — filter by `subsidiary_id` | Yes — session-scoped per entity | Branches: no. Companies: yes | Yes | Yes |
| **Chart of accounts** | Can diverge per subsidiary | Shared by default | Shared within tenant | Per company | Per org |
| **Native consolidation** | Yes (batch) | Yes (Global Consolidation module) | Branches: real-time. Companies: batch | No native cross-company | No |
| **Intercompany** | Manual or scripted | Automatic due-to/due-from | Inter-branch: automatic. Inter-company: semi-automatic | Manual | N/A |
| **Base currency** | Can differ per subsidiary | Can differ per entity | Must be same within tenant | Per company | Per org |
| **Apideck mechanism** | Filter `subsidiary_id` on response | `x-apideck-company-id` header | Filter `BranchID` on response; separate connections for companies | `x-apideck-company-id` header | `x-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`.

```text
  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.

```text
  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.

> **Entity = location in the Intacct API**
>
Entities use `locationid` as their identifier — a historical naming convention. `locationid` in authentication context means "entity ID," not a physical location. Departments are always shared across entities; locations are entity-private.

### 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

| Aspect | Entity | Location |
|--------|--------|----------|
| Own GL books | Yes | No (shares entity's GL) |
| Own trial balance | Yes | No (filtered view) |
| Own currency | Yes (optional) | No |
| API session scope | Yes (`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.

```text
  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:

| Mode | P&L | Balance sheet | Inter-branch balancing |
|------|-----|---------------|------------------------|
| **Without branches** | Single | Single | N/A |
| **Branches not requiring balancing** | Per branch | Shared | No automatic entries |
| **Branches requiring balancing** | Per branch | Per branch | Automatic 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

```text
  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)    │
  └──────────────────────────────────────────┘
```

---

## Related resources

- [Multi-Entity Accounting guide](/guides/multi-entity-accounting) — integration-level guidance (headers, fields, patterns)
- [Apideck Accounting API](https://developers.apideck.com/apis/accounting)
- [Tracking dimensions in accounting integrations](https://www.apideck.com/blog/tracking-dimensions-in-accounting-integrations) (blog)
