# Edara API v3: Suppliers

Read the [guide](../guide.md) first: authentication, paging, errors, rate limits and the shared `PagedResult`, `BatchResult` and `*Reference` shapes.

- `GET /v3/suppliers`: Lists suppliers.
- `GET /v3/suppliers/{id}`: Gets a supplier by id.
- `POST /v3/suppliers`: Creates a supplier.
- `PUT /v3/suppliers/{id}`: Updates a supplier.
- `DELETE /v3/suppliers/{id}`: Deletes a supplier.

## Endpoints

### `GET /v3/suppliers`: Lists suppliers.

Operation `GetSuppliers` · permission `read:supplier`

**Query string**: `GetSuppliersQuery`

| 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) | Maximum number of items to return. Defaults to 100, maximum 1000. |
| `name` | `string` |  |  | Supplier name filter. |

**Responses**: OK `PagedResult<SupplierResponse>`: Paged list of suppliers.

**Notes**

- `name` is trimmed and matches any part of the supplier name. A blank `name` applies no filter.
- Inactive suppliers are included.
- Results are ordered by id. A negative `offset` is treated as 0, and a `limit` outside 1 to 1000 falls back to 100.
- A supplier linked to several purchase persons appears more than once and takes several places on the page, while `totalCount` counts each supplier once. Remove duplicates by id, and expect a page to hold fewer distinct suppliers than `limit`.

---

### `GET /v3/suppliers/{id}`: Gets a supplier by id.

Operation `GetSupplierById` · permission `read:supplier`

**Parameters**

| name | in | type | default | description |
|---|---|---|---|---|
| `id` | route | `int` |  | The supplier id. |

**Responses**: OK `SupplierResponse`: The supplier.

**Notes**

- Inactive suppliers are returned. An unknown id returns `404`.

---

### `POST /v3/suppliers`: Creates a supplier.

Operation `CreateSupplier` · permission `create:supplier`

**Body**: `SupplierCreateRequest`

| field | type | default | validation | description |
|---|---|---|---|---|
| `name` | `string` |  | NotEmpty()  .MaximumLength(100) | Supplier display name. |
| `mobile` | `string` |  |  | Supplier mobile number. |
| `email` | `string` |  |  | Supplier email address. |
| `taxRegisterationId` | `string` |  |  | Supplier tax registration id. |
| `relatedAccountId` | `int?` |  |  | Existing GL account to link. Mutually exclusive with `RelatedAccountParentNodeId`. |
| `relatedAccountParentNodeId` | `int?` |  |  | Parent chart-of-accounts node under which to create a new related account. Mutually exclusive with `RelatedAccountId`. |

**Responses**: Created `SupplierResponse`: Supplier created.

**Business errors** (HTTP 409, match on `errorCode`):

- `DupplicatedName`: Another supplier or related account already uses this name.

**Notes**

- Send exactly one of `relatedAccountId` or `relatedAccountParentNodeId`. Sending both or neither returns `400`. An unknown account or node id also returns `400`, not `404`.
- With `relatedAccountParentNodeId`, a new accounts payable account is created under that node, named after the supplier, with the next available code. With `relatedAccountId`, the existing account is linked.
- A supplier name that already exists returns `409` `DupplicatedName`. With `relatedAccountParentNodeId`, you get the same error when an account with that name already exists.
- Only the name, mobile, email, and tax registration id are stored. They are trimmed, and blank values are stored as null. The new supplier has no code.

---

### `PUT /v3/suppliers/{id}`: Updates a supplier.

Operation `UpdateSupplier` · permission `update:supplier`

**Parameters**

| name | in | type | default | description |
|---|---|---|---|---|
| `id` | route | `int` |  | The supplier id. |

**Body**: `SupplierUpdateRequest`

| field | type | default | validation | description |
|---|---|---|---|---|
| `name` | `string` |  | NotEmpty()  .MaximumLength(100) | Supplier display name. |
| `mobile` | `string` |  |  | Supplier mobile number. |
| `email` | `string` |  |  | Supplier email address. |
| `taxRegisterationId` | `string` |  |  | Supplier tax registration id. |

**Responses**: OK `SupplierResponse`: The updated supplier.

**Business errors** (HTTP 409, match on `errorCode`):

- `DupplicatedName`: Another supplier already uses this name.

**Notes**

- An unknown id returns `404`.
- `name`, `mobile`, `email`, and `taxRegisterationId` are overwritten on every update. If you omit `mobile`, `email`, or `taxRegisterationId`, the stored value is cleared, not kept.
- Renaming a supplier does not rename its linked account.
- Any uniqueness conflict returns `409` `DupplicatedName`, even when the conflicting value is not the name.
- The supplier's active status is not changed by this endpoint.

---

### `DELETE /v3/suppliers/{id}`: Deletes a supplier.

Operation `DeleteSupplier` · permission `delete:supplier`

**Parameters**

| name | in | type | default | description |
|---|---|---|---|---|
| `id` | route | `int` |  | The supplier id. |

**Responses**: NoContent: (not declared; read from the method body)

**Business errors** (HTTP 409, match on `errorCode`):

- `ItemCannotDeleteItInUse`: The supplier is still referenced by related records.

**Notes**

- The delete is permanent. An unknown id returns `404`.
- Deleting a supplier also deletes its related account when no other supplier uses that account. Otherwise only the link to the account is removed.
- A supplier that is still in use cannot be deleted. The request returns `409` `ItemCannotDeleteItInUse`, with no details about what uses it.

## 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. |

### `SupplierResponse`

Response describing a supplier.

| field | type | description |
|---|---|---|
| `id` | `int` | Supplier identifier. |
| `name` | `string` | Supplier name. |
| `mobile` | `string` | Supplier mobile number. |
| `email` | `string` | Supplier email address. |
| `taxRegisterationId` | `string` | Supplier tax registration id. |
| `relatedAccount` | `AccountReference` | Related general-ledger account. |
