> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nmbr.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Tagging & Journal Entry Tracking

> Allocate payroll line items across tags for accounting codes and journal entries

## Overview

Tags categorize and allocate payroll amounts across dimensions like department, project, or location, so costs can be tracked, split, and mapped to the right accounting codes automatically.

Each line item can carry a tag assignment, a structure that defines how that line item's dollar amount is distributed across one or more tags. Those allocations are used to determine accounting codes and detailed journal entries.

The typical flow looks like this:

1. **Define tag groups and tags**: create tag groups ("Department", "Project") and tags within them ("Engineering", "Sales", "Project Alpha")
2. **Assign tags**: set tag assignments on work assignments, generators, or individual line items to describe how costs are distributed
3. **Configure accounting code rules**: define rules that map tags to expense and liability accounting codes, resolved automatically during payroll calculation
4. **Generate journal entries**: tag allocations produce journal entry rows, one per allocation per tracking dimension, ready to export to the connected accounting system

## Concepts

* **[Tag groups and tags](#setting-up-tag-groups-and-tags)**: tag groups (e.g. "Department") and their values (e.g. "Engineering", "Sales")
* **[Tag assignments and allocations](#tag-assignments-and-allocations)**: how an amount is distributed across tags, with one or more allocations
* **[Assigning tags](#assigning-tags)**: tag assignments can be set on work assignments, generators, and line items, and [resolve down](#tag-resolution-and-precedence) to line items automatically
* **[Primary tag group](#primary-tag-group)**: the tag group whose accounting code rules are applied
* **[Accounting code rules](#accounting-code-rules)**: map tags to expense and liability accounting codes
* **[Derived tags on statutory withholdings](#derived-tags-on-statutory-withholdings)**: withholdings calculate their allocations from applicable remuneration
* **[Journal entry tracking dimensions](#journal-entry-tracking-dimensions)**: tag groups marked as tracking dimensions split journal entry rows with matched accounting codes

## Setting up tag groups and tags

Tag groups represent a category to track (e.g. "Department"). Tags are the values within that group (e.g. "Engineering", "Sales"). Each tag group belongs to a business entity. A tag group can also be marked as a journal entry tracking dimension; see [Journal entry tracking dimensions](#journal-entry-tracking-dimensions).

1. [Create a tag group](/api-reference/tag-groups/create-a-tag-group) for each category to track
2. [Create tags](/api-reference/tags/create-a-tag) within each group

Tag groups carry a few optional properties beyond their label:

* `color`: a hex colour (e.g. `#AABBCC`) used for display.
* `is_component_locked`: when `true`, the tags in this group cannot be edited through the embedded Component. They can still be managed through the API.
* `is_journal_entry_dimension`: see [Journal entry tracking dimensions](#journal-entry-tracking-dimensions).
* `archived_at`: archived tag groups (and tags) are excluded from index listings by default. Pass `include_archived=true` to include them.
* `is_deletable`: `false` while the group is the primary tag group, or while any of its tags are used in active allocations. The same applies to individual tags.

Tag groups and tags imported from an accounting integration carry the external identifiers (`integrations.xero`, `integrations.quickbooks`) that link them back to the source system, so they round-trip on re-sync. See [Importing tracking dimensions](/guides/accounting/integrations#importing-tracking-dimensions).

See the [Tag Groups](/api-reference/tag-groups/list-tag-groups) and [Tags](/api-reference/tags/list-tags) API reference for full details.

Tags can also carry per-side codes used to compose a formatted code on the Journal Entry report. See [Journal Entry Segment Templates](/guides/accounting/segment-templates).

## Tag assignments and allocations

A **tag assignment** describes how a line item's amount is distributed across tags. Tag assignments can be set on work assignments, generators, and line items. Each contains a `unit` that determines how allocations are measured, and one or more **tag allocations**, each with a set of tags and an allocation value.

#### Example tag assignment structure

```jsonc theme={null}
{
  "tag_assignment": {
    "unit": "percentage",
    "is_component_locked": false, // When true, the assignment will not be editable in the Component
    "tag_allocations": [
      {
        "tags": [
          "<engineering_tag_id>", // From department tag group
          "<project_alpha_tag_id>", // From project tag group
        ],
        "value": 60,
      },
      {
        "tags": [
          "<sales_tag_id>", // From department tag group
        ],
        "value": 40,
      },
    ],
  },
}
```

In this example, 60% of the amount is attributed to the Engineering department on Project Alpha, and 40% to the Sales department. Each allocation can combine tags from different tag groups, but only one tag per group is allowed in each allocation.

Allocations must sum to less than or equal to 100%. Any unallocated remainder falls back to the line item's own accounting codes. If no accounting code can be determined, the payroll is blocked until the allocation is resolved.

### Supported units by resource

The `unit` on a tag assignment controls how allocation values are interpreted. Available units depend on the resource type. Work assignments and generators only support `percentage` because they define default allocations before line item amounts are known. Only line items have concrete dollar values and hours that can be allocated directly.

| Resource                                                                                                  | Supported units                 |
| --------------------------------------------------------------------------------------------------------- | ------------------------------- |
| Work assignment                                                                                           | `percentage`                    |
| Pay rate, overtime rate, employee benefit, employer benefit, reimbursement, earning, allowance, deduction | `percentage`                    |
| Earning line item                                                                                         | `percentage`, `amount`, `hours` |
| Deduction, allowance, reimbursement, employee benefit, employer benefit line item                         | `percentage`, `amount`          |

## Assigning tags

### Work assignments

A `tag_assignment` on a work assignment defines the default allocation for all of that employee's line items. Work assignment tag assignments use the `percentage` unit. Each allocation defines what percentage of the total amount is attributed to those tags. Allocations must sum to less than or equal to 100%.

Pass `tag_assignment` when [creating](/api-reference/work-assignments/create-a-work-assignment) or [updating](/api-reference/work-assignments/update-a-work-assignment) a work assignment. Pass `null` to remove it. Use `?expand=tag_assignment` to include it in responses.

### Generators

In this guide, **generators** refers to the resources that produce line items: pay rates, overtime rates, earnings, deductions, allowances, reimbursements, and benefits.

Generators support a `tag_assignment` that overrides the work assignment's `tag_assignment` for line items created by that generator. Generator tag assignments use `percentage` allocations only.

Pass `tag_assignment` when creating or updating any generator resource.

### Line items

Line items support a `custom_tag_assignment` that overrides the managed tag assignment inherited from the work assignment or generator.

#### Allocation units

| Unit         | Description                         | Validation                                                             | Use case                                                  |
| ------------ | ----------------------------------- | ---------------------------------------------------------------------- | --------------------------------------------------------- |
| `percentage` | Split by percentage of total amount | Allocations must sum to less than or equal to 100%                     | Default, same as work assignments and generators          |
| `hours`      | Split by hours worked               | Allocations must sum to less than or equal to the line item's `hours`  | Earning line items only, attribute costs by hours per tag |
| `amount`     | Split by fixed dollar amounts       | Allocations must sum to less than or equal to the line item's `amount` | Attribute exact dollar amounts per tag                    |

Earning line items accept all three units. Non-earning line items (deductions, allowances, reimbursements, benefits) accept `percentage` and `amount` only.

#### Expanding tag assignments

Line items expose several expandable tag properties. Each returns the full tag assignment structure:

| Expand                   | Description                                                                                              |
| ------------------------ | -------------------------------------------------------------------------------------------------------- |
| `tag_assignment`         | The effective tag assignment: the `custom_tag_assignment` if set, otherwise the `managed_tag_assignment` |
| `custom_tag_assignment`  | Optional override: if set, these allocations are used instead of the managed value                       |
| `managed_tag_assignment` | The auto-inherited allocation from the work assignment or generator                                      |
| `tag_assignment_amounts` | The resolved dollar distribution for the line item                                                       |

### Patching a tag assignment

To adjust an existing tag assignment without resending the whole structure, pass `tag_assignment_patch` instead of `tag_assignment` on a work assignment or generator. The two keys are mutually exclusive.

| Field                   | Description                                                                                                                                |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `add_tags`              | Tag IDs to add to every existing allocation. Adding a tag replaces any other tag from the same tag group on that allocation.               |
| `remove_tags`           | Tag IDs to remove from every existing allocation. An allocation left with no tags is deleted; the distribution strategy decides its value. |
| `distribution_strategy` | Governs the value of allocations deleted by `remove_tags`. Defaults to `reallocate`.                                                       |

The `distribution_strategy` accepts:

* `reallocate`: spread the deleted value proportionally across the remaining allocations.
* `unallocated`: drop the value; the assignment's allocations will sum to less than before.
* `error`: refuse the patch if any allocation would be deleted.

## Tag resolution and precedence

Line items on draft payrolls automatically receive a `managed_tag_assignment`, resolved from the generator's `tag_assignment` if set, otherwise from the work assignment's `tag_assignment`.

If a `custom_tag_assignment` is set on the line item, it takes precedence over the managed value. The effective `tag_assignment` (used for accounting code matching and journal entries) is the `custom_tag_assignment` if one exists, otherwise the `managed_tag_assignment`.

Tag resolution only applies to draft payrolls. Once a payroll is approved, its tag assignments are locked. Subsequent changes to work assignment or generator tag assignments will not affect it.

When a work assignment's `tag_assignment` is updated, draft line items whose generator has no `tag_assignment`, have their `managed_tag_assignment` updated to match. When a generator's `tag_assignment` is updated, all of its draft line items have their `managed_tag_assignment` updated to match.

## Primary tag group

A business entity can designate one tag group as its **primary tag group**.

* Tags from this group can be linked to [accounting code rules](#accounting-code-rules), enabling automatic accounting code matching
* When set, every tag allocation must include a tag from the primary tag group

Set the primary tag group through the business entity's [`accounting_settings.primary_tag_group`](/api-reference/business-entities/update-a-business-entity). The top-level `primary_tag_group_id` is a deprecated alias. Setting a primary tag group also flags it as a journal entry dimension; the same request can [set the full set of tracking dimensions](#setting-the-whole-set-at-once). If the primary tag group is changed, draft payrolls with allocations missing a tag from the new primary group will be blocked until corrected.

## Accounting code rules

Tags and tag groups can scope accounting code rules, so a line item's tags influence which expense and liability codes it receives. A tag- or tag-group-scoped rule takes precedence over a global rule, and matches tags in the [primary tag group](#primary-tag-group).

See [Accounting Codes & Rules](/guides/accounting/codes-and-rules#rule-precedence) for the full precedence model (tag, tag group, and global tiers) and how rules resolve during payroll calculation.

## Derived tags on statutory withholdings

Statutory withholding line items (CPP, EI, income tax, etc.) are system-calculated and cannot be directly tagged. Instead, they derive their tag assignments from the applicable remuneration on the pay stub.

This behaviour is controlled by the business entity's `accounting_settings.resolve_journal_entry_stat_withholdings` setting. When `true`, each withholding is split across the same tags as its source earnings. When `false`, each withholding stays a single unsplit row in journal entries.

When enabled, after payroll calculation the system examines which remuneration line items contribute to each withholding and builds a weighted percentage distribution based on their resolved dollar amounts, regardless of whether the original tag assignment used `percentage`, `hours`, or `amount` units. This ensures withholding amounts follow the same distribution as the remuneration that generated them.

### Example: statutory withholdings derived from pensionable earnings

**Earnings on the pay stub:**

| Line item      | Amount  | Engineering | Sales |
| -------------- | ------- | ----------- | ----- |
| Salary earning | \$3,000 | 100%        |       |
| Bonus earning  | \$2,000 |             | 100%  |

**Derived statutory withholdings:**

| Line item       | Amount | Engineering | Sales       |
| --------------- | ------ | ----------- | ----------- |
| CPP withholding | \$300  | 60% (\$180) | 40% (\$120) |
| EI withholding  | \$150  | 60% (\$90)  | 40% (\$60)  |

The withholdings inherit a 60/40 distribution derived from the weighted remuneration (\$3,000 Engineering / \$2,000 Sales).

## Journal entry tracking dimensions

Tag groups can be marked as **tracking dimensions** on journal entries. When enabled, each line item allocation produces a separate journal entry row, with matched accounting codes and the tag from each tracking dimension.

The [primary tag group](#primary-tag-group) is always a tracking dimension. Up to two additional tag groups can be marked as tracking dimensions by setting `is_journal_entry_dimension` to `true`.

Tagged payroll data produces structured journal entries with tracking detail per tag group.

### Setting the whole set at once

A business entity update accepts the complete set of tracking dimensions as `accounting_settings.journal_entry_dimensions`, alongside the primary tag group, and applies them together:

```json theme={null}
{
  "accounting_settings": {
    "primary_tag_group_id": "tgrp_01PROJECT...",
    "journal_entry_dimensions": ["tgrp_01PROJECT...", "tgrp_01LOCATION..."]
  }
}
```

The collection replaces the current set, so a tag group left out of it stops being a tracking dimension — no separate call to turn it off. The primary tag group is always a tracking dimension: its id has to appear in the collection, and naming it uses one of the three slots rather than two. Archived tag groups can be named, and keep their slot until they are dropped from the collection.

The request is rejected with a `422` if the collection names more than three tag groups, leaves out the primary tag group the business entity ends up with, or names a tag group belonging to another business entity. Nothing from a rejected request is applied, so a business entity is never left partway through a change. The same collection comes back on the business entity, and `is_journal_entry_dimension` on an individual tag group keeps working as it does today.

### Example: journal entry rows with tracking dimensions

Given a salary earning of \$5,000 tagged 60% Engineering / 40% Sales:

**Without tracking dimensions:**

| Account           | Debit   | Credit  |
| ----------------- | ------- | ------- |
| Salary Expense    | \$5,000 |         |
| Payroll Liability |         | \$5,000 |

**With Department and Project as tracking dimensions:**

| Account           | Debit   | Credit  | Department  | Project       |
| ----------------- | ------- | ------- | ----------- | ------------- |
| Salary Expense    | \$3,000 |         | Engineering | Project Alpha |
| Salary Expense    | \$2,000 |         | Sales       |               |
| Payroll Liability |         | \$3,000 | Engineering | Project Alpha |
| Payroll Liability |         | \$2,000 | Sales       |               |

Each allocation produces its own debit and credit row, with the matched accounting codes and tracking dimension tags.

### Retrieving dimension tags

Each journal entry row carries up to three dimension tags, one per tracking dimension: `dimension_1_tag`, `dimension_2_tag`, and `dimension_3_tag`. A tag group keeps the same slot across every row in a payroll. Slots are not pinned to a fixed group, so read each tag's `tag_group` to tell which dimension it represents rather than relying on position.

The tags sit two levels down: rows are nested under the journal entry, and each tag is nested under a row. Both are returned as stubs by default, so resolving the tags inline takes a nested expand. Expand `journal_entry_rows.dimension_1_tag`, `journal_entry_rows.dimension_2_tag`, and `journal_entry_rows.dimension_3_tag` for the dimensions to resolve.

Each expanded row then includes the full tag for every dimension it carries:

```json theme={null}
{
  "id": "accjr_01...",
  "object": "journal_entry_row",
  "data": {
    "type": "debit",
    "amount": 2500,
    "code": "5110",
    "dimension_1_tag": {
      "id": "tag_01AURORA...",
      "object": "tag",
      "data": {
        "label": "Aurora",
        "tag_group": { "id": "tgrp_01...", "object": "tag_group" }
      }
    },
    "dimension_2_tag": {
      "id": "tag_01MTL...",
      "object": "tag",
      "data": {
        "label": "Montreal",
        "tag_group": { "id": "tgrp_01...", "object": "tag_group" }
      }
    },
    "dimension_3_tag": null
  }
}
```

A dimension with no tag on a row returns `null`. Without the expand, each dimension tag is returned as a stub with `id` and `links` only.

## End-to-end example

This example walks through the full tagging flow, from setup to journal entries.

* Quebec-based business entity with two employees: Marie (Montreal) and Luc (Quebec City)
* Both earn \$60,000 salary, paid semi-monthly (\$2,500 per period)
* Both work on Project Aurora
* Luc also receives an \$833.33 bonus for work on Project Beacon

### 1. Set up tags

1. Create a "Project" tag group with two tags: **Aurora** and **Beacon**
2. Create a "Location" tag group with two tags: **Montreal** and **Quebec City**
3. Set "Project" as the business entity's primary tag group (`accounting_settings.primary_tag_group`)
4. Mark both tag groups as journal entry tracking dimensions (`is_journal_entry_dimension: true`)

<details>
  <summary>API structure</summary>

  ```jsonc theme={null}
  // Project tag group
  {
    "id": "tgrp_01J...",
    "object": "tag_group",
    "data": {
      "label": "Project",
      "label_translations": { "en": "Project", "fr": "Projet" },
      "description": null,
      "is_component_locked": false,
      "is_journal_entry_dimension": true,
      "business_entity": { "id": "be_01...", "object": "business_entity" }
    }
  }

  // Aurora project tag
  {
    "id": "tag_01AURORA...",
    "object": "tag",
    "data": {
      "label": "Aurora",
      "label_translations": { "en": "Aurora", "fr": "Aurora" },
      "description": null,
      "tag_group": { "id": "tgrp_01J...", "object": "tag_group" },
      "business_entity": { "id": "be_01...", "object": "business_entity" }
    }
  }

  // Beacon project tag
  {
    "id": "tag_01BEACON...",
    "object": "tag",
    "data": {
      "label": "Beacon",
      "label_translations": { "en": "Beacon", "fr": "Beacon" },
      "description": null,
      "tag_group": { "id": "tgrp_01J...", "object": "tag_group" },
      "business_entity": { "id": "be_01...", "object": "business_entity" }
    }
  }

  // The "Location" tag group (tgrp_01L...) with tags "Montreal" and "Quebec City"
  // follows the same structure as above.
  ```
</details>

### 2. Create accounting code rules

Define rules for the primary tag group to map each project to accounting codes:

| Tag    | Type                  | Expense code                    | Liability code                  |
| ------ | --------------------- | ------------------------------- | ------------------------------- |
| Aurora | Earning               | 5110 (Aurora Salaries)          | 2100 (Aurora Payroll Liability) |
| Aurora | Statutory withholding | 5120 (Aurora Stat Withholdings) | 2110 (Aurora Stat Payable)      |
| Beacon | Earning               | 5210 (Beacon Salaries)          | 2200 (Beacon Payroll Liability) |
| Beacon | Statutory withholding | 5220 (Beacon Stat Withholdings) | 2210 (Beacon Stat Payable)      |

Each project has an earning rule and a stat withholding rule. No tag-only fallbacks are needed since all line items in this example are covered by type-level rules.

<details>
  <summary>API structure</summary>

  ```jsonc theme={null}
  // Aurora: earning rule
  {
    "id": "acr_01A...",
    "object": "accounting_code_rule",
    "data": {
      "business_entity": { "id": "be_01...", "object": "business_entity" },
      "tag": { "id": "tag_01AURORA...", "object": "tag" }, // Aurora project tag
      "type": "earning",
      "subtype": null,
      "business_preset": null,
      "expense_accounting_code": { "id": "ac_5110...", "object": "accounting_code" }, // Aurora Salaries
      "liability_accounting_code": { "id": "ac_2100...", "object": "accounting_code" } // Aurora Payroll Liability
    }
  }

  // Aurora: stat withholding rule
  {
    "id": "acr_01B...",
    "object": "accounting_code_rule",
    "data": {
      "business_entity": { "id": "be_01...", "object": "business_entity" },
      "tag": { "id": "tag_01AURORA...", "object": "tag" }, // Aurora project tag
      "type": "statutory_withholding",
      "subtype": null,
      "business_preset": null,
      "expense_accounting_code": { "id": "ac_5120...", "object": "accounting_code" }, // Aurora Stat Withholdings
      "liability_accounting_code": { "id": "ac_2110...", "object": "accounting_code" } // Aurora Stat Payable
    }
  }

  // Beacon: earning rule
  {
    "id": "acr_01C...",
    "object": "accounting_code_rule",
    "data": {
      "business_entity": { "id": "be_01...", "object": "business_entity" },
      "tag": { "id": "tag_01BEACON...", "object": "tag" }, // Beacon project tag
      "type": "earning",
      "subtype": null,
      "business_preset": null,
      "expense_accounting_code": { "id": "ac_5210...", "object": "accounting_code" }, // Beacon Salaries
      "liability_accounting_code": { "id": "ac_2200...", "object": "accounting_code" } // Beacon Payroll Liability
    }
  }

  // Beacon: stat withholding rule
  {
    "id": "acr_01D...",
    "object": "accounting_code_rule",
    "data": {
      "business_entity": { "id": "be_01...", "object": "business_entity" },
      "tag": { "id": "tag_01BEACON...", "object": "tag" }, // Beacon project tag
      "type": "statutory_withholding",
      "subtype": null,
      "business_preset": null,
      "expense_accounting_code": { "id": "ac_5220...", "object": "accounting_code" }, // Beacon Stat Withholdings
      "liability_accounting_code": { "id": "ac_2210...", "object": "accounting_code" } // Beacon Stat Payable
    }
  }
  ```
</details>

### 3. Assign tags to work assignments

Both employees' work assignments are tagged 100% Aurora, with their respective location:

**Marie:**

* 100% to `Project: Aurora`, `Location: Montreal`

**Luc:**

* 100% to `Project: Aurora`, `Location: Quebec City`

<details>
  <summary>API structure: work assignment with tag\_assignment</summary>

  ```jsonc theme={null}
  // Marie's work assignment with ?expand=tag_assignment
  {
    "id": "wa_01M...",
    "object": "work_assignment",
    "data": {
      // ...
      "tag_assignment": {
        "unit": "percentage",
        "tag_allocations": [
          {
            "tags": [
              {
                "id": "tag_01AURORA...",
                "object": "tag",
                "data": {
                  "label": "Aurora",
                  "tag_group": { "id": "tgrp_01J...", "object": "tag_group" },
                  "business_entity": {
                    "id": "be_01...",
                    "object": "business_entity",
                  },
                },
              },
              {
                "id": "tag_01MTL...",
                "object": "tag",
                "data": {
                  "label": "Montreal",
                  "tag_group": { "id": "tgrp_01L...", "object": "tag_group" },
                  "business_entity": {
                    "id": "be_01...",
                    "object": "business_entity",
                  },
                },
              },
            ],
            "value": 100,
            "expense_accounting_code": null,
            "liability_accounting_code": null,
          },
        ],
      },
    },
  }
  ```
</details>

### 4. Line items on the pay stub

In this example, the salary line items resolve their `managed_tag_assignment` from the work assignment. Since Luc's bonus is for work on Project Beacon, a `custom_tag_assignment` on that line item overrides the managed Aurora tag with Beacon. When expanded, the effective `tag_assignment` returns the `custom_tag_assignment` if one is set, otherwise the `managed_tag_assignment`.

**Marie's salary earning (\$2,500.00):**

* Managed tag assignment: 100% to `Project: Aurora`, `Location: Montreal`
* Custom tag assignment: none
* **Effective tag assignment:** 100% to `Project: Aurora`, `Location: Montreal`

**Luc's salary earning (\$2,500.00):**

* Managed tag assignment: 100% to `Project: Aurora`, `Location: Quebec City`
* Custom tag assignment: none
* **Effective tag assignment:** 100% to `Project: Aurora`, `Location: Quebec City`

**Luc's bonus earning (\$833.33):**

* Managed tag assignment: 100% to `Project: Aurora`, `Location: Quebec City`
* Custom tag assignment: 100% to `Project: Beacon`, `Location: Quebec City`
* **Effective tag assignment:** 100% to `Project: Beacon`, `Location: Quebec City`

### 5. Matched accounting codes

Each line item's tag allocations are matched against accounting code rules:

| Employee | Line item       | Primary tag | Matched rule          | Expense code                    | Liability code                  |
| -------- | --------------- | ----------- | --------------------- | ------------------------------- | ------------------------------- |
| Marie    | Salary earning  | Aurora      | Earning               | 5110 (Aurora Salaries)          | 2100 (Aurora Payroll Liability) |
| Luc      | Salary earning  | Aurora      | Earning               | 5110 (Aurora Salaries)          | 2100 (Aurora Payroll Liability) |
| Luc      | Bonus earning   | Beacon      | Earning               | 5210 (Beacon Salaries)          | 2200 (Beacon Payroll Liability) |
| Marie    | QPP withholding | Aurora      | Statutory withholding | 5120 (Aurora Stat Withholdings) | 2110 (Aurora Stat Payable)      |
| Luc      | QPP withholding | Aurora      | Statutory withholding | 5120 (Aurora Stat Withholdings) | 2110 (Aurora Stat Payable)      |
| Luc      | QPP withholding | Beacon      | Statutory withholding | 5220 (Beacon Stat Withholdings) | 2210 (Beacon Stat Payable)      |

Luc's QPP withholding has two allocations (75% Aurora / 25% Beacon), each resolved independently against its matching rule.

<details>
  <summary>API structure: Luc's bonus earning with resolved tag allocations and accounting codes</summary>

  ```jsonc theme={null}
  // Luc's bonus earning with ?expand=tag_assignment,managed_tag_assignment,custom_tag_assignment
  {
    "id": "eli_01B...",
    "object": "earning_line_item",
    "data": {
      "amount": 833.33,
      // ...
      "managed_tag_assignment": {
        // Inherited from work assignment (Aurora, Quebec City)
        "unit": "percentage",
        "tag_allocations": [
          {
            "tags": [
              {
                "id": "tag_01AURORA...",
                "object": "tag",
                "data": { "label": "Aurora" },
              },
              {
                "id": "tag_01QC...",
                "object": "tag",
                "data": { "label": "Quebec City" },
              },
            ],
            "value": 100,
            "expense_accounting_code": {
              "id": "ac_5110...",
              "object": "accounting_code",
            }, // Aurora Salaries
            "liability_accounting_code": {
              "id": "ac_2100...",
              "object": "accounting_code",
            }, // Aurora Payroll Liability
          },
        ],
      },
      "custom_tag_assignment": {
        // User override: Beacon, Quebec City
        "unit": "percentage",
        "tag_allocations": [
          {
            "tags": [
              {
                "id": "tag_01BEACON...",
                "object": "tag",
                "data": { "label": "Beacon" },
              },
              {
                "id": "tag_01QC...",
                "object": "tag",
                "data": { "label": "Quebec City" },
              },
            ],
            "value": 100,
            "expense_accounting_code": {
              "id": "ac_5210...",
              "object": "accounting_code",
            }, // Beacon Salaries
            "liability_accounting_code": {
              "id": "ac_2200...",
              "object": "accounting_code",
            }, // Beacon Payroll Liability
          },
        ],
      },
      "tag_assignment": {
        // Effective: custom takes precedence over managed
        "unit": "percentage",
        "tag_allocations": [
          {
            "tags": [
              {
                "id": "tag_01BEACON...",
                "object": "tag",
                "data": { "label": "Beacon" },
              },
              {
                "id": "tag_01QC...",
                "object": "tag",
                "data": { "label": "Quebec City" },
              },
            ],
            "value": 100,
            "expense_accounting_code": {
              "id": "ac_5210...",
              "object": "accounting_code",
            }, // Beacon Salaries
            "liability_accounting_code": {
              "id": "ac_2200...",
              "object": "accounting_code",
            }, // Beacon Payroll Liability
          },
        ],
      },
    },
  }
  ```
</details>

### 6. Derived statutory withholdings

Statutory withholdings derive their tag allocations from the remuneration that generates them.

**Marie**: all remuneration is tagged `Project: Aurora`, `Location: Montreal`, so each withholding carries the same single allocation:

* Federal tax (\$184.47)
  * 100% (\$184.47) to `Project: Aurora`, `Location: Montreal`
* Provincial tax (\$235.29)
  * 100% (\$235.29) to `Project: Aurora`, `Location: Montreal`
* QPP (\$148.31)
  * 100% (\$148.31) to `Project: Aurora`, `Location: Montreal`
* QPIP (\$10.75)
  * 100% (\$10.75) to `Project: Aurora`, `Location: Montreal`
* EI (\$32.50)
  * 100% (\$32.50) to `Project: Aurora`, `Location: Montreal`

**Luc**: remuneration is \$2,500 (`Project: Aurora`) + \$833.33 (`Project: Beacon`), a 75/25 split. Both carry `Location: Quebec City`. Each withholding derives two allocations at that ratio:

* Federal tax (\$325.75)
  * 75% (\$244.31) to `Project: Aurora`, `Location: Quebec City`
  * 25% (\$81.44) to `Project: Beacon`, `Location: Quebec City`
* Provincial tax (\$350.77)
  * 75% (\$263.08) to `Project: Aurora`, `Location: Quebec City`
  * 25% (\$87.69) to `Project: Beacon`, `Location: Quebec City`
* QPP (\$200.81)
  * 75% (\$150.61) to `Project: Aurora`, `Location: Quebec City`
  * 25% (\$50.20) to `Project: Beacon`, `Location: Quebec City`
* QPIP (\$14.33)
  * 75% (\$10.75) to `Project: Aurora`, `Location: Quebec City`
  * 25% (\$3.58) to `Project: Beacon`, `Location: Quebec City`
* EI (\$43.33)
  * 75% (\$32.50) to `Project: Aurora`, `Location: Quebec City`
  * 25% (\$10.83) to `Project: Beacon`, `Location: Quebec City`

### 7. Journal entry rows

With Project and Location as journal entry tracking dimensions, each allocation produces its own row. Employer contribution rows are omitted for brevity.

| Account             | Location    | Project | Debit      | Credit     |
| ------------------- | ----------- | ------- | ---------- | ---------- |
| Aurora Salaries     | Montreal    | Aurora  | \$2,500.00 |            |
| Aurora Salaries     | Quebec City | Aurora  | \$2,500.00 |            |
| Beacon Salaries     | Quebec City | Beacon  | \$833.33   |            |
| Aurora Stat Payable | Montreal    | Aurora  |            | \$611.32   |
| Aurora Stat Payable | Quebec City | Aurora  |            | \$701.25   |
| Beacon Stat Payable | Quebec City | Beacon  |            | \$233.74   |
| Net Payroll Payable |             |         |            | \$4,287.02 |
