# Edara API v3: Currencies

Read the [guide](../guide.md) first: authentication, paging, errors, rate limits and the shared `PagedResult`, `BatchResult` and `*Reference` shapes.

- `GET /v3/currencies`: Lists currencies.
- `GET /v3/currencies/{id}`: Gets a currency by id.
- `POST /v3/currencies`: Creates a currency.
- `PUT /v3/currencies/{id}`: Updates a currency by id.
- `PUT /v3/currencies/code/{code}`: Updates a currency by code.
- `DELETE /v3/currencies/{id}`: Deletes a currency by id.
- `DELETE /v3/currencies/code/{code}`: Deletes a currency by code.

## Endpoints

### `GET /v3/currencies`: Lists currencies.

Operation `GetCurrencies` · permission `read:currency`

**Query string**: `GetCurrenciesQuery`

| 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. |
| `code` | `string` |  | Must(code => !string.IsNullOrWhiteSpace(code)) .When(x => x.Code != null) | The currency code filter. |
| `updateDate` | `DateTime?` |  |  | The updated-after filter. |

**Responses**: OK `PagedResult<CurrencyResponse>`: Paged list of currencies.

**Notes**

- `code` matches `internationalCode` exactly, not `symbol`.
- When you send `code`, `updateDate` is ignored and `totalCount` is 0 or 1.
- Without `code`, results are ordered by id and inactive currencies are included.
- `updateDate` returns currencies created or updated strictly after that date and time.
- `isSystemCurrency` marks the organization's base currency.

---

### `GET /v3/currencies/{id}`: Gets a currency by id.

Operation `GetCurrencyById` · permission `read:currency`

**Parameters**

| name | in | type | default | description |
|---|---|---|---|---|
| `id` | route | `int` |  | The currency id. |

**Responses**: OK `CurrencyResponse`: The currency.

**Notes**

- Inactive currencies are returned. An unknown id returns `404`.

---

### `POST /v3/currencies`: Creates a currency.

Operation `CreateCurrency` · permission `create:currency`

> No uniqueness is enforced on currency symbol / international code / description (matches legacy V2 behavior).

**Body**: `CurrencyUpsertRequest`

| field | type | default | validation | description |
|---|---|---|---|---|
| `symbol` | `string` |  | NotEmpty() | The currency symbol. |
| `description` | `string` |  | NotEmpty() | The currency display name. |
| `internationalCode` | `string` |  | MaximumLength(10) .When(x => !string.IsNullOrWhiteSpace(x.InternationalCode)) | The ISO 4217 code. |
| `currencySubUnit` | `string` |  | MaximumLength(100) .When(x => !string.IsNullOrWhiteSpace(x.CurrencySubUnit)) | The currency sub-unit label. |
| `isSystemCurrency` | `bool` |  |  | Whether this is the system currency. |
| `isActive` | `bool?` |  |  | Whether the currency is active. |

**Responses**: Created `CurrencyResponse`: Currency created.

**Business errors** (HTTP 409, match on `errorCode`):

- `DupplicatedCode`: Another currency already uses the same code.

**Notes**

- `internationalCode` is in practice required and must be one of a fixed list of ISO currency codes. A missing or unknown code returns `409` with `InvalidInternationalCode`.
- `internationalCode` is matched without regard to case and stored in the list's standard casing.
- `internationalCode` must be unique. A code that already exists returns `409` with `DupplicatedCode`. `symbol` and `description` are not checked for uniqueness.
- `isActive` defaults to `true` when omitted, and an omitted `currencySubUnit` is stored as an empty string.
- You cannot set the gain and loss accounts or the exchange rate through this endpoint.
- A `symbol` longer than 5 characters or a `description` longer than 50 characters is cut to that length without an error.
- A successful create returns `201` with the created currency.

---

### `PUT /v3/currencies/{id}`: Updates a currency by id.

Operation `UpdateCurrency` · permission `update:currency`

> No uniqueness is enforced on currency symbol / international code / description (matches legacy V2 behavior).

**Parameters**

| name | in | type | default | description |
|---|---|---|---|---|
| `id` | route | `int` |  | The currency id. |

**Body**: `CurrencyUpsertRequest`

| field | type | default | validation | description |
|---|---|---|---|---|
| `symbol` | `string` |  | NotEmpty() | The currency symbol. |
| `description` | `string` |  | NotEmpty() | The currency display name. |
| `internationalCode` | `string` |  | MaximumLength(10) .When(x => !string.IsNullOrWhiteSpace(x.InternationalCode)) | The ISO 4217 code. |
| `currencySubUnit` | `string` |  | MaximumLength(100) .When(x => !string.IsNullOrWhiteSpace(x.CurrencySubUnit)) | The currency sub-unit label. |
| `isSystemCurrency` | `bool` |  |  | Whether this is the system currency. |
| `isActive` | `bool?` |  |  | Whether the currency is active. |

**Responses**: OK `CurrencyResponse`: The updated currency.

**Business errors** (HTTP 409, match on `errorCode`):

- `DupplicatedCode`: Another currency already uses the same code.

**Notes**

- An unknown id returns `404`.
- This is a full replace of `symbol`, `description`, `internationalCode`, `currencySubUnit` and `isSystemCurrency`. Send all of them on every update.
- Omitting `isSystemCurrency` stores `false`, which clears the system currency flag.
- `isActive` is the only optional field: when you omit it, the stored value is kept. The gain and loss accounts are not changed.
- `internationalCode` must be on the same fixed list of ISO currency codes as on create, or you get `409` with `InvalidInternationalCode`. It must also be unique among the other currencies, or you get `409` with `DupplicatedCode`.

---

### `PUT /v3/currencies/code/{code}`: Updates a currency by code.

Operation `UpdateCurrencyByCode` · permission `update:currency`

> No uniqueness is enforced on currency symbol / international code / description (matches legacy V2 behavior).

**Parameters**

| name | in | type | default | description |
|---|---|---|---|---|
| `code` | route | `string` |  | The currency code. |

**Body**: `CurrencyUpsertRequest`

| field | type | default | validation | description |
|---|---|---|---|---|
| `symbol` | `string` |  | NotEmpty() | The currency symbol. |
| `description` | `string` |  | NotEmpty() | The currency display name. |
| `internationalCode` | `string` |  | MaximumLength(10) .When(x => !string.IsNullOrWhiteSpace(x.InternationalCode)) | The ISO 4217 code. |
| `currencySubUnit` | `string` |  | MaximumLength(100) .When(x => !string.IsNullOrWhiteSpace(x.CurrencySubUnit)) | The currency sub-unit label. |
| `isSystemCurrency` | `bool` |  |  | Whether this is the system currency. |
| `isActive` | `bool?` |  |  | Whether the currency is active. |

**Responses**: OK `CurrencyResponse`: The updated currency.

**Business errors** (HTTP 409, match on `errorCode`):

- `DupplicatedCode`: Another currency already uses the same code.

**Notes**

- `code` in the path is the currency's `internationalCode`, not its symbol. It is trimmed and matched exactly, and an unknown code returns `404`.
- Otherwise this behaves like PUT /v3/currencies/{id}: it is a full replace, and omitting `isSystemCurrency` stores `false`.
- You can change `internationalCode` in the body. The new value must be on the allowed list and unique.

---

### `DELETE /v3/currencies/{id}`: Deletes a currency by id.

Operation `DeleteCurrency` · permission `delete:currency`

**Parameters**

| name | in | type | default | description |
|---|---|---|---|---|
| `id` | route | `int` |  | The currency id. |

**Responses**: NoContent: (not declared; read from the method body)

**Business errors** (HTTP 409, match on `errorCode`):

- `ItemCannotDeleteItInUse`: The currency is referenced by existing documents or related records.

**Notes**

- The currency is deleted permanently. If other records still use it, you get `409` with `ItemCannotDeleteItInUse`.
- An unknown id returns `404`.

---

### `DELETE /v3/currencies/code/{code}`: Deletes a currency by code.

Operation `DeleteCurrencyByCode` · permission `delete:currency`

**Parameters**

| name | in | type | default | description |
|---|---|---|---|---|
| `code` | route | `string` |  | The currency code. |

**Responses**: NoContent: (not declared; read from the method body)

**Business errors** (HTTP 409, match on `errorCode`):

- `ItemCannotDeleteItInUse`: The currency is referenced by existing documents or related records.

**Notes**

- `code` in the path is matched against `internationalCode`, trimmed and exact. An unknown code returns `404`.
- The currency is deleted permanently. If other records still use it, you get `409` with `ItemCannotDeleteItInUse`.

## Types

### `CurrencyResponse`

Response describing a currency.

| field | type | description |
|---|---|---|
| `id` | `int` | The currency identifier. |
| `symbol` | `string` | The currency symbol. |
| `description` | `string` | The currency display name. |
| `internationalCode` | `string` | The ISO 4217 code. |
| `currencySubUnit` | `string` | The currency sub-unit label. |
| `isSystemCurrency` | `bool` | Whether this is the system currency. |
| `isActive` | `bool` | Whether the currency is active. |
