# Versioning and changelog

How the REST API and the MCP server are versioned, and what counts as a compatible change.

Section: Commerce · Getting started
Canonical URL: https://docs.omniretailconnect.nl/commerce/getting-started/versioning

## REST API

- The version is part of the URL: `/api/v1`. The prefix is fixed by the contract.
- Within v1 changes are **additive only**: new endpoints, new optional parameters and new response fields.
- Clients must ignore unknown response fields.
- A breaking change would be released as `/api/v2`.
- The OpenAPI document ([commerce.json](https://docs.omniretailconnect.nl/docs/openapi/commerce.json)) is versioned with the API and describes the current v1 contract. Its `info.version` is `1.11.0`.

## MCP server

- The MCP server identifies itself with the server version `1.6.0`.
- It offers fifteen read tools to every token and forty-five write tools to tokens with a write scope. A token without a write scope stays strictly read-only (see [Privacy and security](https://docs.omniretailconnect.nl/commerce/mcp/privacy-and-security.md#read-only)).
- New tools, new optional arguments and new result fields are additive changes. Clients must ignore unknown result fields.

## Rolling back (for operators)

- The two columns added for the REST API (`mcp_tokens.channels` and `mcp_tool_calls.interface`) have defaults, so existing tokens stay MCP-only and existing audit rows read `mcp`.
- **Before rolling back the `channels` migration, or deploying older code that does not know channels, revoke every token that holds only the `api` channel.** Older MCP code ignores channels, so an api-only token would become valid on the MCP server.
- Switching the REST API off is safe at any time and needs no rollback; tokens and audit rows are kept.

## Changelog

*Changelog*

| Version | Interface | Changes |
| --- | --- | --- |
| `1.0.0` | REST API (`/api/v1`) | First release: read-only endpoints for products, SKUs, availability, orders, categories and the sales summary, plus the OpenAPI document. |
| `1.1.0` | REST API (`/api/v1`) | Additive: the three product writes `PATCH /products/{id}`, `PUT /skus/{sku}/price` and `PUT /skus/{sku}/stock` with the scope `commerce.write.products`. |
| `1.2.0` | REST API (`/api/v1`) | `GET /sales-summary` no longer counts refunds of orders that are now cancelled: a cancelled order counts nowhere, also not in `refunded` and `net_sales`. The fields are unchanged, but the meaning of `refunded` and `net_sales` changed, and figures for past periods can change when an earlier order is cancelled later. The MCP tool `get_sales_summary` follows the same rule. |
| `1.3.0` | REST API (`/api/v1`) | Additive: `GET /orders/by-id/{id}` returns an order by its internal id. Order shipments gain `tracking_url` (`null` without `commerce.read.pii`), and orders gain `returns` (at most 20 return requests, never their reason or contact email). The MCP tool `get_order` returns the same fields. |
| `1.4.0` | REST API (`/api/v1`) | No change to the endpoints described here: this version only added endpoints and scopes for an internal OmniRetail integration, which are not part of the public copy. |
| `1.5.0` | REST API (`/api/v1`) | Additive: product images of `GET /products/{id}` and `GET /skus/{sku}` gain `id`, the media id, before `url`. A client that validates responses strictly against a schema generated from an older OpenAPI document must regenerate it; clients that ignore unknown fields need no change. |
| `1.6.0` | REST API (`/api/v1`) | No change to the endpoints described here: this version only added a draft endpoint for an internal OmniRetail integration, which is not part of the public copy. |
| `1.7.0` | REST API (`/api/v1`) | Additive: REST endpoints for the write tools that were MCP-only: `POST /products`, `POST /products/{id}/media`, `DELETE /products/{id}/media/{mediaId}`, `PUT /products/{id}/media/{mediaId}/primary`, `POST /categories`, `PATCH /categories/{id}`, `POST /categories/{id}/move` and `PUT\|DELETE /categories/{id}/products/{productId}`. New scopes `commerce.write.discounts`, `commerce.write.orders` and `commerce.write.content`; the admin offers write permissions as checkboxes. The `Allow` header of a `405` can now list `DELETE`. |
| `1.8.0` | REST API (`/api/v1`) | Additive: the reference lists `GET /brands`, `/labels`, `/tax-classes` and `/properties`; the product writes `PATCH /products/{id}/seo`, `PUT /products/{id}/slug`, `/properties` and `/labels` and `PATCH /skus/{sku}`; brand writes (`POST /brands`, `PATCH\|DELETE /brands/{id}`, `PUT /brands/{id}/slug`, `PUT\|DELETE /brands/{id}/logo`); label writes (`POST /labels`, `PATCH\|DELETE /labels/{id}`, `POST /labels/{id}/move`); and featured products (`PUT\|DELETE /categories/{id}/featured/{productId}`, `POST .../move`, scope `commerce.write.collections`). |
| `1.9.0` | REST API (`/api/v1`) | Additive: variant offers `PUT\|DELETE /skus/{sku}/sale` and `PUT /skus/{sku}/price-breaks`; discount codes `GET /discounts`, `GET /discounts/{id}` and, with `commerce.write.discounts`, `POST /discounts`, `PATCH\|DELETE /discounts/{id}` and `POST /discounts/{id}/deactivate`. Products gain `slug`, `seo`, `labels`, `properties`, and per variant `sales` and `price_breaks`. Discount codes are only shown to `commerce.write.discounts` tokens and never for codes a source manages (`code_hidden`). `PATCH /skus/{sku}` no longer matches a path ending in `/sale` or `/price-breaks`. |
| `1.10.0` | REST API (`/api/v1`) | Additive: order writes with `commerce.write.orders`: `POST /orders/{id}/confirm-payment`, `/cancel`, `/notes`, `/shipments` and `PATCH /orders/{id}/shipments/{shipmentId}`. No refunds and no cancellation of paid orders. Orders gain `fulfilment.shipments[].id` and `internal_notes` (only with `commerce.read.pii`, otherwise `null`). |
| `1.11.0` | REST API (`/api/v1`) | Additive: CMS pages: `GET /pages`, `GET /pages/{id}` and, with `commerce.write.content`, `POST /pages`, `PATCH /pages/{id}` (with `expected_updated_at`) and `DELETE /pages/{id}`. 20 block types, image URLs the shop downloads, and the new page fields `canonical_url`, `noindex` and `og_image`. The page writes accept a body of up to 256 KiB. |
| `1.0.0` | MCP server | First release: seven read tools. Tokens gained channels (`mcp`, `api`) with the REST API; tokens without a channel setting stay MCP-only. |
| `1.1.0` | MCP server | The write tools `update_product`, `set_price` and `set_stock` with the scope `commerce.write.products`, the change history per token and the write limit of 30 write calls per token per minute. Write tokens created in the shop admin live at most 30 days. |
| `1.2.0` | MCP server | The write tools `create_product`, `attach_product_to_collection`, `detach_product_from_collection`, `add_product_media`, `remove_product_media` and `set_primary_product_media` (scope `commerce.write.products`), and `create_collection`, `update_collection` and `move_collection` with the new scope `commerce.write.collections`. `get_product` images gain `id`, the media id. |
| `1.3.0` | MCP server | The reference lists `list_brands`, `list_labels`, `list_tax_classes` and `list_properties`; the write tools `update_product_seo`, `change_product_slug`, `update_variant`, `set_product_properties`, `set_labels`, the brand and label tools, and the featured product tools (`commerce.write.collections`). `get_product` gains `slug`, `seo`, `labels` and `properties`. |
| `1.4.0` | MCP server | The variant offer tools `set_variant_sale`, `end_variant_sale` and `set_price_breaks`, and the discount tools `list_discounts`, `get_discount`, `create_discount`, `update_discount`, `deactivate_discount` and `delete_discount` with the scope `commerce.write.discounts`. `get_product` variants gain `sales` and `price_breaks`. |
| `1.5.0` | MCP server | The order tools `confirm_offline_payment`, `cancel_unpaid_order`, `add_order_note`, `add_shipment` and `update_shipment_tracking` with the scope `commerce.write.orders`. `get_order` gains `internal_notes` (with `commerce.read.pii`) and the shipment `id`. |
| `1.6.0` | MCP server | The page tools `list_pages`, `get_page`, `create_page`, `update_page` and `delete_page` with the scope `commerce.write.content`. The request body cap of the endpoint went from 64 KiB to 256 KiB for the page writes; every other tool still takes at most 64 KiB of arguments. |

See [REST API overview](https://docs.omniretailconnect.nl/commerce/api/overview.md), [Product writes](https://docs.omniretailconnect.nl/commerce/api/product-writes.md) and [MCP overview](https://docs.omniretailconnect.nl/commerce/mcp/overview.md).
