# Unit Conversions

**Unit conversions** map an alternative unit to an article's base unit via
a `numerator` / `denominator` ratio — for example a carton of 6 pieces is
`alternative_unit = "CTN", numerator = 6, denominator = 1`. Mercura uses
them to normalise ordered quantities across units.
You can:
- **`POST /articles/unit-conversions`** — bulk-upsert up to 100,000 conversions in a
single call. Async — returns a `JobAck`; poll `GET /jobs/{job_id}` for
status. Each row upserts the `(article_number, alternative_unit)`
conversion.
- **`GET /articles/unit-conversions`** — cursor-paginated list of your conversions.
Pass `article_number` to list one article's conversions, or
`modified_since` on the first page to fetch only what changed.

 - [The ratio](https://docs.mercura.ai/openapi/unit-conversions/the-ratio.md): ### The ratio The conversion is `1 alternative_unit = (numerator / denominator) base units`. Both must be positive. The ratio is stored and returned exactly as sent — it is not collapsed to a single f
 - [Upsert semantics (v1)](https://docs.mercura.ai/openapi/unit-conversions/upsert-semantics-(v1).md): ### Upsert semantics (v1) `POST` **inserts or updates** each `(article, alternative_unit)` conversion; it never removes conversions you stop sending, and there is **no delete endpoint yet**. A row who
 - [POST /articles/unit-conversions](https://docs.mercura.ai/openapi/unit-conversions/public_unit_conversions_bulk_upsert.md): Bulk-upsert unit conversions (async). Accepts up to 100,000 rows per call. Each row upserts the `(article_number, alternative_unit)` conversion; rows whose article doesn't exist are skipped (see the j
 - [GET /articles/unit-conversions](https://docs.mercura.ai/openapi/unit-conversions/public_unit_conversions_list.md): Cursor-paginated list of unit conversions.
