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

# Create and Activate Vendors

> How to create a vendor in the Accounting System from a DRAFT Pleo vendor, then activate it back in Pleo, including failure handling.

export const VendorCreationProcessingOrderDiagram = () => {
  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": "12px"}}}%%
flowchart TD
    A[DRAFT vendor detected] --> B[Create vendor in AS]
    B -->|Success| C[Activate Vendor in Pleo<br>code + externalId]
    B -->|Failure| D[Leave vendor as DRAFT<br>retry Step 1 on next detection]
    C -->|Success| E[Vendor state: ACTIVE]
    C -->|Failure/unknown| F[Persist AS externalId + code<br>retry Step 2 only, do not re-create in AS]

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

export const VendorCreationExportBeforeActivationDiagram = () => {
  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[Bookkeeper tags expense<br>with a DRAFT vendor] --> B[Expense included<br>in an export job]
    B --> C{Does the item's vendor<br>have an externalId?}
    C -->|"Yes: exists in the AS"| D[Export the item against<br>the AS vendor record]
    C -->|"No: externalId is empty"| E["Fail the export item:<br>failureReasonType vendor_unknown"]
    E --> F[Step 1 + Step 2 above<br>create and activate the vendor]
    F --> G[Retry the export item]
    G --> C
    C -.->|"No: externalId is empty (avoid this)"| H["BUG (avoid this): create the<br>AS vendor from this failure"]

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

export const VendorCreationInteractionWithSyncDiagram = () => {
  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[Step 1 succeeds, Step 2<br>fails or times out] --> B[AS vendor exists,<br>Pleo vendor still DRAFT]
    B --> C[Later, non-overlapping<br>Vendor Sync run]
    C --> D[Sync sees AS vendor as unmatched]
    D --> E{Is a mitigation in place?}
    E -->|"No: the gap<br>(avoid this)"| F["BUG (avoid this): Sync creates<br>a duplicate Pleo Vendor"]
    E -->|"Yes: lock held for full<br>pending-activation lifetime"| G[Sync run blocked until<br>activation resolves]
    E -->|"Yes: Sync cross-checks<br>pending-activation identifiers"| H[Sync skips creation]

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

export const VendorCreationActivationRetryDiagram = () => {
  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[Step 1 succeeds] --> B[Persist externalId + code<br>against the Pleo id]
    B --> C[Call activate]
    C -->|Succeeds| D[Vendor state: ACTIVE]
    C -->|Fails / times out / unknown| E[Do not re-run Step 1]
    E --> F[Retry activate only,<br>using stored identifiers]
    F --> C
    C -->|"Fails / times out / unknown,<br>re-run Step 1 (avoid this)"| G["BUG (avoid this): second AS<br>vendor record created"]

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

export const VendorCreationRetryCreationDiagram = () => {
  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[Retry vendor creation] --> B{Do we know whether a prior<br>attempt created an AS record?}
    B -->|Yes: record exists| C[Reuse known AS vendor]
    B -->|Yes: no record created| D[Create new AS vendor]
    B -->|Unknown| E[Look up AS vendor by stored<br>Pleo id + companyId]
    E -->|Match found| C
    E -->|No match| D
    B -->|"Unknown, skip lookup (avoid this)"| F["BUG (avoid this): duplicate<br>AS vendor created"]

   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:${nodeFill},stroke:${nodeStroke}${nodeTextStyle}
   style F 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 integrations create a vendor in the Accounting System from a `DRAFT` Pleo vendor, then activate the corresponding Vendor in Pleo.

This covers the **second and third steps** in the Vendor Creation workflow, run immediately after a `DRAFT` vendor is detected.

## Implementation

See the corresponding how-to articles for API usage and step-by-step instructions:

* [How to Create a Vendor in the AS](/docs/current/how-tos/accounting-integrations/vendors/how-to-create-vendor-in-as)
* [How to Activate a Vendor in Pleo](/docs/current/how-tos/accounting-integrations/vendors/how-to-activate-vendor-in-pleo)

## Data Mapping for Vendor Creation

The `DRAFT` vendor in Pleo already contains everything needed to create the record in the AS.

| Pleo Vendor Field       | AS Vendor Datapoint                                                                        |
| ----------------------- | ------------------------------------------------------------------------------------------ |
| `name`                  | Official name of the vendor                                                                |
| `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, if provided                                              |
| `taxRegistrationNumber` | The vendor's VAT / GST / Tax ID number, if provided                                        |

A `DRAFT` vendor has no `code` or `externalId` yet. Both are assigned by the AS once the record is created there.

## Step 1: Create the Vendor in the AS

Using the fields above, create the corresponding vendor record in the Accounting System.

### Output

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

<RememberCallout title="Remember">
  If the AS has no separate stable identifier beyond the account code, `code` and `externalId` can be the same value.
</RememberCallout>

## Step 2: Activate the Vendor in Pleo

Report the identifiers assigned by the AS back to Pleo so the Vendor transitions from `DRAFT` to `ACTIVE`.

| Pleo Vendors API Field | Requirement                                                                    |
| ---------------------- | ------------------------------------------------------------------------------ |
| `externalId`           | Required. The identifier assigned to the new vendor by the AS.                 |
| `code`                 | Optional. The account code assigned to the new vendor by the AS, if available. |

### Output

* The Pleo Vendor's `state` transitions to `ACTIVE`
* The Vendor becomes available for bookkeepers to tag on expenses and invoices
* The vendor is now eligible to be picked up by future [Vendor Sync](/docs/current/integration-design/accounting-integrations/imports/vendors/integration-design-vendor-sync-overview) runs, matched by `externalId`

<RememberCallout title="Remember">
  This create-and-activate step must not run concurrently with [Vendor Sync](/docs/current/integration-design/accounting-integrations/imports/vendors/integration-design-vendor-sync) for the same company. Overlapping execution can cause Sync to create a duplicate Vendor for an AS record still in flight here, or archive a Vendor this flow just activated if Sync's AS fetch has not yet caught up. Use the same per-company concurrency lock for both workflows.
</RememberCallout>

## Failure Handling

Step 1 (AS creation) and Step 2 (activation in Pleo) can each fail independently, and each failure mode needs different handling to avoid duplicate records or a vendor stuck in limbo.

### If AS Creation Fails

If creating the vendor in the AS fails, the integration must not call activate. The vendor remains `DRAFT` in Pleo and should be retried on the next detection cycle.

Retries must not create duplicate vendor records in the AS. If the integration cannot confirm whether a previous attempt already created the record, check for an existing AS vendor with matching details before creating a new one. "Matching details" must be exact, not fuzzy: where the Accounting System supports a custom reference or memo field on vendor records, the integration must store the `DRAFT` vendor's Pleo `id` (and its `companyId`, for integrations serving multiple Pleo companies against the same AS) on the AS vendor record at creation time, and use that stored `id` (and `companyId`) for retry lookups instead of matching on `name`, which can produce false positives or false negatives.

<VendorCreationRetryCreationDiagram />

### If Activation Fails

AS creation succeeding is not the same as the vendor being fully created. The vendor is only done once activation in Pleo has also succeeded.

If the `:activate` call fails, times out, or its outcome is unknown (for example, a network error after the request was sent), the integration must not re-run Step 1 and create a second AS record. Instead, persist the AS-assigned `externalId` (and `code`, if returned) durably as soon as Step 1 succeeds, and retry only Step 2, the `:activate` call, using those stored identifiers, on the next detection cycle or a dedicated retry job.

A `DRAFT` vendor whose AS record already exists must be distinguishable, at retry time, from one that still needs AS creation. Storing the AS-assigned identifiers against the Pleo `id` as soon as they exist is what makes that distinction possible.

<VendorCreationActivationRetryDiagram />

### Interaction with Vendor Sync

The per-company concurrency lock with Vendor Sync (see Step 2 above) only prevents literally overlapping execution. It does not, by itself, prevent a **later, non-overlapping** Vendor Sync run from creating a duplicate Vendor: if Step 1 succeeds but Step 2 fails or times out, the AS vendor now exists while the Pleo vendor is still `DRAFT` and therefore invisible to Sync's `ACTIVE`/`ARCHIVED` matching. A Sync run any time after that failure, not just a concurrent one, will see that AS vendor as unmatched and create a duplicate Pleo Vendor for it.

To close this gap, either:

* Hold the per-company lock for the full lifetime of a pending activation, not just for the duration of the Step 1/Step 2 calls, releasing it only once activation succeeds or the `DRAFT` vendor is abandoned per your retry-abandonment policy; or
* Have Vendor Sync's matching step cross-check pending-activation AS identifiers (the ones persisted above) before creating, and skip creation for any AS vendor already claimed by an in-flight or retryable Vendor Creation attempt.

<VendorCreationInteractionWithSyncDiagram />

### Interaction with Expense Export

A bookkeeper can tag an expense with a `DRAFT` vendor and submit it for export before Step 1 and Step 2 above have completed. Pleo does not block this.

The export item's vendor object has no `state` field, so the integration cannot check for `DRAFT` or `ACTIVE` directly. Check `externalId` instead: an empty `externalId` means the vendor doesn't exist in the AS yet. In that case, reject the export item rather than attempting to post it. Report it back to Pleo 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)). Once Step 1 and Step 2 complete, the vendor's `externalId` is populated, and a later export of that same item can succeed.

<VendorCreationExportBeforeActivationDiagram />

<RememberCallout title="Remember">
  Do not create the AS vendor record as a side effect of this export failure. Vendor creation and activation stay driven by Step 1 and Step 2 above, on their own detection cycle, not by an export attempt hitting a `DRAFT` vendor.
</RememberCallout>

## Processing Order

<VendorCreationProcessingOrderDiagram />

## Upstream Dependencies

* A `DRAFT` vendor detected in Pleo
* A valid connection to the Accounting System

## Downstream Dependencies

* Vendor Tagging and Accounts Payable bookkeeping, once the Vendor is `ACTIVE`
* Future Vendor Sync runs, which will now match this Vendor by `externalId`

***

## What Comes Next?

Once Vendor Creation is implemented, review [Vendor Sync](/docs/current/integration-design/accounting-integrations/imports/vendors/integration-design-vendor-sync-overview) to ensure newly activated vendors stay up to date over time.

***

## Related Reading

* [How to Create a Vendor in the AS](/docs/current/how-tos/accounting-integrations/vendors/how-to-create-vendor-in-as)
* [How to Activate a Vendor in Pleo](/docs/current/how-tos/accounting-integrations/vendors/how-to-activate-vendor-in-pleo)
* [Vendor Creation Workflow Guide](/docs/current/guides/vendor-creation-workflow-guide)
* [Platform Capabilities: Vendor Creation](/docs/current/platform/exports/vendors/vendor-creation-overview)

***
