Tracking Dimensions: Departments, Locations, Subsidiaries & Tracking Categories

Tracking dimensions allow you to categorize and segment accounting transactions for reporting and analysis. This guide explains how to use departments, locations, subsidiaries, and tracking categories across different accounting connectors.

Overview

Apideck's Accounting API supports four tracking dimensions:

DimensionPurposeExample Use Cases
DepartmentOrganizational unit or cost centerMarketing, Sales, Engineering, Operations
LocationPhysical or logical placeLondon Office, New York, Online Store
SubsidiaryLegal entity in multi-company setupUS Holdings Inc, UK Ltd, APAC Pty
Tracking CategoryFlexible custom tagsProject Alpha, Grant #12345, Product Line A

These dimensions enable powerful reporting capabilities:

  • P&L by department (cost center analysis)
  • Balance sheet by subsidiary (consolidated reporting)
  • Revenue by location (regional performance)
  • Expenses by tracking category (project costing)

Supported Resources

Transactional Resources

Tracking dimensions can be applied to these transactional resources:

Resourcedepartment_idlocation_idsubsidiary_idtracking_categories
Invoices
Bills
Credit Notes
Expenses
Purchase Orders
Journal Entries
Payments
Bill Payments

Line Item Support

Most transactional resources support tracking at both the header and line item level:

{
  "department_id": "dept-001",
  "location_id": "loc-001",
  "line_items": [
    {
      "description": "Consulting services",
      "department_id": "dept-002",
      "location_id": "loc-002",
      "tracking_categories": [
        { "id": "cat-001", "name": "Project Alpha" }
      ]
    }
  ]
}

Priority: Line item values override header values for that specific line.

Dimension Resources

You can manage tracking dimensions through dedicated endpoints:

EndpointDescription
GET /accounting/departmentsList all departments
GET /accounting/locationsList all locations
GET /accounting/subsidiariesList all subsidiaries
GET /accounting/tracking-categoriesList all tracking categories

Each endpoint supports standard CRUD operations (list, get, create, update, delete) where the connector supports them.

Using Tracking Dimensions

Creating a Transaction with Tracking

curl -X POST "https://unify.apideck.com/accounting/invoices" \
  -H "Authorization: Bearer {api_key}" \
  -H "x-apideck-consumer-id: {consumer_id}" \
  -H "x-apideck-app-id: {app_id}" \
  -H "x-apideck-service-id: quickbooks" \
  -H "Content-Type: application/json" \
  -d '{
    "customer_id": "cust-123",
    "department_id": "dept-sales",
    "location_id": "loc-nyc",
    "tracking_categories": [
      { "id": "class-enterprise" }
    ],
    "line_items": [
      {
        "description": "Professional Services",
        "quantity": 10,
        "unit_price": 150,
        "department_id": "dept-consulting",
        "tracking_categories": [
          { "id": "project-alpha" }
        ]
      }
    ]
  }'

Filtering Reports by Location

Balance Sheet and Profit & Loss reports can be filtered by location:

# Balance Sheet filtered by location
curl "https://unify.apideck.com/accounting/balance-sheet?filter[location_id]=loc-nyc" \
  -H "Authorization: Bearer {api_key}" \
  -H "x-apideck-consumer-id: {consumer_id}" \
  -H "x-apideck-app-id: {app_id}" \
  -H "x-apideck-service-id: netsuite"

# Profit & Loss filtered by location
curl "https://unify.apideck.com/accounting/profit-and-loss?filter[location_id]=loc-nyc" \
  -H "Authorization: Bearer {api_key}" \
  -H "x-apideck-consumer-id: {consumer_id}" \
  -H "x-apideck-app-id: {app_id}" \
  -H "x-apideck-service-id: netsuite"

Listing Available Tracking Categories

curl "https://unify.apideck.com/accounting/tracking-categories" \
  -H "Authorization: Bearer {api_key}" \
  -H "x-apideck-consumer-id: {consumer_id}" \
  -H "x-apideck-app-id: {app_id}" \
  -H "x-apideck-service-id: xero"

Response:

{
  "data": [
    {
      "id": "tc-001",
      "name": "Region",
      "status": "active",
      "items": [
        { "id": "tc-001-a", "name": "North America" },
        { "id": "tc-001-b", "name": "Europe" },
        { "id": "tc-001-c", "name": "Asia Pacific" }
      ]
    },
    {
      "id": "tc-002",
      "name": "Department",
      "status": "active",
      "items": [
        { "id": "tc-002-a", "name": "Sales" },
        { "id": "tc-002-b", "name": "Marketing" }
      ]
    }
  ]
}

Connector Support

Not all connectors support all tracking dimensions. Here's what's available:

Full Support (All 4 Dimensions)

ConnectorDepartmentsLocationsSubsidiariesTracking Categories
NetSuite
Sage Intacct

Partial Support (2-3 Dimensions)

ConnectorDepartmentsLocationsSubsidiariesTracking Categories
QuickBooks Online
Workday
Dynamics 365 BC

Limited Support (1 Dimension)

ConnectorDepartmentsLocationsSubsidiariesTracking Categories
Xero
MYOB
Zoho Books
FreeAgent
Freshbooks

Connector-Specific Behavior

QuickBooks Online

QuickBooks uses "Classes" for tracking categories and has both Departments and Locations:

{
  "department_id": "58",
  "location_id": "1",
  "tracking_categories": [
    { "id": "5000000000000026437", "name": "Enterprise" }
  ]
}

Note: QuickBooks' "Department" is often used for location-like tracking (regions, branches). Check your customer's QuickBooks configuration to understand how they use these fields.

Requirement: The QuickBooks account must have "Track locations" and "Track classes" enabled in Settings > Account and Settings > Advanced.

Scope required: com.intuit.quickbooks.accounting

For detailed setup instructions, see the QuickBooks connector guide.

Xero

Xero uses Tracking Categories for all dimensional tracking. Each organization can have up to 2 tracking categories, each with multiple options:

{
  "tracking_categories": [
    { "id": "region-uuid", "name": "North America" },
    { "id": "dept-uuid", "name": "Sales" }
  ]
}

Limitation: Only 2 tracking categories per Xero organization. Plan category usage carefully.

Common Pattern: Many Xero users create one tracking category for "Department" and one for "Region" to simulate the department/location split.

Line Items: Tracking can be assigned at both the transaction header and line item level for granular reporting.

NetSuite

NetSuite (OneWorld edition) has full support for all dimensions:

{
  "department_id": "3",
  "location_id": "1",
  "subsidiary_id": "2",
  "tracking_categories": [
    { "id": "1", "name": "Class A" }
  ]
}

Requirement: For NetSuite OneWorld, subsidiary_id is often required on transactions. Transactions without a valid subsidiary will be rejected.

Hierarchy: Departments, locations, and subsidiaries can be hierarchical (parent/child). Use the parent_id field when creating nested structures.

Custom Segments: NetSuite supports additional custom segments beyond the standard four dimensions. These can be accessed via pass_through if needed.

Sage Intacct

Sage Intacct uses "Entities" for subsidiaries and supports up to 8 custom dimensions:

{
  "department_id": "SALES",
  "location_id": "US-WEST",
  "subsidiary_id": "ENTITY-001",
  "tracking_categories": [
    { "id": "PROJECT-123", "name": "Project Alpha" }
  ]
}

Requirement: location_id (maps to LOCATIONID) is often required for multi-entity setups.

Custom Dimensions: Sage supports user-defined dimensions beyond the standard four. These are accessible via pass_through if needed.

Note: Sage Intacct was historically mapped to use subsidiaries for location data. Dedicated locations support was added later.

Best Practices

1. Discover Available Dimensions First

Before creating transactions with tracking, list available dimensions:

# Get departments
curl "https://unify.apideck.com/accounting/departments" \
  -H "Authorization: Bearer {api_key}" \
  -H "x-apideck-consumer-id: {consumer_id}" \
  -H "x-apideck-app-id: {app_id}" \
  -H "x-apideck-service-id: {service_id}"

# Get tracking categories
curl "https://unify.apideck.com/accounting/tracking-categories" \
  -H "Authorization: Bearer {api_key}" \
  -H "x-apideck-consumer-id: {consumer_id}" \
  -H "x-apideck-app-id: {app_id}" \
  -H "x-apideck-service-id: {service_id}"

This ensures you use valid IDs and understand the customer's tracking structure.

2. Handle Missing Dimension Support Gracefully

Not all connectors support all dimensions. Your integration should check support before including fields:

const invoice = {
  customer_id: customerId,
  line_items: lineItems
};

// Only include tracking if the connector supports it
if (connectorSupports('departments')) {
  invoice.department_id = departmentId;
}

if (connectorSupports('tracking_categories')) {
  invoice.tracking_categories = categories;
}

3. Use Line Items for Mixed Tracking

When a single invoice spans multiple departments or projects:

{
  "customer_id": "cust-123",
  "line_items": [
    {
      "description": "Sales consulting",
      "department_id": "sales",
      "tracking_categories": [{ "id": "project-a" }]
    },
    {
      "description": "Technical implementation",
      "department_id": "engineering",
      "tracking_categories": [{ "id": "project-a" }]
    }
  ]
}

4. Validate Subsidiary Requirements

For enterprise connectors (NetSuite, Sage), check if subsidiary is required:

// NetSuite OneWorld requires subsidiary
if (serviceId === 'netsuite') {
  const subsidiaries = await apideck.accounting.subsidiaries.list();
  if (subsidiaries.data.length > 1 && !transaction.subsidiary_id) {
    throw new Error('subsidiary_id is required for NetSuite OneWorld');
  }
}

5. Cache Dimension Lists

Tracking dimensions change infrequently. Cache the results of list calls:

// Cache departments for 1 hour
const departments = await cache.getOrSet(
  `departments:${consumerId}:${serviceId}`,
  () => apideck.accounting.departments.list(),
  { ttl: 3600 }
);

Troubleshooting

"Invalid department_id" Error

Cause: The department ID doesn't exist or isn't active in the connected accounting system.

Solution:

  1. List departments to get valid IDs: GET /accounting/departments
  2. Verify the department is active (not archived)
  3. Check if department is valid for the specified subsidiary/location

"tracking_categories not supported" Error

Cause: The connector doesn't support tracking categories.

Solution: Check the connector support matrix above. Consider using pass_through for connector-specific fields.

Subsidiary Required Error (NetSuite/Sage)

Cause: Multi-entity systems often require subsidiary context.

Solution:

  1. List subsidiaries: GET /accounting/subsidiaries
  2. Include subsidiary_id on the transaction
  3. Ensure the subsidiary is valid for the current user's permissions

Xero "Maximum tracking categories exceeded"

Cause: Xero only allows 2 tracking categories per organization.

Solution: Xero's limit is organization-wide, not per-transaction. Work with your customer to:

  1. Consolidate tracking needs into 2 categories
  2. Use tracking category "options" for additional granularity within each category

Enhancement Options

If you need tracking support that isn't currently available in the unified API:

  1. Pass-through: Use pass_through to send connector-specific fields directly to the downstream API
  2. Proxy API: For complex platform-specific functionality, use the Proxy API to make direct calls
  3. Request Enhancement: Contact us to request unified API extensions for your use case