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

# Tags Sync Workflow Guide

export const SyncTagsDiagram = () => {
  const [isDark, setIsDark] = useState(false);
  useEffect(() => {
    const check = () => setIsDark(document.documentElement.classList.contains("dark"));
    check();
    const observer = new MutationObserver(check);
    observer.observe(document.documentElement, {
      attributes: true,
      attributeFilter: ["class"]
    });
    return () => observer.disconnect();
  }, []);
  const nodeFill = isDark ? "#212222" : "#EEF4F4";
  const nodeStroke = isDark ? "#848989" : "#E1E6E6";
  const nodeTextStyle = isDark ? ",color:#EEF4F4" : ",color:#131414";
  const linkStyle = isDark ? "" : "linkStyle default stroke:#848989,stroke-width:1px;";
  const diagram = `
%%{init: {"themeVariables": {"fontSize": "32px"}}}%%
flowchart LR
    T1["1. Iterate Over Tag Groups"] --> T2["2. Retrieve Dimension Values"] --> T3["3. Retrieve All Tags"] --> T4["4. Resolve Duplicates"] --> T5["5. Match by Code"]
    T5 -->|No match| T6["6. Create Tag"]
    T5 -->|Match found| T7["7. Unarchive or Update"]
    T6 --> T8["8. Archive Unmatched"]
    T7 --> T8

click T1 "#1-iterate-over-each-selected-tag-group"
click T2 "#2-retrieve-dimension-values-from-the-accounting-system"
click T3 "#3-retrieve-all-tags-from-pleo-for-the-tag-group"
click T4 "#4-resolve-duplicate-tags"
click T5 "#5-match-dimension-values-to-tags-by-code"
click T6 "#6-create-tags-for-new-dimension-values"
click T7 "#7-unarchive-or-update-existing-tags"
click T8 "#8-archive-tags-with-no-matching-active-dimension-value"

style T1 white-space:normal,fill:${nodeFill},stroke:${nodeStroke}${nodeTextStyle}
style T2 white-space:normal,fill:${nodeFill},stroke:${nodeStroke}${nodeTextStyle}
style T3 white-space:normal,fill:${nodeFill},stroke:${nodeStroke}${nodeTextStyle}
style T4 white-space:normal,fill:${nodeFill},stroke:${nodeStroke}${nodeTextStyle}
style T5 white-space:normal,fill:${nodeFill},stroke:${nodeStroke}${nodeTextStyle}
style T6 white-space:normal,fill:${nodeFill},stroke:${nodeStroke}${nodeTextStyle}
style T7 white-space:normal,fill:${nodeFill},stroke:${nodeStroke}${nodeTextStyle}
style T8 white-space:normal,fill:${nodeFill},stroke:${nodeStroke}${nodeTextStyle}
${linkStyle}
`;
  return <Mermaid chart={diagram} />;
};

export const SyncTagGroupsDiagram = () => {
  const [isDark, setIsDark] = useState(false);
  useEffect(() => {
    const check = () => setIsDark(document.documentElement.classList.contains("dark"));
    check();
    const observer = new MutationObserver(check);
    observer.observe(document.documentElement, {
      attributes: true,
      attributeFilter: ["class"]
    });
    return () => observer.disconnect();
  }, []);
  const nodeFill = isDark ? "#212222" : "#EEF4F4";
  const nodeStroke = isDark ? "#848989" : "#E1E6E6";
  const nodeTextStyle = isDark ? ",color:#EEF4F4" : ",color:#131414";
  const linkStyle = isDark ? "" : "linkStyle default stroke:#848989,stroke-width:1px;";
  const diagram = `
%%{init: {"themeVariables": {"fontSize": "24px"}}}%%
flowchart LR
    S1["1. Retrieve Selected Dimensions"] --> S2["2. Retrieve All Tag Groups"] --> S3["3. Match by Code"]
    S3 -->|No match| S4["4. Create Tag Group"]
    S3 -->|Match found| S5["5. Unarchive or Update"]
    S4 --> S6["6. Archive Unmatched"]
    S5 --> S6

click S1 "#1-retrieve-selected-dimensions-from-the-accounting-system"
click S2 "#2-retrieve-all-tag-groups-from-pleo"
click S3 "#3-match-dimensions-to-tag-groups-by-code"
click S4 "#4-create-tag-groups-for-new-dimensions"
click S5 "#5-unarchive-or-update-existing-tag-groups"
click S6 "#6-archive-tag-groups-with-no-matching-selected-dimension"

style S1 white-space:normal,fill:${nodeFill},stroke:${nodeStroke}${nodeTextStyle}
style S2 white-space:normal,fill:${nodeFill},stroke:${nodeStroke}${nodeTextStyle}
style S3 white-space:normal,fill:${nodeFill},stroke:${nodeStroke}${nodeTextStyle}
style S4 white-space:normal,fill:${nodeFill},stroke:${nodeStroke}${nodeTextStyle}
style S5 white-space:normal,fill:${nodeFill},stroke:${nodeStroke}${nodeTextStyle}
style S6 white-space:normal,fill:${nodeFill},stroke:${nodeStroke}${nodeTextStyle}
${linkStyle}
`;
  return <Mermaid chart={diagram} />;
};

export const SelectDimensionsDiagram = () => {
  const [isDark, setIsDark] = useState(false);
  useEffect(() => {
    const check = () => setIsDark(document.documentElement.classList.contains("dark"));
    check();
    const observer = new MutationObserver(check);
    observer.observe(document.documentElement, {
      attributes: true,
      attributeFilter: ["class"]
    });
    return () => observer.disconnect();
  }, []);
  const nodeFill = isDark ? "#212222" : "#EEF4F4";
  const nodeStroke = isDark ? "#848989" : "#E1E6E6";
  const nodeTextStyle = isDark ? ",color:#EEF4F4" : ",color:#131414";
  const linkStyle = isDark ? "" : "linkStyle default stroke:#848989,stroke-width:1px;";
  const diagram = `
%%{init: {"themeVariables": {"fontSize": "32px"}}}%%
flowchart LR
    S1["1. Retrieve Active Dimensions"] --> S2["2. Retrieve Existing Tag Groups"] --> S3["3. Apply Auto-Selection"]
    S3 -->|First connection| S3a["Auto-select matching Dimensions"]
    S3 -->|Subsequent connection| S3b["Restore from config"]
    S3a --> S4["4. Store the Selection"]
    S3b --> S4
    S4 --> S5["5. Handle Inactive Dimensions"]

click S1 "#1-retrieve-active-dimensions-from-the-accounting-system"
click S2 "#2-retrieve-existing-tag-groups-from-pleo"
click S3 "#3-apply-auto-selection-on-first-connection"
click S4 "#4-store-the-dimension-selection"
click S5 "#5-handle-inactive-dimensions"

style S1 white-space:normal,fill:${nodeFill},stroke:${nodeStroke}${nodeTextStyle}
style S2 white-space:normal,fill:${nodeFill},stroke:${nodeStroke}${nodeTextStyle}
style S3 white-space:normal,fill:${nodeFill},stroke:${nodeStroke}${nodeTextStyle}
style S3a white-space:normal,fill:${nodeFill},stroke:${nodeStroke}${nodeTextStyle}
style S3b white-space:normal,fill:${nodeFill},stroke:${nodeStroke}${nodeTextStyle}
style S4 white-space:normal,fill:${nodeFill},stroke:${nodeStroke}${nodeTextStyle}
style S5 white-space:normal,fill:${nodeFill},stroke:${nodeStroke}${nodeTextStyle}
${linkStyle}
`;
  return <Mermaid chart={diagram} />;
};

export const TagsSyncOverviewDiagram = () => {
  const [isDark, setIsDark] = useState(false);
  useEffect(() => {
    const check = () => setIsDark(document.documentElement.classList.contains("dark"));
    check();
    const observer = new MutationObserver(check);
    observer.observe(document.documentElement, {
      attributes: true,
      attributeFilter: ["class"]
    });
    return () => observer.disconnect();
  }, []);
  const nodeFill = isDark ? "#212222" : "#EEF4F4";
  const nodeStroke = isDark ? "#848989" : "#E1E6E6";
  const nodeTextStyle = isDark ? ",color:#EEF4F4" : ",color:#131414";
  const subgraphFill = isDark ? "#131414" : "#ffffff";
  const subgraphStroke = isDark ? "#848989" : "#6B7070";
  const subgraphTextStyle = isDark ? ",color:#EEF4F4" : ",color:#6B7070";
  const linkStyle = isDark ? "" : "linkStyle default stroke:#848989,stroke-width:1px;";
  const diagram = `
%%{init: {"themeVariables": {"fontSize": "18px"}}}%%
flowchart LR

subgraph AS["Accounting System"]
    source["Dimensions & Dimension Values"]
end

subgraph Pleo["Pleo APIs"]
    A["1. Select Dimensions"]
    B["2. Sync Tag Groups with Dimensions"]
    C["3. Sync Tags with Dimension Values"]
    A --> B --> C
end

source --> A

click A "#1-select-dimensions"
click B "#2-sync-tag-groups-with-dimensions"
click C "#3-sync-tags-with-dimension-values"

style A white-space:normal,fill:${nodeFill},stroke:${nodeStroke}${nodeTextStyle}
style B white-space:normal,fill:${nodeFill},stroke:${nodeStroke}${nodeTextStyle}
style C white-space:normal,fill:${nodeFill},stroke:${nodeStroke}${nodeTextStyle}
style source white-space:normal,fill:${nodeFill},stroke:${nodeStroke}${nodeTextStyle}
style AS fill:${subgraphFill},stroke:${subgraphStroke}${subgraphTextStyle}
style Pleo fill:${subgraphFill},stroke:${subgraphStroke}${subgraphTextStyle}
${linkStyle}
`;
  return <Mermaid chart={diagram} />;
};

export const WhatComesNext = ({children, href}) => <div className="mt-4">
    <a href={href} className="btn-primary">
      {children} →
    </a>
  </div>;

export const RecommendedCallout = ({title, children}) => <div className="callout-box callout-recommended">
    <div className="callout-row">
      <span className="callout-icon">
        <svg width="22" height="22" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M229.06,108.79l-48.7,42,14.88,62.79a8.4,8.4,0,0,1-12.52,9.17L128,189.09,73.28,222.74a8.4,8.4,0,0,1-12.52-9.17l14.88-62.79-48.7-42A8.46,8.46,0,0,1,31.73,94L95.64,88.8l24.62-59.6a8.36,8.36,0,0,1,15.48,0l24.62,59.6L224.27,94A8.46,8.46,0,0,1,229.06,108.79Z" opacity="0.2" /><path d="M239.18,97.26A16.38,16.38,0,0,0,224.92,86l-59-4.76L143.14,26.15a16.36,16.36,0,0,0-30.27,0L90.11,81.23,31.08,86a16.46,16.46,0,0,0-9.37,28.86l45,38.83L53,211.75a16.38,16.38,0,0,0,24.5,17.82L128,198.49l50.53,31.08A16.4,16.4,0,0,0,203,211.75l-13.76-58.07,45-38.83A16.43,16.43,0,0,0,239.18,97.26Zm-15.34,5.47-48.7,42a8,8,0,0,0-2.56,7.91l14.88,62.8a.37.37,0,0,1-.17.48c-.18.14-.23.11-.38,0l-54.72-33.65a8,8,0,0,0-8.38,0L69.09,215.94c-.15.09-.19.12-.38,0a.37.37,0,0,1-.17-.48l14.88-62.8a8,8,0,0,0-2.56-7.91l-48.7-42c-.12-.1-.23-.19-.13-.5s.18-.27.33-.29l63.92-5.16A8,8,0,0,0,103,91.86l24.62-59.61c.08-.17.11-.25.35-.25s.27.08.35.25L153,91.86a8,8,0,0,0,6.75,4.92l63.92,5.16c.15,0,.24,0,.33.29S224,102.63,223.84,102.73Z" /></svg>
      </span>
      <div>
        {title && <div className="callout-title">
            {title}
          </div>}
        <div className="callout-body">
          {children}
        </div>
      </div>
    </div>
  </div>;

<RecommendedCallout title="Recommended Workflow">
  This guide covers [Integration Level 2](/docs/current/getting-started/accounting-integrations-overview), which enables syncing Accounting Dimensions from your Accounting System into Pleo as Tags. It builds on Level 1 (Expense Items Exporting) and ensures bookkeepers can assign the correct Dimensions to expenses before export.
</RecommendedCallout>

## What You'll Have Built

After implementing this workflow:

* Accounting Dimensions from the AS are reflected as Tag Groups in Pleo.
* Dimension Values are reflected as Tags within each Tag Group.
* Tags are automatically kept up-to-date on a scheduled basis.
* Bookkeepers can assign current, accurate Dimensions to expenses in Pleo.
* The integration aligns with Pleo's Tags Sync guarantees and matching model.

## Who This Guide Is For

This guide is intended for:

* Integration developers
* Solution architects
* Accounting platform integrators

It focuses on **workflow understanding**, not implementation details.

## Before You Start

You should be familiar with:

* Pleo's [supported authentication](/docs/current/integration-design/auth/integration-design-auth-overview#authentication-policy-overview) methods.
* The [Tags Sync](/docs/current/platform/accounting-integrations/imports/tags/tags-sync-overview) platform capabilities page.

## Tags Sync Workflow Overview

In the Accounting System, Dimensions represent categories used to classify expenses (such as Department, Cost Centre, or Project). Each Dimension contains Dimension Values, which are the individual options a bookkeeper can assign to an expense (such as Engineering, Marketing, or Operations).

Tags Sync maps this structure into Pleo. Dimensions become Tag Groups and Dimension Values become Tags. The Accounting System is the source of truth; the integration's role is to keep Pleo's Tag Groups and Tags aligned with the current state of the AS so bookkeepers always have accurate, up-to-date options when coding expenses.

Step 1 runs once on first connection and configures which Dimensions to synchronise. Steps 2 and 3 run together on a schedule, keeping Pleo in sync with the AS as Dimensions and Dimension Values change over time. Each step produces outputs required by the next.

<TagsSyncOverviewDiagram />

The how-to articles in this section use a consistent example to illustrate each step. The table below shows the starting state in both systems before the sync process runs.

| Dimension (AS) | AS Status | Tag Group (Pleo) | Pleo Status    | Desired Pleo State             |
| -------------- | --------- | ---------------- | -------------- | ------------------------------ |
| Department     | Active    | Department       | Active         | Active (no change)             |
| Project        | Active    | Project          | Active         | Active (no change)             |
| Finance        | Active    | —                | Does not exist | Created                        |
| Cost Centre    | Active    | Cost Centre      | Archived       | Unarchived                     |
| Supplier       | Active    | —                | Does not exist | Created                        |
| —              | —         | Region           | Active         | Archived (doesn't exist in AS) |

The three steps progress as follows:

| Step                 | Integration action                                                               | Outcome                                                |
| -------------------- | -------------------------------------------------------------------------------- | ------------------------------------------------------ |
| 1. Select Dimensions | Selects Department, Project, Finance, Cost Centre, and Supplier                  | 5 Dimensions stored in the integration's configuration |
| 2. Sync Tag Groups   | Creates Finance and Supplier Tag Groups, unarchives Cost Centre, archives Region | Tag Groups in Pleo aligned with selected Dimensions    |
| 3. Sync Tags         | Creates, updates, and archives Tags to match Dimension Values from the AS        | Tags in Pleo aligned with current AS Dimension Values  |

***

## Steps

### 1. Select Dimensions

#### Purpose

Before Tags Sync can run, the integration must know which Accounting Dimensions from the AS to synchronise. This step configures that selection and stores it for every subsequent sync cycle.

On **first connection**, the integration automatically pre-selects Dimensions whose code matches an existing active Tag Group in Pleo. This reduces setup effort for integrators who have previously configured Tags manually in Pleo. Any remaining Dimensions can be selected manually, up to a maximum of 5 in total.

On **subsequent connections**, the stored selection is restored from the integration's configuration. No re-selection is needed. If a previously selected Dimension has become inactive in the AS since the last sync, it is automatically deselected and its corresponding Tag Group is archived in Pleo.

#### Input

* Active Dimensions from the AS (only active Dimensions are eligible for selection)
* Existing active Tag Groups from Pleo, used to determine which Dimensions can be auto-selected on first connection. If there are no active Tag Groups in Pleo, nothing is auto-selected and all Dimensions must be selected manually.

#### Workflow Process

<SelectDimensionsDiagram />

#### Output

* Dimensions auto-selected where their code matches an active Pleo Tag Group (first connection only)
* Dimensions that have become inactive in the AS automatically removed from the selection
* Up to 5 Dimensions stored in the integration's configuration, ready for use in every sync cycle

#### Why It Matters

The Dimension selection defines the scope of every sync cycle that follows. Only selected, active Dimensions are synchronised, so the selection must reflect what bookkeepers actually need to code expenses against. Auto-selection eliminates manual setup when reconnecting or reconfiguring after Tags have already been created in Pleo, and automatic deselection of inactive Dimensions keeps the selection clean without requiring manual intervention.

#### Integration Design

If you're an integration developer or architect, read the [Dimension Selection](/docs/current/integration-design/accounting-integrations/imports/tags/integration-design-tags-dimension-selection) integration design doc before implementing this step. It covers the rules and constraints your implementation must comply with, including selection limits, auto-selection matching logic, how inactive Dimensions are handled, and what deselecting a Dimension does to the corresponding Tag Group in Pleo.

#### Step-by-Step Instructions

When you're ready to start implementing, follow the step-by-step instructions in the accompanying How-to article.

<WhatComesNext href="/docs/current/how-tos/accounting-integrations/imports/tags/how-to-select-dimensions-for-tags-sync">
  How to Select Dimensions for Tags Sync
</WhatComesNext>

***

### 2. Sync Tag Groups with Dimensions

#### Purpose

This step runs at the start of every Tags Sync cycle, immediately after the Dimension selection is confirmed. The integration retrieves the selected Dimensions from its configuration, then retrieves all Tag Groups from Pleo, both active and archived, and aligns them.

For each selected Dimension, the integration looks for a matching Tag Group in Pleo by code (case-insensitive). If a match is found and the Tag Group is archived, it is unarchived. If no match exists, a new Tag Group is created. If the Tag Group name differs from the AS, it is updated to match.

Any active Tag Group in Pleo that no longer has a matching selected Dimension is archived. This covers Dimensions that were deselected or became inactive since the last sync cycle.

#### Input

* Selected active Dimensions from the integration's configuration (the Dimensions chosen in Step 1 that are still active in the AS)
* Active and archived Tag Groups from Pleo. Archived Tag Groups are included so they can be unarchived rather than duplicated if a Dimension is re-selected.

#### Workflow Process

<SyncTagGroupsDiagram />

#### Output

* Tag Groups created for Dimensions with no existing match in Pleo
* Archived Tag Groups unarchived where a selected Dimension matches
* Tag Group names updated where they differ from the current AS Dimension name
* Active Tag Groups archived where their Dimension is no longer selected

#### Why It Matters

Tag Groups are the containers that hold Tags. If this step is not run correctly, the structure bookkeepers rely on to code expenses will be out of date. Tag Group sync ensures the Pleo structure mirrors the AS before any Tags are processed, so Tags always end up in the right place.

#### Integration Design

If you're an integration developer or architect, read the [Sync Tag Groups with Dimensions](/docs/current/integration-design/accounting-integrations/imports/tags/integration-design-tags-sync-tag-groups) integration design doc before implementing this step. It covers the matching rules, archiving behaviour, and how the sync handles inactive Dimensions discovered during the cycle.

#### Step-by-Step Instructions

When you're ready to start implementing, follow the step-by-step instructions in the accompanying How-to article.

<WhatComesNext href="/docs/current/how-tos/accounting-integrations/imports/tags/how-to-sync-tag-groups-with-accounting-dimensions">
  How to Sync Tag Groups with Accounting Dimensions
</WhatComesNext>

***

### 3. Sync Tags with Dimension Values

#### Purpose

This step runs immediately after Tag Group sync, once for every active Tag Group in Pleo. For each Tag Group, the integration retrieves the corresponding Dimension Values from the AS and the current Tags from Pleo, then aligns them.

Tags are matched to Dimension Values by code (case-insensitive). Matched Tags that are archived are unarchived. Tags whose names differ from the AS are updated. If a Dimension Value has no matching Tag, a new Tag is created. Active Tags with no matching Dimension Value are archived.

The step also handles duplicate Tags (where multiple Tags in Pleo share the same code) by retaining the best match and archiving the rest.

#### Input

* Active Dimension Values from the AS for each selected Dimension (only active values are processed; inactive, blocked, or expired values result in the corresponding Tag being archived)
* Active and archived Tags from Pleo for each Tag Group. Archived Tags are included so they can be unarchived if the corresponding Dimension Value becomes active again.

#### Workflow Process

<SyncTagsDiagram />

#### Output

* Tags created for Dimension Values with no existing match in Pleo
* Archived Tags unarchived where a Dimension Value matches
* Tag names updated where they differ from the current AS Dimension Value name
* Active Tags archived where their Dimension Value is no longer active in the AS
* Duplicate Tags resolved by retaining the best match and archiving the rest

#### Why It Matters

Tags are what bookkeepers see and use when coding expenses. If Tags are out of date, bookkeepers may assign incorrect Dimensions, leading to errors when expenses are exported to the AS. This step ensures every active Dimension Value in the AS is available as a Tag in Pleo, and that stale Tags are removed before they cause problems.

#### Integration Design

If you're an integration developer or architect, read the [Sync Tags with Dimension Values](/docs/current/integration-design/accounting-integrations/imports/tags/integration-design-tags-sync-tags) integration design doc before implementing this step. It covers matching rules, duplicate resolution logic, the conditions under which Tags are archived, and how the sync handles edge cases like expired or blocked Dimension Values.

#### Step-by-Step Instructions

When you're ready to start implementing, follow the step-by-step instructions in the accompanying How-to article.

<WhatComesNext href="/docs/current/how-tos/accounting-integrations/imports/tags/how-to-sync-tags-with-dimension-values">
  How to Sync Tags with Dimension Values
</WhatComesNext>

***

## What Comes Next?

After implementing Tags Sync, you can extend your integration with:

* [Chart of Accounts Sync](/reference/accounts/chart-of-accounts-api-overview)
* [Tax Sync](/reference/tax-codes-overview)

***

## Related Reading

* [Integration Design - Tags Sync Overview](/docs/current/integration-design/accounting-integrations/imports/tags/integration-design-tags-overview)
* [Platform Capabilities — Tags Sync](/docs/current/platform/accounting-integrations/imports/tags/tags-sync-overview)

***
