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

# Purchase Order Update API

> Update an existing purchase order by its identifier. Only POs in DRAFTED or DECLINED state can be updated.

## Authentication

All requests require an API key in the request headers.

**Headers:**

```
Authorization: Api-Key YOUR_API_KEY
Content-Type: application/json
```

## Request

**Content-Type:** `application/json`

### Path Parameters

| Parameter | Type   | Required | Description                                                                                              |
| --------- | ------ | -------- | -------------------------------------------------------------------------------------------------------- |
| `poId`    | string | Yes      | The unique slug identifier of the purchase order to update (returned from the PO creation or search API) |

### Body Parameters

All body fields are optional. Only the fields you provide will be updated.

| Parameter            | Type   | Required | Description                                                                                                                                                                                                                                                                          |
| -------------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `poNumber`           | string | No       | Purchase order number (minimum 1 character)                                                                                                                                                                                                                                          |
| `lineItems`          | array  | No       | List of line items. Replaces all existing line items if provided (minimum 1 item)                                                                                                                                                                                                    |
| `poType`             | string | No       | Purchase order type. Valid values: `GOODS`, `SERVICES`                                                                                                                                                                                                                               |
| `matchingType`       | string | No       | Matching type. Valid values: `TWO_WAY`, `THREE_WAY`                                                                                                                                                                                                                                  |
| `poDate`             | string | No       | Purchase order date in ISO-8601 format (YYYY-MM-DD)                                                                                                                                                                                                                                  |
| `vendorId`           | string | No       | Slug identifier of the vendor to link to the PO                                                                                                                                                                                                                                      |
| `description`        | string | No       | Short description for the purchase order (1-255 characters)                                                                                                                                                                                                                          |
| `currency`           | string | No       | ISO 4217 currency code (3 characters, e.g., `INR`)                                                                                                                                                                                                                                   |
| `paymentTerms`       | string | No       | Free form outline of the agreed payment terms                                                                                                                                                                                                                                        |
| `deliveryDate`       | string | No       | Requested delivery date in ISO-8601 format (YYYY-MM-DD)                                                                                                                                                                                                                              |
| `termsAndConditions` | string | No       | Terms and conditions for the purchase order                                                                                                                                                                                                                                          |
| `additionalNotes`    | string | No       | Additional notes for delivery or special requirements                                                                                                                                                                                                                                |
| `state`              | string | No       | Target state: `DRAFTED` or `ACTIVE`. When `ACTIVE` is requested the API validates required fields (merging body with what is already on the PO). If all required fields are present the PO is activated; otherwise it stays in `DRAFTED` and the response includes `submitWarnings`. |
| `tags`               | object | No       | PO-level tags (flex fields). Map of tag slug to a `{ value }` object. See [Tags](#tags) below.                                                                                                                                                                                       |

### Line Items Object

Each item in the `lineItems` array must contain:

| Parameter    | Type   | Required                 | Description                                                                             |
| ------------ | ------ | ------------------------ | --------------------------------------------------------------------------------------- |
| `quantity`   | number | Yes                      | Quantity requested for the line item                                                    |
| `rate`       | number | Yes                      | Unit rate to be applied to the line item                                                |
| `identifier` | string | Yes                      | Free-text label for the line item (minimum 1 character)                                 |
| `skuCode`    | string | Required for `THREE_WAY` | Item code of an existing SKU in your inventory. Takes priority over `skuName`           |
| `skuName`    | string | Required for `THREE_WAY` | Name of an existing SKU in your inventory (used when `skuCode` is not provided)         |
| `tags`       | object | No                       | Line-item-level tags. Map of tag slug to a `{ value }` object. See [Tags](#tags) below. |

> **SKU matching (`THREE_WAY`):** When the PO uses `THREE_WAY` matching and `lineItems` are included in the update, every line item **must** provide `skuCode` or `skuName`, and it **must** resolve to an existing SKU. If any line item is missing both fields or cannot be matched, the request is rejected with a `400` error and the PO is **not updated**.

### Editable States

A purchase order can only be updated when it is in one of the following states:

| State      | Description                                          |
| ---------- | ---------------------------------------------------- |
| `DRAFTED`  | PO is in draft — editable                            |
| `DECLINED` | PO was declined and returned for revision — editable |

Attempting to update a PO in any other state (`PENDING`, `APPROVED`, `CLOSED`, `ARCHIVED`) will return a `400` error.

### Tags

Tags can be applied both at the **PO level** (`tags` in the request body) and at the **line-item level** (`tags` inside each `lineItems` entry). In both cases `tags` is an object that maps a tag slug to a `{ value }` object:

<Info>
  To discover the available tag slugs, their types, and (for `DROPDOWN` tags) the valid value ids, see the tag APIs: the [Tag List API](/apis/tag-list), and [Tag Detail API](/apis/tag-detail).
</Info>

```json theme={null}
{
  "tags": {
    "cost-center": { "value": 42 },
    "project-code": { "value": "PRJ-2024" },
    "expected-by": { "value": "2024-03-15" },
    "budget": { "value": 5000 }
  }
}
```

The `value` you send depends on the tag's type:

| Tag type   | What to send as `value`                             |
| ---------- | --------------------------------------------------- |
| `DROPDOWN` | The tag value **id** (number) of an existing option |
| `VARCHAR`  | Free text (string)                                  |
| `DATETIME` | A date string in `YYYY-MM-DD` format                |

## Code Examples

<CodeGroup>
  ```bash cURL theme={null}
  curl -X PATCH https://api.pazy.io/v1.0/procurement/purchase-order/po_slug_identifier \
    -H "Authorization: Api-Key YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "description": "Updated office supplies order",
      "deliveryDate": "2024-03-01",
      "paymentTerms": "Net 45 days",
      "tags": {
        "cost-center": { "value": 42 },
        "project-code": { "value": "PRJ-2024" }
      },
      "lineItems": [
        {
          "identifier": "SKU-001",
          "quantity": 120,
          "rate": 50.00,
          "tags": {
            "budget-line": { "value": "Stationery" }
          }
        }
      ]
    }'
  ```

  ```javascript JavaScript (Fetch API) theme={null}
  const response = await fetch('https://api.pazy.io/v1.0/procurement/purchase-order/po_slug_identifier', {
    method: 'PATCH',
    headers: {
      'Authorization': 'Api-Key YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      description: 'Updated office supplies order',
      deliveryDate: '2024-03-01',
      paymentTerms: 'Net 45 days',
      tags: {
        'cost-center': { value: 42 },
        'project-code': { value: 'PRJ-2024' }
      },
      lineItems: [
        {
          identifier: 'SKU-001',
          quantity: 120,
          rate: 50.00,
          tags: {
            'budget-line': { value: 'Stationery' }
          }
        }
      ]
    })
  });

  const result = await response.json();
  ```

  ```python Python (requests) theme={null}
  import requests

  url = "https://api.pazy.io/v1.0/procurement/purchase-order/po_slug_identifier"
  headers = {
      "Authorization": "Api-Key YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  payload = {
      "description": "Updated office supplies order",
      "deliveryDate": "2024-03-01",
      "paymentTerms": "Net 45 days",
      "tags": {
          "cost-center": {"value": 42},
          "project-code": {"value": "PRJ-2024"}
      },
      "lineItems": [
          {
              "identifier": "SKU-001",
              "quantity": 120,
              "rate": 50.00,
              "tags": {
                  "budget-line": {"value": "Stationery"}
              }
          }
      ]
  }

  response = requests.patch(url, headers=headers, json=payload)
  result = response.json()
  ```
</CodeGroup>

## Success Response

**HTTP Status:** `200 OK`

**Response Fields:**

| Field                   | Type    | Description                                                                                     |
| ----------------------- | ------- | ----------------------------------------------------------------------------------------------- |
| `ok`                    | boolean | Indicates whether the request was successful                                                    |
| `data`                  | object  | Contains the update response data                                                               |
| `data.poId`             | string  | Unique slug identifier of the updated purchase order                                            |
| `data.state`            | string  | Present when `state` was requested. `ACTIVE` if activation succeeded, `DRAFTED` if it fell back |
| `data.skuMatchWarnings` | array   | Present when one or more line items could not be matched to a SKU                               |
| `data.submitWarnings`   | object  | Present when `state: ACTIVE` was requested but required fields were missing                     |

### `submitWarnings` Object

| Field       | Type             | Description                                                                 |
| ----------- | ---------------- | --------------------------------------------------------------------------- |
| `po`        | array of strings | PO-level fields that were missing (e.g. `"vendorId"`, `"paymentTerms"`)     |
| `lineItems` | object           | Map of line item identifier to missing fields (e.g. `"quantity"`, `"rate"`) |

### Response Example — update only (no state change)

```json theme={null}
{
  "ok": true,
  "data": {
    "poId": "po_slug_identifier"
  }
}
```

### Response Example — activated (`state: "ACTIVE"`, all fields present)

```json theme={null}
{
  "ok": true,
  "data": {
    "poId": "po_slug_identifier",
    "state": "ACTIVE"
  }
}
```

### Response Example — fell back to draft (`state: "ACTIVE"`, fields missing)

```json theme={null}
{
  "ok": true,
  "data": {
    "poId": "po_slug_identifier",
    "state": "DRAFTED",
    "submitWarnings": {
      "po": ["paymentTerms"],
      "lineItems": {}
    }
  }
}
```

## Error Responses

### SKU Required (THREE\_WAY match)

**HTTP Status:** `400 Bad Request`

```json theme={null}
{
  "ok": false,
  "error": {
    "code": "SKU_REQUIRED",
    "message": "skuCode or skuName is required for each line item in a THREE_WAY purchase order. Missing on: \"SKU-001\""
  }
}
```

### SKU Not Found (THREE\_WAY match)

**HTTP Status:** `400 Bad Request`

```json theme={null}
{
  "ok": false,
  "error": {
    "code": "SKU_NOT_FOUND",
    "message": "SKU with item code \"UNKNOWN-CODE\" not found in your inventory"
  }
}
```

### Purchase Order Not Found

**HTTP Status:** `404 Not Found`

```json theme={null}
{
  "ok": false,
  "error": {
    "code": "PURCHASE_ORDER_NOT_FOUND",
    "message": "Purchase order not found"
  }
}
```

### Invalid State

**HTTP Status:** `400 Bad Request`

```json theme={null}
{
  "ok": false,
  "error": {
    "code": "INVALID_STATE",
    "message": "Purchase order cannot be updated in APPROVED state"
  }
}
```

### Invalid Procurement Type

**HTTP Status:** `400 Bad Request`

```json theme={null}
{
  "ok": false,
  "error": {
    "code": "INVALID_PROCUREMENT_TYPE",
    "message": "Invalid procurement type"
  }
}
```

### Invalid Matching Type

**HTTP Status:** `400 Bad Request`

```json theme={null}
{
  "ok": false,
  "error": {
    "code": "INVALID_MATCHING_TYPE",
    "message": "Invalid matching type"
  }
}
```

### Invalid Date

**HTTP Status:** `400 Bad Request`

```json theme={null}
{
  "ok": false,
  "error": {
    "code": "INVALID_DATE",
    "message": "Invalid date"
  }
}
```

### Invalid Currency

**HTTP Status:** `400 Bad Request`

```json theme={null}
{
  "ok": false,
  "error": {
    "code": "INVALID_CURRENCY",
    "message": "Invalid currency Only INR is supported at the moment"
  }
}
```

### Vendor Not Found

**HTTP Status:** `404 Not Found`

```json theme={null}
{
  "ok": false,
  "error": {
    "code": "VENDOR_NOT_FOUND",
    "message": "Vendor not found"
  }
}
```

### Authentication Errors

**HTTP Status:** `401 Unauthorized`

```json theme={null}
{
  "ok": false,
  "error": {
    "code": "MISSING_CREDENTIALS",
    "message": "Missing Credentials"
  }
}
```

```json theme={null}
{
  "ok": false,
  "error": {
    "code": "INVALID_API_KEY",
    "message": "Invalid API Key"
  }
}
```

### Permission Errors

**HTTP Status:** `403 Forbidden`

```json theme={null}
{
  "ok": false,
  "error": {
    "code": "INSUFFICIENT_PERMISSIONS",
    "message": "Permission check failed - PERMISSION_CHECK_FAILED"
  }
}
```

### Internal Error

**HTTP Status:** `500 Internal Server Error`

```json theme={null}
{
  "ok": false,
  "error": {
    "code": "PROCUREMENT_CREATION_FAILED",
    "message": "Error creating procurement"
  }
}
```

## Best Practices

* Only POs in `DRAFTED` or `DECLINED` state can be updated. Check the PO state first using the [Purchase Order Details API](/apis/po-details)
* All body fields are optional — send only the fields you want to change
* If you provide `lineItems`, the entire list of line items will be replaced; ensure you include all intended line items in the request
* Use the `poId` returned from the [Purchase Order Creation API](/apis/po-creation) or [Purchase Order Search API](/apis/po-search) to obtain the identifier
* Use ISO 8601 date format (YYYY-MM-DD) for all date fields
* Pass `state: "ACTIVE"` to activate a draft PO in the same request as your field updates. Validation merges the body with what is already stored, so you only need to send the fields that are changing — already-set fields on the PO count toward the activation check
* Check `submitWarnings` in the response when `state: "ACTIVE"` is sent — it identifies any remaining missing fields that prevented activation
* Tags can be set both on the PO (`tags` in the body) and on individual line items (`tags` inside each `lineItems` entry). Use the [tag APIs](/apis/tag-list) to look up valid tag slugs, types, and dropdown value ids before sending them
