Tax rates define the percentage of tax applied to products at checkout (e.g. "Standard VAT" at 23%). A rate can also carry a special **label** instead of a numeric percentage (e.g. "Reverse charge"), in which case the rate is forced to 0.

## Units

`rate` on this endpoint is a **percentage number**: `23` means 23%. Products expose their assigned rate in the same shape, as the product-level `taxRate` object — prefer that one when rendering.

The `productTaxRate` object still embedded in product and cart payloads is different: its nested `taxRate.rate` is the internal representation, percent × 1000 (`"23000"` for 23%). It is kept for compatibility only and should not be used for display. See [Prices and tax](/docs/api-reference/products#prices-and-tax).

## List Tax Rates

```
GET /api/v1/tax-rates
```

### Query Parameters

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `limit` | `number` | 10 | Tax rates per page (1-100) |
| `offset` | `number` | 0 | Tax rates to skip |
| `query` | `string` | – | Search by tax rate name |

### Response

```json
{
  "data": [
    {
      "id": "0191abc0-1234-7def-8000-000000000001",
      "name": "Standard VAT",
      "rate": 23,
      "label": null,
      "createdAt": "2024-05-20T10:30:00.000Z",
      "updatedAt": "2024-05-20T10:30:00.000Z"
    }
  ],
  "meta": {
    "count": 1
  }
}
```

---

## Create Tax Rate

```
POST /api/v1/tax-rates
```

Creates a tax rate. Provide either a numeric `rate` or a `label` – one is required. When a `label` is set, the rate is forced to 0.

### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | `string` | Yes | Display name, e.g. `Standard VAT` |
| `rate` | `number` | No* | Percentage rate (e.g. `23` = 23%, range 0-100). Ignored if `label` is set |
| `label` | `string` | No* | Special label instead of a numeric rate (e.g. `Reverse charge`); forces rate to 0 |

\* Provide either `rate` or `label`.

```bash
curl -X POST \
  -H "Authorization: Bearer your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"name": "Standard VAT", "rate": 23}' \
  https://your-store.yns.store/api/v1/tax-rates
```

### Response (201)

```json
{
  "id": "0191abc0-1234-7def-8000-000000000001",
  "name": "Standard VAT",
  "rate": 23,
  "label": null,
  "createdAt": "2024-06-15T10:30:00.000Z",
  "updatedAt": "2024-06-15T10:30:00.000Z"
}
```

---

## Get Tax Rate

```
GET /api/v1/tax-rates/:id
```

Returns a single tax rate by UUID.

### Response

```json
{
  "id": "0191abc0-1234-7def-8000-000000000001",
  "name": "Standard VAT",
  "rate": 23,
  "label": null,
  "createdAt": "2024-05-20T10:30:00.000Z",
  "updatedAt": "2024-05-20T10:30:00.000Z"
}
```

---

## Update Tax Rate

```
PATCH /api/v1/tax-rates/:id
```

Replaces a tax rate's name, rate, and label. Uses the same body as **Create Tax Rate**.

### Request Body

Same fields as [Create Tax Rate](#create-tax-rate).

```bash
curl -X PATCH \
  -H "Authorization: Bearer your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"name": "Reduced VAT", "rate": 8}' \
  https://your-store.yns.store/api/v1/tax-rates/0191abc0-1234-7def-8000-000000000001
```

### Response (200)

```json
{
  "id": "0191abc0-1234-7def-8000-000000000001",
  "name": "Reduced VAT",
  "rate": 8,
  "label": null,
  "createdAt": "2024-05-20T10:30:00.000Z",
  "updatedAt": "2024-06-15T11:00:00.000Z"
}
```

---

## Delete Tax Rate

```
DELETE /api/v1/tax-rates/:id
```

Hard-deletes the tax rate by UUID. If the rate is still assigned to one or more products, the request is rejected with a `409`.

```bash
curl -X DELETE \
  -H "Authorization: Bearer your_api_key" \
  https://your-store.yns.store/api/v1/tax-rates/0191abc0-1234-7def-8000-000000000001
```

### Response

```json
{
  "ok": true,
  "deleted": 1
}
```

### In Use (409)

```json
{
  "error": "Cannot delete tax rate because it is still assigned to products"
}
```