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

# Vendor Sync Data Mapping

> The field-by-field mapping from Accounting System vendor data to Pleo's Vendors API, including how to handle invalid values.

export const VendorSyncDataMappingInvalidFieldsDiagram = () => {
  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 errorFill = isDark ? "#3A1E22" : "#FCE9EA";
  const errorStroke = isDark ? "#FF90A1" : "#F15A71";
  const errorTextStyle = isDark ? ",color:#FF90A1" : ",color:#7A1F2B";
  const linkStyle = isDark ? "" : "linkStyle default stroke:#848989,stroke-width:1px;";
  const diagram = `
%%{init: {"themeVariables": {"fontSize": "12px"}}}%%
flowchart TD
    A[AS field value for a vendor] --> B{Valid for this field?<br>e.g. ISO country/currency}
    B -->|Yes| C[Write value to Pleo]
    B -->|"No: blank, malformed,<br>or non-ISO"| G{Required by the<br>Vendors API?}
    G -->|"No, optional<br>e.g. country"| D[Skip this field, log for investigation,<br>process other fields/matching normally]
    G -->|"Yes, required<br>e.g. defaultCurrency"| H[Skip create/update for this vendor and log,<br>or send a fallback value and log]
    B -->|"No, abort entire<br>sync run (avoid this)"| E["BUG (avoid this): one bad field<br>blocks every vendor in the run"]
    B -->|"No, write invalid<br>value as-is (avoid this)"| F["BUG (avoid this): invalid data<br>written into Pleo"]

   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 D white-space:normal,fill:${nodeFill},stroke:${nodeStroke}${nodeTextStyle}
   style G white-space:normal,fill:${nodeFill},stroke:${nodeStroke}${nodeTextStyle}
   style H white-space:normal,fill:${nodeFill},stroke:${nodeStroke}${nodeTextStyle}
   style E white-space:normal,fill:${errorFill},stroke:${errorStroke}${errorTextStyle}
   style F white-space:normal,fill:${errorFill},stroke:${errorStroke}${errorTextStyle}
${linkStyle}
`;
  return <Mermaid chart={diagram} />;
};

export const VendorSyncDataMappingExternalIdDiagram = () => {
  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 errorFill = isDark ? "#3A1E22" : "#FCE9EA";
  const errorStroke = isDark ? "#FF90A1" : "#F15A71";
  const errorTextStyle = isDark ? ",color:#FF90A1" : ",color:#7A1F2B";
  const linkStyle = isDark ? "" : "linkStyle default stroke:#848989,stroke-width:1px;";
  const diagram = `
%%{init: {"themeVariables": {"fontSize": "12px"}}}%%
flowchart TD
    A[Choose externalId source] --> B{Are the AS's account<br>codes immutable?}
    B -->|Yes| C[code and externalId<br>can share the same value]
    B -->|No: codes can<br>be renumbered| D[Use a separate, stable<br>AS-internal record identifier]
    B -->|"No, use code as<br>externalId anyway (avoid this)"| E["BUG (avoid this): matching breaks<br>after a renumbering event"]

   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 D white-space:normal,fill:${nodeFill},stroke:${nodeStroke}${nodeTextStyle}
   style E white-space:normal,fill:${errorFill},stroke:${errorStroke}${errorTextStyle}
${linkStyle}
`;
  return <Mermaid chart={diagram} />;
};

export const RememberCallout = ({title, children}) => <div className="callout-box callout-remember">
    <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.66,98.34,172.39,155.8c11.46,22.93-1.72,45.86-10.11,57a8,8,0,0,1-12,.83L42.34,105.76A8,8,0,0,1,43,93.85c29.65-23.92,57.4-10,57.4-10l57.27-57.46a8,8,0,0,1,11.31,0L229.66,87A8,8,0,0,1,229.66,98.34Z" opacity="0.2" /><path d="M235.32,81.37,174.63,20.69a16,16,0,0,0-22.63,0L98.37,74.49c-10.66-3.34-35-7.37-60.4,13.14a16,16,0,0,0-1.29,23.78L85,159.71,42.34,202.34a8,8,0,0,0,11.32,11.32L96.29,171l48.29,48.29A16,16,0,0,0,155.9,224c.38,0,.75,0,1.13,0a15.93,15.93,0,0,0,11.64-6.33c19.64-26.1,17.75-47.32,13.19-60L235.33,104A16,16,0,0,0,235.32,81.37ZM224,92.69h0l-57.27,57.46a8,8,0,0,0-1.49,9.22c9.46,18.93-1.8,38.59-9.34,48.62L48,100.08c12.08-9.74,23.64-12.31,32.48-12.31A40.13,40.13,0,0,1,96.81,91a8,8,0,0,0,9.25-1.51L163.32,32,224,92.68Z" /></svg>
      </span>
      <div>
        {title && <div className="callout-title">
            {title}
          </div>}
        <div className="callout-body">
          {children}
        </div>
      </div>
    </div>
  </div>;

This page describes how data from the Accounting System is mapped to Pleo's Vendors API during Vendor Sync.

Data mapping ensures that vendors from the AS are reflected accurately in Pleo's Vendors.

## Implementation

* [Vendor Sync Workflow Guide](/docs/current/guides/accounting-integrations/imports/vendor-sync-workflow-guide): workflow context and sequencing
* [How to Fetch and Match Vendors](/docs/current/how-tos/accounting-integrations/imports/vendors/how-to-fetch-and-match-vendors): API usage and step-by-step instructions

## Vendors: Data Mapping

Map the following datapoints from AS vendor records to Pleo Vendors API fields.

| Pleo Vendors API Field  | AS Vendor Datapoint                                                                                    |
| ----------------------- | ------------------------------------------------------------------------------------------------------ |
| `externalId`            | The unique, long-lasting identifier of the vendor in the AS. Used for matching.                        |
| `code`                  | The account code assigned to the vendor in the AS, shown to users to help identify the correct record. |
| `name`                  | Official name of the vendor as recorded in the AS                                                      |
| `country`               | Country of the vendor (ISO 3166-1 alpha-2 country code)                                                |
| `defaultCurrency`       | Default currency for the vendor's financial operations (ISO 4217 currency code, 3 letters)             |
| `registrationNumber`    | The vendor's registration number in its country, if available                                          |
| `taxRegistrationNumber` | The vendor's VAT / GST / Tax ID number, if available                                                   |

### Using externalId and code

`code` and `externalId` can be the same value if the AS has no separate stable identifier beyond the account code. `externalId` is what Pleo uses for matching, so it must never change for a given vendor across sync runs.

Only set `code` and `externalId` to the same value if the AS's account codes are themselves immutable. If the AS can renumber account codes (for example, during a chart-of-accounts reorganisation), do not use the code as `externalId`. Use a separate, AS-internal record identifier that does not change when the code does, so matching continues to work after a renumbering event.

<VendorSyncDataMappingExternalIdDiagram />

### Handling Invalid AS Field Values

This mapping assumes the AS returns valid values for each field. If an AS vendor record has a blank, malformed, or non-ISO `country` or `defaultCurrency` (for example, a legacy record with no country set, or a free-text currency name instead of an ISO 4217 code), do not fail the entire sync run and do not write the invalid value into Pleo as-is.

* `country` is optional on the Vendors API. Skip writing it for that vendor, log it for investigation, and still process the vendor's other valid fields and matching/state transition normally.
* `defaultCurrency` is required on the Vendors API (`VendorCreateRequest` and `VendorUpdateRequest` both reject a request that omits it), so it can't simply be skipped. Either skip the create or update for that vendor and log it for investigation, or send a fallback value and continue: fall back to the Vendor's existing `defaultCurrency` already on Pleo (update only), or to a fallback currency your integration preconfigures for the company. Log the invalid value for investigation either way.

Treat a required field being unusable as a per-vendor data-quality issue, not a reason to abort the run or silently guess a value.

<VendorSyncDataMappingInvalidFieldsDiagram />

## Matching Field

Vendors are matched to their AS counterparts using the **`externalId`** field on both ends.

The `externalId` is the stable identifier used to track a vendor across sync runs, even if its name, code, or other details change.

## Vendor State

| Pleo Vendors API Field | When to Use                                                                                                                                                             |
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `state: ACTIVE`        | Set automatically by Pleo when a Vendor is created with an `externalId`. Used for every vendor synced from the AS.                                                      |
| `state: ARCHIVED`      | Use when archiving Vendors that no longer have a matching active vendor in the AS, or that were previously synced but have since been deleted, archived, or deactivated |

<RememberCallout title="Remember">
  `state: DRAFT` is not produced by Vendor Sync. It only occurs when a vendor is created directly in Pleo without an `externalId`, as covered in [Vendor Creation](/docs/current/integration-design/exports/vendors/integration-design-vendor-creation-overview).
</RememberCallout>

***

## What Comes Next?

* [Vendor Sync Periodicity and Scheduling](/docs/current/integration-design/accounting-integrations/imports/vendors/integration-design-vendor-sync-periodicity)

***

## Related Reading

* [Sync Vendors](/docs/current/integration-design/accounting-integrations/imports/vendors/integration-design-vendor-sync)
* [Vendor Sync Workflow Guide](/docs/current/guides/accounting-integrations/imports/vendor-sync-workflow-guide)
* [Platform Capabilities: Vendor Sync](/docs/current/platform/accounting-integrations/imports/vendors/vendor-sync-overview)

***
