> ## 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 Creation Workflow Guide

> The end-to-end sequence for this workflow: detecting a DRAFT Vendor in Pleo, creating it in the AS, and activating it back in Pleo.

export const ActivateVendorInPleoDiagramNonClickable = () => {
  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 s2Fill = isDark ? "#212222" : "#EEF4F4";
  const s2Stroke = isDark ? "#848989" : "#212222";
  const s2TextStyle = isDark ? ",color:#EEF4F4" : ",color:#212222";
  const linkStyle = isDark ? "" : "linkStyle default stroke:#848989,stroke-width:1px;";
  const diagram = `
%%{init: {"themeVariables": {"fontSize": "10px"}}}%%
flowchart LR
    S1["1. Activate Vendor in Pleo<br>(code + externalId)"] --> S2["Vendor state: ACTIVE"]

style S1 white-space:normal,fill:${nodeFill},stroke:${nodeStroke}${nodeTextStyle}
style S2 white-space:normal,fill:${s2Fill},stroke:${s2Stroke},stroke-dasharray:5 5${s2TextStyle}
${linkStyle}
`;
  return <Mermaid chart={diagram} />;
};

export const CreateVendorInASDiagramNonClickable = () => {
  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 s2Fill = isDark ? "#212222" : "#EEF4F4";
  const s2Stroke = isDark ? "#848989" : "#212222";
  const s2TextStyle = isDark ? ",color:#EEF4F4" : ",color:#212222";
  const linkStyle = isDark ? "" : "linkStyle default stroke:#848989,stroke-width:1px;";
  const diagram = `
%%{init: {"themeVariables": {"fontSize": "10px"}}}%%
flowchart LR
    S1["1. Create Vendor in the AS"] --> S2["AS-assigned externalId<br>(+ optional code)"]

style S1 white-space:normal,fill:${nodeFill},stroke:${nodeStroke}${nodeTextStyle}
style S2 white-space:normal,fill:${s2Fill},stroke:${s2Stroke},stroke-dasharray:5 5${s2TextStyle}
${linkStyle}
`;
  return <Mermaid chart={diagram} />;
};

export const DetectDraftVendorOptionsDiagramNonClickable = () => {
  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 outerFill = isDark ? "#212222" : "#EEF4F4";
  const outerStroke = isDark ? "#848989" : "#212222";
  const outerTextStyle = isDark ? ",color:#EEF4F4" : ",color:#212222";
  const linkStyle = isDark ? "" : "linkStyle default stroke:#848989,stroke-width:1px;";
  const diagram = `
%%{init: {"themeVariables": {"fontSize": "10px"}}}%%
flowchart LR
    A["Choose Discovery<br>Strategy"] --> B["Option A: Webhook<br>Trigger (Recommended)"]
    A --> C["Option B: Polling<br>(fallback)"]
    B --> D["Create Vendor<br>in AS"]
    C --> D

style A white-space:normal,fill:${outerFill},stroke:${outerStroke},stroke-dasharray:5 5${outerTextStyle}
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:${outerFill},stroke:${outerStroke},stroke-dasharray:5 5${outerTextStyle}
${linkStyle}
`;
  return <Mermaid chart={diagram} />;
};

export const CreateVendorInPleoDiagramNonClickable = () => {
  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 s3Fill = isDark ? "#212222" : "#EEF4F4";
  const s3Stroke = isDark ? "#848989" : "#212222";
  const s3TextStyle = isDark ? ",color:#EEF4F4" : ",color:#212222";
  const linkStyle = isDark ? "" : "linkStyle default stroke:#848989,stroke-width:1px;";
  const diagram = `
%%{init: {"themeVariables": {"fontSize": "10px"}}}%%
flowchart LR
    S1["1. Verify Vendor<br>doesn't already exist"] --> S2["2. Create the<br>new Vendor"] --> S3["Vendor state: DRAFT"]

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:${s3Fill},stroke:${s3Stroke},stroke-dasharray:5 5${s3TextStyle}
${linkStyle}
`;
  return <Mermaid chart={diagram} />;
};

export const VendorCreationOverviewDiagram = () => {
  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": "12px"}}}%%
flowchart LR

subgraph Pleo1["Pleo"]
    A["1. Create Vendor<br>in Pleo"]
end

subgraph Integration["Integration"]
    B["2. Detect Draft<br>Vendor"]
    C["3. Create Vendor<br>in AS"]
    B --> C
end

subgraph Pleo2["Pleo"]
    D["4. Activate Vendor<br>in Pleo"]
end

A --> B
C --> D

click A "#1-create-vendor-in-pleo"
click B "#2-detect-draft-vendor"
click C "#3-create-vendor-in-as"
click D "#4-activate-vendor-in-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 Pleo1 fill:${subgraphFill},stroke:${subgraphStroke}${subgraphTextStyle}
style Integration fill:${subgraphFill},stroke:${subgraphStroke}${subgraphTextStyle}
style Pleo2 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 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>;

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 the Pleo → Accounting System half of [Integration Level 4](/docs/current/getting-started/accounting-integrations-overview): creating a vendor in your Accounting System (AS) when a bookkeeper adds a new one directly in Pleo.
</RecommendedCallout>

<RememberCallout title="Remember">
  This guide covers Vendor Creation only. For the complementary Accounting System → Pleo direction, where existing vendors are kept in sync, see the [Vendor Sync Workflow Guide](/docs/current/guides/accounting-integrations/imports/vendor-sync-workflow-guide).
</RememberCallout>

## What You'll Have Built

After implementing this workflow:

* New vendors added directly in Pleo are detected reliably, ideally the moment they are created.
* Each new vendor is created in the Accounting System without manual data entry.
* The corresponding Pleo Vendor is activated as soon as creation succeeds, using the identifiers assigned by the AS.
* The integration aligns with Pleo's Vendor Creation guarantees.

## 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 [Vendor Creation](/docs/current/platform/exports/vendors/vendor-creation-overview) platform capabilities page.
* How to configure [webhook subscriptions](/reference/webhooks/overview-webhooks#configuring-webhooks-during-integration).

## Vendor Creation Workflow Overview

Vendor Sync assumes a vendor already exists in the AS. But bookkeepers sometimes need to tag an expense to a vendor that doesn't exist anywhere yet. When that happens, they add it directly in Pleo, and Pleo creates it in `DRAFT` state, since it has no `code` or `externalId` until the AS creates the matching record.

Vendor Creation is the integration's job of turning that `DRAFT` vendor into a real record in the AS, then confirming back to Pleo that it's ready to use.

Unlike the expense Export workflow, there is no job or batch here. Each new vendor is a single, independent event, detected and processed on its own.

<VendorCreationOverviewDiagram />

The how-to articles in this section use a consistent example to illustrate each step: a bookkeeper adds "Greenfield Logistics" as a new vendor in Pleo.

| Step                       | Action                                                           | Outcome                                                    |
| -------------------------- | ---------------------------------------------------------------- | ---------------------------------------------------------- |
| 1. Create Vendor in Pleo   | A bookkeeper adds a new vendor directly in Pleo                  | The vendor exists in Pleo in `DRAFT` state                 |
| 2. Detect Draft Vendor     | Detects the new `DRAFT` vendor via webhook or polling            | The vendor's details are ready to be created in the AS     |
| 3. Create Vendor in AS     | Creates the corresponding vendor record in the Accounting System | The AS assigns an identifier and, where applicable, a code |
| 4. Activate Vendor in Pleo | Reports the `code` and `externalId` back to Pleo                 | The Pleo Vendor transitions from `DRAFT` to `ACTIVE`       |

***

## Steps

### 1. Create Vendor in Pleo

#### Purpose

This step is the trigger event for the rest of Vendor Creation: a bookkeeper adds a new vendor directly in Pleo, one that doesn't exist in the Accounting System yet.

#### Input

* The vendor's name, country, and currency, entered by the bookkeeper
* Optionally, a tax number and registration number

#### Workflow Process

<CreateVendorInPleoDiagramNonClickable />

#### Output

* A new Vendor exists in Pleo with `state: DRAFT`
* The Vendor has no `code` or `externalId` yet
* A `v1.vendor.created` webhook event is emitted

#### Why It Matters

Until a bookkeeper takes this action, there is no `DRAFT` vendor for your integration to detect. This is a product action, not something your integration builds, but the rest of this workflow only runs in response to it.

#### Step-by-Step Instructions

<WhatComesNext href="/docs/current/how-tos/accounting-integrations/vendors/how-to-create-vendors-in-pleo">
  How to Create Vendors in Pleo
</WhatComesNext>

***

### 2. Detect Draft Vendor

#### Purpose

This step runs whenever a bookkeeper adds a new vendor in Pleo that has no matching record in the AS yet. The integration must detect this `DRAFT` vendor before it can create the corresponding record in the AS.

#### Input

* A vendor created in Pleo with `state: DRAFT`
* A `v1.vendor.created` webhook notification (preferred), or a scheduled polling trigger on a controlled interval of every 5 minutes if webhooks are not used (see [Detect Draft Vendors](/docs/current/integration-design/exports/vendors/integration-design-vendor-creation-detect-draft-vendors) for the full polling contract, including the shared 600 requests/minute budget with Vendor Sync)

#### Workflow Process

<DetectDraftVendorOptionsDiagramNonClickable />

#### Output

* A `DRAFT` vendor identified and ready for creation in the AS, with its `name`, `country`, `defaultCurrency`, `registrationNumber`, and `taxRegistrationNumber` available

#### Why It Matters

Until this vendor is detected, it cannot be created in the AS, and the bookkeeper cannot use it for bookkeeping. Detecting it via webhook, rather than waiting for the next scheduled poll, gets the vendor usable as quickly as possible.

#### Integration Design

If you're an integration developer or architect, read the [Detect Draft Vendors](/docs/current/integration-design/exports/vendors/integration-design-vendor-creation-detect-draft-vendors) integration design doc before implementing this step. It covers the detection mechanisms (webhook and polling) and why detection must not modify vendor state.

#### 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/vendors/how-to-detect-draft-vendors">
  How to Detect Draft Vendors
</WhatComesNext>

***

### 3. Create Vendor in AS

#### Purpose

Using the details from the detected `DRAFT` vendor, the integration creates the corresponding vendor record in the Accounting System.

#### Input

* The `DRAFT` vendor's `name`, `country`, `defaultCurrency`, `registrationNumber`, and `taxRegistrationNumber`
* A valid connection to the Accounting System

#### Workflow Process

<CreateVendorInASDiagramNonClickable />

#### Output

* A new vendor record created in the AS
* An AS-assigned identifier for the new record, to be used as the Pleo `externalId`
* Optionally, an AS-assigned account code, to be used as the Pleo `code`

#### Why It Matters

This is the step where the vendor becomes real: a record that the Accounting System, and eventually the bookkeeper, can rely on for accounting purposes.

#### Integration Design

If you're an integration developer or architect, read the [Create and Activate Vendors](/docs/current/integration-design/exports/vendors/integration-design-vendor-creation-create-and-activate) integration design doc before implementing this step. It covers the data mapping, and how to handle a failed creation attempt.

#### Step-by-Step Instructions

<WhatComesNext href="/docs/current/how-tos/accounting-integrations/vendors/how-to-create-vendor-in-as">
  How to Create a Vendor in the AS
</WhatComesNext>

***

### 4. Activate Vendor in Pleo

#### Purpose

Once the vendor exists in the AS, the integration reports its identifiers back to Pleo, transitioning the Vendor from `DRAFT` to `ACTIVE`.

#### Input

* The `externalId` assigned by the AS (required)
* The `code` assigned by the AS, if available (optional)

#### Workflow Process

<ActivateVendorInPleoDiagramNonClickable />

#### Output

* The Pleo Vendor's `state` transitions to `ACTIVE`
* The vendor becomes available for bookkeepers to tag on expenses and invoices, provided Vendor Tagging is enabled for the company. See [How to Enable Vendor-Based Bookkeeping](/docs/current/how-tos/accounting-integrations/how-to-enable-vendor-based-bookkeeping)
* The vendor becomes eligible to be matched by future Vendor Sync runs

#### Why It Matters

Without activation, the vendor stays stuck in `DRAFT` in Pleo even though it now exists in the AS. A bookkeeper can still tag an expense with a `DRAFT` vendor and export it, but the integration must reject that export item with `failureReasonType: vendor_unknown` (see [How to Update Export Items](/docs/current/how-tos/accounting-integrations/how-to-update-export-items-for-as-erp-processing#2-build-update-payload)) until the vendor is activated. Activation is the signal that closes the loop and lets that export succeed.

#### Integration Design

If you're an integration developer or architect, read the [Create and Activate Vendors](/docs/current/integration-design/exports/vendors/integration-design-vendor-creation-create-and-activate) integration design doc before implementing this step. It covers the activation request, and how it connects back into Vendor Sync.

#### Step-by-Step Instructions

<WhatComesNext href="/docs/current/how-tos/accounting-integrations/vendors/how-to-activate-vendor-in-pleo">
  How to Activate a Vendor in Pleo
</WhatComesNext>

***

## Observability and Recovery

Build in enough visibility to detect and recover from failures without manual database inspection:

* **Correlation ID:** carry a single identifier for each vendor's DRAFT-to-ACTIVE lifecycle, from detection through creation and activation, so all log lines for one vendor's journey can be traced together.
* **Stuck-DRAFT alerting:** alert if a `DRAFT` vendor remains unactivated beyond a defined threshold (for example, several detection cycles or a fixed time window). This usually indicates a failed AS creation call, a permissions issue, or a stuck retry, and won't otherwise surface until a bookkeeper notices the vendor is unusable.
* **Audit trail:** for each vendor, log the detection event, the AS creation attempt (success or failure), and the activation call, so the full DRAFT-to-ACTIVE history can be reconstructed later.

## What Comes Next?

Once Vendor Creation is live, bookkeepers can add new vendors in Pleo at any time and use them for bookkeeping as soon as the integration activates them.

To complete Level 4, also implement the complementary direction:

* [Vendor Sync Workflow Guide](/docs/current/guides/accounting-integrations/imports/vendor-sync-workflow-guide): keep existing AS vendors, including this newly created one, in sync with Pleo going forward.

***

## Related Reading

* [Integration Design: Vendor Creation Overview](/docs/current/integration-design/exports/vendors/integration-design-vendor-creation-overview)
* [Platform Capabilities: Vendor Creation](/docs/current/platform/exports/vendors/vendor-creation-overview)

***
