# Edara API v3: Purchase Orders

Read the [guide](../guide.md) first: authentication, paging, errors, rate limits and the shared `PagedResult`, `BatchResult` and `*Reference` shapes.

- `GET /v3/purchase-orders`: Lists purchase orders.
- `GET /v3/purchase-orders/{id}`: Gets a purchase order by id.
- `POST /v3/purchase-orders/find`: Finds purchase orders.
- `POST /v3/purchase-orders/purchase-returns/find`: Finds purchase returns.

## Endpoints

### `GET /v3/purchase-orders`: Lists purchase orders.

Operation `GetPurchaseOrders` · permission `read:purchase-order`

**Query string**: `GetPurchaseOrdersQuery`

| field | type | default | validation | description |
|---|---|---|---|---|
| `offset` | `int?` | 0 | **no validator**: negative silently becomes 0 | Number of items to skip before returning results. Defaults to 0. |
| `limit` | `int?` | 100 | **no validator**: out of 1..1000 silently becomes 100 | Maximum number of items to return. Defaults to 100, maximum 1000. |
| `code` | `string` |  |  | Optional exact document-code filter. |

**Responses**: OK `PagedResult<PurchaseOrderResponse>`: Paged list of purchase orders.

**Notes**

- Without `code`, the list also includes purchase returns and other purchase document types, not only orders.
- Results are ordered by id. A negative `offset` is treated as 0, and a `limit` outside 1 to 1000 falls back to 100.
- `totalCount` counts all purchase documents, including the other document types.
- `code` is trimmed and matched exactly, so it returns at most one item and paging is ignored. No match returns `200` with an empty list, not `404`.
- A `code` lookup does not return a document that has no lines, but the plain list does.
- A `code` lookup also finds archived documents.

---

### `GET /v3/purchase-orders/{id}`: Gets a purchase order by id.

Operation `GetPurchaseOrderById` · permission `read:purchase-order`

**Parameters**

| name | in | type | default | description |
|---|---|---|---|---|
| `id` | route | `int` |  | The purchase order id. |

**Responses**: OK `PurchaseOrderResponse`: The purchase order.

**Notes**

- An unknown id returns `404`. A document that has no lines also returns `404`.
- An id that belongs to a purchase return or another purchase document type is returned too. Check `documentType` in the response.
- Archived documents are returned too.

---

### `POST /v3/purchase-orders/find`: Finds purchase orders.

Operation `FindPurchaseOrders` · permission `read:purchase-order`

**Body**: `FindPurchaseOrdersRequest`

| field | type | default | validation | description |
|---|---|---|---|---|
| `offset` | `int?` | 0 | >= 0 | Number of items to skip before returning results. Defaults to 0. |
| `limit` | `int?` | 100 | 1..1000 (out of range → 400); LessThanOrEqualTo(100) .When(x => x.Limit.HasValue) | Maximum number of items to return. Defaults to 100, maximum 1000. |
| `supplierId` | `int?` |  | GreaterThan(0) .When(x => x.SupplierId.HasValue) | Supplier identifier filter. |
| `dateFrom` | `DateTime?` |  | NotNull() | Inclusive lower bound of the document date range. |
| `dateTo` | `DateTime?` |  | NotNull(); GreaterThanOrEqualTo(x => x.DateFrom) .When(x => x.DateFrom.HasValue && x.DateTo.HasValue) | Inclusive upper bound of the document date range. |

**Responses**: OK `PagedResult<PurchaseOrderResponse>`: Paged list of purchase orders. · NotFound `ProblemDetails`: The referenced supplier was not found.

**Notes**

- `dateTo` must not be earlier than `dateFrom`. A `limit` above 100 returns `400` instead of being reduced. An unknown `supplierId` returns `404`, not an empty list.
- `dateFrom` and `dateTo` filter on when the document was created in Edara, not on the document date. A `dateTo` without a time means the start of that day, so send the end of the day to include it.
- Only purchase orders are returned, not other purchase document types. Results are ordered newest first by creation time.
- A page can hold fewer items than `limit`, because orders with no lines are left out after paging while `totalCount` still counts them. Do not treat a short page as the last page.

---

### `POST /v3/purchase-orders/purchase-returns/find`: Finds purchase returns.

Operation `FindPurchaseReturns` · permission `read:purchase-return`

**Body**: `FindPurchaseReturnsRequest`

| field | type | default | validation | description |
|---|---|---|---|---|
| `offset` | `int?` | 0 | >= 0 | Number of items to skip before returning results. Defaults to 0. |
| `limit` | `int?` | 100 | 1..1000 (out of range → 400); LessThanOrEqualTo(100) .When(x => x.Limit.HasValue) | Maximum number of items to return. Defaults to 100, maximum 1000. |
| `supplierId` | `int?` |  | GreaterThan(0) .When(x => x.SupplierId.HasValue) | Supplier identifier filter. |
| `dateFrom` | `DateTime?` |  | NotNull() | Inclusive lower bound of the document date range. |
| `dateTo` | `DateTime?` |  | NotNull(); GreaterThanOrEqualTo(x => x.DateFrom) .When(x => x.DateFrom.HasValue && x.DateTo.HasValue) | Inclusive upper bound of the document date range. |

**Responses**: OK `PagedResult<PurchaseOrderResponse>`: Paged list of purchase returns. · NotFound `ProblemDetails`: The referenced supplier was not found.

**Notes**

- Only purchase returns are returned. Everything else works the same as POST /v3/purchase-orders/find.
- `dateTo` must not be earlier than `dateFrom`. A `limit` above 100 returns `400` instead of being reduced. An unknown `supplierId` returns `404`.
- `dateFrom` and `dateTo` filter on when the return was created in Edara. A `dateTo` without a time means the start of that day, so send the end of the day to include it.
- A page can hold fewer items than `limit`, because returns with no lines are left out after paging while `totalCount` still counts them. Do not treat a short page as the last page.

## Types

### `AccountReference`

Lightweight account reference (id + code + name).

| field | type | description |
|---|---|---|
| `id` | `int` | The account id. |
| `code` | `string` | The account code. |
| `name` | `string` | The account name. |

### `CurrencyReference`

Lightweight currency reference (id + ISO code + name).

| field | type | description |
|---|---|---|
| `id` | `int` | The currency id. |
| `code` | `string` | The ISO 4217 currency code. |
| `name` | `string` | The currency name. |

### `DocumentType`

Document type codes shared across sales, purchase, and warehouse domains.

Values (sent/returned as the name): `RS`, `RR`, `RT`, `IO`, `IR`, `IT`, `TR`, `CI`, `CO`, `JE`, `SI`, `PI`, `CN`, `DN`, `NR`, `NP`, `SO`, `SR`, `RecSO`, `PO`, `PR`, `OB`, `RMA`

### `PurchaseOrderInstallmentResponse`

Response describing a purchase-order payment installment.

| field | type | description |
|---|---|---|
| `id` | `int?` | Unique identifier of the installment. |
| `documentId` | `int?` | Identifier of the parent purchase order. |
| `daysLimit` | `int?` | Number of days from the document date until the payment is due. |
| `amount` | `decimal?` | Amount due for this installment. |
| `dueDate` | `DateTime?` | Due date of the installment payment. |
| `bankId` | `int?` | Identifier of the bank associated with the installment. |
| `noteNo` | `string` | Promissory note number for the installment. |
| `comments` | `string` | Free-text comments for the installment. |
| `noteTypeId` | `int?` | Identifier of the note type for the installment. |

### `PurchaseOrderItemResponse`

Response describing a purchase-order line item.

| field | type | description |
|---|---|---|
| `id` | `int?` | Unique identifier of the line item. |
| `documentId` | `int?` | Identifier of the parent purchase order. |
| `quantity` | `decimal?` | Quantity ordered. |
| `issuedQuantity` | `decimal?` | Quantity already issued or received against this line. |
| `unitPrice` | `decimal?` | Price per unit before discounts. |
| `price` | `decimal?` | Total line price (quantity * unit price) before discount. |
| `tax` | `TaxReference` | Tax applied to the line item. |
| `taxRate` | `decimal?` | Effective tax rate applied to the line item. |
| `itemDiscount` | `decimal?` | Discount applied to the line item, interpreted per `ItemDiscountType`. |
| `itemDiscountType` | `DiscountType?` | Type of the line-item discount (value or percentage). |
| `serviceItemId` | `int?` | Identifier of the service item, when the line represents a service. |
| `stockItem` | `StockItemReference` | Stock item being purchased. |
| `unitOfMeasure` | `UnitOfMeasureReference` | Unit of measure of the ordered quantity. |
| `uMRatio` | `decimal?` | Conversion ratio of the selected unit of measure to the base unit. |
| `comments` | `string` | Free-text comments for the line item. |
| `returnedQuantity` | `decimal?` | Quantity that has been returned against this line. |
| `batchNumber` | `string` | Batch number of the received goods. |
| `productionDate` | `DateTime?` | Production date of the batch. |
| `expiryDate` | `DateTime?` | Expiry date of the batch. |
| `detailWarehouse` | `WarehouseReference` | Warehouse the line is received into, when it differs from the document warehouse. |
| `packagesCount` | `decimal?` | Number of packages for the line. |
| `purchaseItemId` | `int?` | Identifier of the linked purchase item. |
| `stockItemClassificationCode` | `string` | Classification code of the stock item. |
| `unitFairValue` | `decimal?` | Unit fair value of the line item. |
| `updateWOdetailId` | `int?` | Identifier of the work-order detail this line updates. |
| `returnedFromWOdetailId` | `int?` | Identifier of the work-order detail this line was returned from. |
| `linkedPODetailId` | `int?` | Identifier of the originating purchase-order detail this line is linked to. |

### `PurchaseOrderResponse`

Response describing a purchase order.

| field | type | description |
|---|---|---|
| `id` | `int?` | Unique identifier of the purchase order. |
| `documentCode` | `string` | System-generated document code. |
| `documentType` | `DocumentType?` | Type of the purchase document. |
| `orderStatus` | `SalesOrderStatus?` | Current fulfilment status of the purchase order. |
| `paperNumber` | `string` | External paper/reference number from the supplier's document. |
| `supplier` | `SupplierReference` | Supplier the goods are purchased from. |
| `purchasePersonId` | `int?` | Identifier of the purchase person responsible for the order. |
| `warehouse` | `WarehouseReference` | Destination warehouse where goods are received. |
| `treasuryId` | `int?` | Identifier of the treasury used for cash settlement. |
| `nPAccount` | `AccountReference` | Notes-payable account associated with the order. |
| `costAllocationAccount` | `AccountReference` | Account used to allocate landed/extra costs. |
| `currency` | `CurrencyReference` | Currency of the order. |
| `exchangeRate` | `decimal?` | Exchange rate to the system currency. |
| `documentDate` | `DateTime?` | Date of the purchase order document. |
| `shippingDate` | `DateTime?` | Expected delivery/shipping date. |
| `grossTotal` | `decimal?` | Total before discounts and taxes. |
| `subTotal` | `decimal?` | Subtotal after line-item discounts but before order discount and taxes. |
| `netTotal` | `decimal?` | Final total after all discounts and taxes. |
| `totalItemsDiscounts` | `decimal?` | Sum of all line-item discounts. |
| `discount` | `decimal?` | Order-level discount amount. |
| `discountRate` | `decimal?` | Order-level discount percentage. |
| `taxable` | `bool?` | Indicates whether the order is subject to tax. |
| `needAddedTax` | `bool?` | Indicates whether added tax applies to the order. |
| `applyTaxAfterDiscount` | `bool?` | Indicates whether tax is applied after the order discount. |
| `tax` | `decimal?` | Total tax amount for the order. |
| `addedTax` | `decimal?` | Total added-tax amount for the order. |
| `cashAmount` | `decimal?` | Cash amount paid at the time of the order. |
| `nPAmount` | `decimal?` | Amount recorded against the notes-payable account. |
| `onAccountAmount` | `decimal?` | Amount recorded on the supplier account (credit). |
| `allocatedCost` | `decimal?` | Cost allocated to the order. |
| `distributedCost` | `decimal?` | Cost distributed across the order line items. |
| `notes` | `string` | Free-text notes for the purchase order. |
| `printPrice` | `bool?` | Indicates whether prices are printed on the document. |
| `isIssued` | `bool?` | Indicates whether the order has been issued to the warehouse. |
| `issueDate` | `DateTime?` | Date the order was issued. |
| `isCashed` | `bool?` | Indicates whether the order has been cashed. |
| `isNPDone` | `bool?` | Indicates whether the notes-payable processing is done. |
| `isReviewed` | `bool?` | Indicates whether the order has been reviewed. |
| `isByPassed` | `bool?` | Indicates whether the order bypassed standard processing. |
| `byPassingReason` | `string` | Reason the order bypassed standard processing. |
| `byPassUserId` | `int?` | Identifier of the user who bypassed the order. |
| `replicated` | `bool?` | Indicates whether the order was replicated. |
| `hasCostAllocation` | `bool?` | Indicates whether the order has cost allocation. |
| `salesStore` | `SalesStoreReference` | Sales store associated with the order. |
| `requireAutoCash` | `bool?` | Indicates whether automatic cash settlement is required. |
| `requireAutoCredit` | `bool?` | Indicates whether automatic credit settlement is required. |
| `requireAutoWorkorder` | `bool?` | Indicates whether an automatic work order is required. |
| `channel` | `string` | Channel through which the order was placed. |
| `attachmentName` | `string` | Name of the attached file, if any. |
| `relatedWorkOrderCode` | `string` | Document code of the related work order, when the purchase is for a specific job. |
| `relatedWorkOrderValue` | `decimal?` | Value attributed to the related work order. |
| `purchaseOrderDetails` | `List<PurchaseOrderItemResponse>` | Line items of the purchase order. |
| `purchaseOrderInstallments` | `List<PurchaseOrderInstallmentResponse>` | Payment installments of the purchase order. |

### `SalesOrderStatus`

Sales-order lifecycle states.

Values (sent/returned as the name): `Cancelled`=0, `Confirmed`=1, `Pending`=2, `Processing`=3, `OutForDelivery`=4, `Shipped`=5, `Returned`=6, `Open`=7

### `SalesStoreReference`

Lightweight sales-store reference (id + code + name).

| field | type | description |
|---|---|---|
| `id` | `int` | The sales-store id. |
| `code` | `string` | The sales-store code. |
| `name` | `string` | The sales-store name. |

### `StockItemReference`

Lightweight stock-item reference (id + code + description).

| field | type | description |
|---|---|---|
| `id` | `int` | The stock-item id. |
| `code` | `string` | The stock-item code. |
| `description` | `string` | The stock-item description. |

### `SupplierReference`

Lightweight supplier reference (id + code + name).

| field | type | description |
|---|---|---|
| `id` | `int` | The supplier id. |
| `code` | `string` | The supplier code. |
| `name` | `string` | The supplier name. |

### `TaxReference`

Lightweight tax reference (id + name + rate).

| field | type | description |
|---|---|---|
| `id` | `int` | The tax id. |
| `name` | `string` | The tax name. |
| `rate` | `decimal` | The tax rate as a percentage. |

### `UnitOfMeasureReference`

Lightweight unit-of-measure reference (id + name).

| field | type | description |
|---|---|---|
| `id` | `int` | The unit-of-measure id. |
| `name` | `string` | The unit-of-measure name. |

### `WarehouseReference`

Lightweight warehouse reference (id + code + name).

| field | type | description |
|---|---|---|
| `id` | `int` | The warehouse id. |
| `code` | `string` | The warehouse code. |
| `name` | `string` | The warehouse name. |
