> This page is for version V1 (default).
> For other versions, use one of these documentation indexes:
> - V1 (default): https://docs.ottimate.com/v-1/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.ottimate.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.ottimate.com/_mcp/server.

# Vendors

## Overview

A **vendor** represents an organization that provides goods or services to a company. Vendors issue invoices that flow through Ottimate's AP automation workflow. Before you can create invoices in Ottimate, the associated vendor must exist in the system.

**Key Characteristics:**

* Vendors are **company-specific** - each company maintains its own vendor list
* Vendors must be synced from your ERP to enable invoice export
* The `erp_vendor_id` links Ottimate vendors to your accounting system
* Vendors are identified by `id` (Ottimate-assigned) or `erp_vendor_id` (your ERP's ID)

---

## Vendor Data Flow

Understanding when and how vendor data flows between systems:

```
ERP/Accounting System                    Ottimate
┌──────────────────────┐              ┌──────────────────────┐
│                      │              │                      │
│  Vendor Master List  │──── Sync ───▶│  Ottimate Vendors    │
│                      │              │                      │
│  - Vendor ID         │              │  - id (Ottimate)     │
│  - Vendor Name       │              │  - erp_vendor_id     │
│  - Payment Terms     │              │  - erp_vendor_name   │
│  - Contact Info      │              │  - net_terms         │
│                      │              │                      │
└──────────────────────┘              └──────────────────────┘
                                               │
                                               ▼
                                      ┌──────────────────────┐
                                      │  Invoice Created     │
                                      │  with vendor info    │
                                      └──────────────────────┘
                                               │
                                               ▼
                                      ┌──────────────────────┐
                                      │  Approved invoice    │
                                      │  exported to ERP     │
                                      │  using erp_vendor_id │
                                      └──────────────────────┘
```

---

## Sync Patterns

### Ottimate-Hosted ERP Integrations

When you use an [Ottimate-hosted integration](https://ottimate.com/integrations/) (e.g., QuickBooks, NetSuite, Sage), Ottimate automatically syncs vendors from your ERP:

* **Initial sync** happens during onboarding
* **Ongoing sync** keeps vendors updated automatically
* **No API calls needed** - vendor management is handled by the integration

In this scenario, you primarily use the Vendors API to **read** vendor data for reference or validation.

### Custom ERP Integrations

If you're building a custom integration with an unsupported ERP, you're responsible for syncing vendors:

1. **Extract** vendor data from your ERP
2. **Transform** to Ottimate's vendor format
3. **Load** via the Vendors API (`POST /v1/vendors` or `POST /v1/vendors/bulk`)
4. **Maintain** ongoing sync as vendors are added/updated in your ERP

> **Note**
>
> Keep vendor data consistent between Ottimate and your ERP. Mismatched vendor names or IDs can cause issues during invoice export.

---

## Vendor Fields

### Required Fields

| Field                 | Type    | Description                                      |
| --------------------- | ------- | ------------------------------------------------ |
| `ottimate_company_id` | integer | The company this vendor belongs to               |
| `erp_vendor_name`     | string  | Vendor name (should match your ERP)              |
| `erp_vendor_id`       | string  | Unique vendor ID from your ERP/accounting system |

### Optional Fields

| Field       | Type   | Description                                      |
| ----------- | ------ | ------------------------------------------------ |
| `email`     | string | Vendor contact email                             |
| `phone`     | string | Vendor contact phone                             |
| `net_terms` | string | Payment terms (e.g., "Net 30", "Due on receipt") |

### Response Fields

| Field | Type    | Description                                                                   |
| ----- | ------- | ----------------------------------------------------------------------------- |
| `id`  | integer | Ottimate-assigned vendor ID (use as `ottimate_vendor_id` in invoice creation) |

---

## API Operations

### List Vendors

Retrieve all vendors for a company:

```bash
GET /v1/vendors?ottimate_company_id=123
```

**Response:**

```json
{
  "version": "1.0.0",
  "count": 100,
  "page": 1,
  "limit": 20,
  "vendors": [
    {
      "id": 169860239,
      "erp_vendor_name": "Sysco Foods Corp",
      "erp_vendor_id": "SYS-001",
      "ottimate_company_id": 123
    },
    {
      "id": 169860240,
      "erp_vendor_name": "US Foods Inc",
      "erp_vendor_id": "USF-002",
      "ottimate_company_id": 123
    }
  ]
}
```

### Get Single Vendor

Retrieve a specific vendor by Ottimate ID:

```bash
GET /v1/vendors/169860239
```

**Response:**

```json
{
  "version": "1.0.0",
  "vendor": {
    "id": 169860239,
    "erp_vendor_name": "Sysco Foods Corp",
    "erp_vendor_id": "SYS-001",
    "ottimate_company_id": 123
  }
}
```

### Create Single Vendor

Create a new vendor:

```bash
POST /v1/vendors
Content-Type: application/json

{
  "ottimate_company_id": 123,
  "erp_vendor_name": "New Food Supplier Inc",
  "erp_vendor_id": "NFS-001",
  "email": "orders@newfoodsupplier.com",
  "phone": "+1-555-123-4567",
  "net_terms": "Net 30"
}
```

**Response (201 Created):**

```json
{
  "version": "1.0.0",
  "vendor": {
    "id": 169860250,
    "erp_vendor_name": "New Food Supplier Inc",
    "erp_vendor_id": "NFS-001",
    "ottimate_company_id": 123,
    "email": "orders@newfoodsupplier.com",
    "phone": "+1-555-123-4567",
    "net_terms": "Net 30"
  }
}
```

### Bulk Create/Update Vendors

Create or update multiple vendors in a single request. This endpoint uses **upsert behavior** - existing vendors (matched by `erp_vendor_id`) are updated, new vendors are created.

```bash
POST /v1/vendors/bulk
Content-Type: application/json

{
  "ottimate_company_id": 123,
  "vendors": [
    {
      "erp_vendor_name": "Local Produce Co",
      "erp_vendor_id": "LPC-001"
    },
    {
      "erp_vendor_name": "Premium Meats LLC",
      "erp_vendor_id": "PML-001"
    },
    {
      "erp_vendor_name": "Sysco Foods Corp (Updated)",
      "erp_vendor_id": "SYS-001"
    }
  ]
}
```

**Response (201 Created):**

```json
{
  "version": "1.0.0",
  "success_count": 3,
  "created_count": 2,
  "updated_count": 1,
  "error_count": 0,
  "created": [
    {
      "id": 169860251,
      "erp_vendor_name": "Local Produce Co"
    },
    {
      "id": 169860252,
      "erp_vendor_name": "Premium Meats LLC"
    }
  ],
  "updated": [
    {
      "id": 169860239,
      "erp_vendor_name": "Sysco Foods Corp (Updated)"
    }
  ],
  "errors": []
}
```

**Partial Failure Response (207 Multi-Status):**

If some vendors fail validation, you'll receive a 207 response:

```json
{
  "version": "1.0.0",
  "success_count": 1,
  "created_count": 1,
  "updated_count": 0,
  "error_count": 1,
  "created": [
    {
      "id": 169860253,
      "erp_vendor_name": "Seafood Distributors"
    }
  ],
  "updated": [],
  "errors": [
    {
      "index": 1,
      "erp_vendor_id": null,
      "error": "erp_vendor_id is required",
      "type": "validation_error"
    }
  ]
}
```

---

## Net Terms

The `net_terms` field defines payment terms negotiated with the vendor. When provided, Ottimate automatically calculates invoice due dates.

**Accepted Formats:**

| Format              | Example           | Calculation                     | Invoice Date | Due Date   |
| ------------------- | ----------------- | ------------------------------- | ------------ | ---------- |
| `Net <days>`        | Net 10            | Days after invoice date         | 2024-12-01   | 2024-12-11 |
| `n <days>`          | n 10              | Days after invoice date         | 2024-12-01   | 2024-12-11 |
| `<days>`            | 10                | Days after invoice date         | 2024-12-01   | 2024-12-11 |
| `Due on receipt`    | Due on receipt    | Same as invoice date            | 2024-12-01   | 2024-12-01 |
| `EOM <days>`        | eom 10            | Days after end of invoice month | 2024-12-01   | 2025-01-10 |
| `<days> next month` | Net 10 next month | Day of following month          | 2024-12-01   | 2025-01-10 |
| `<day> of month`    | 10th of month     | Next occurrence of that day     | 2024-12-01   | 2024-12-10 |

> **Note**
>
> Net terms are optional. If not provided, invoice due dates must be set manually or calculated by your integration.

---

## Best Practices

* **Sync vendors before invoices** - Ensure vendors exist in Ottimate before creating invoices that reference them.
* **Use the bulk endpoint for efficiency** - When syncing multiple vendors, use the bulk endpoint to reduce API calls.
* **Match ERP identifiers exactly** - The `erp_vendor_id` must match your ERP's vendor ID for successful invoice export.
* **Keep names consistent** - Use the same vendor name in Ottimate as in your ERP to avoid confusion during reconciliation.
* **Cache vendor mappings** - Fetch and cache the vendor list at integration startup to avoid repeated API calls.
* **Handle partial failures** - When using the bulk endpoint, check the `errors` array and handle failed vendors appropriately.
* **Set net_terms for automation** - Providing payment terms enables automatic due date calculation.

---