Каталог
Товар, привязка товара к коллекции, свойства вариантов и типы цен описаны в товарах. Каналы продаж приложения — в приложениях. Отзывы бэк-офиса — в отзывах. Склады и валюты склада — в складах. Здесь — справочники и методы вокруг товара: коллекции витрины, категории учёта, фильтры и дополнительные поля.
Тело без корневого объекта отвечает 422, в message назван ожидаемый ключ, например collection. Несуществующий id в GET отвечает 404 с HTML-страницей.
Коллекции
Коллекция — раздел витрины. Корневая коллекция магазина приходит с пустым parent_id. Скрытая коллекция (is_hidden: true) в список входит. Коллекция, помеченная к удалению, из списка пропадает.
У обычной коллекции is_smart в ответе равен null. Ключ image есть только у коллекции с картинкой.
Список
GET /admin/collections.json без page и per_page отдаёт весь список. Порядок — parent_id, затем position: коллекция без родителя стоит в конце.
parent_id оставляет дочерние коллекции этого родителя. parent_id=null оставляет коллекции без родителя.
page или per_page включают постраничную выдачу. per_page меньше 10 поднимается до 10, больше 250 опускается до 250. В заголовке ответа есть X-TOTAL-PAGES. page меньше 1 отвечает 422.
| Параметр | Описание |
|---|---|
per_page необязательныйчисло |
Размер страницы. Меньше 10 поднимается до 10, больше 250 опускается до 250. |
page необязательныйчисло |
Номер страницы, начиная с 1. |
parent_id необязательныйчисло |
Только дочерние коллекции. null — коллекции без родителя. |
updated_since необязательныйстрока |
Нижняя граница updated_at, граница входит в ответ. |
GET /admin/collections.json?per_page=10&page=1
Authorization: Basic API_KEY:API_PASSWORD
Accept: application/json
Ответ · 200
[
{
"id": 53486015,
"parent_id": 53486010,
"is_hidden": true,
"is_smart": null,
"position": 40,
"recursive": true,
"sort_type": 3,
"title": "docs-api Витрина",
"permalink": "docs-api-vitrina",
"url": "/collection/docs-api-vitrina",
"html_title": "HTML title",
"meta_description": "md",
"meta_keywords": "kw",
"description": "<p>Описание <b>коллекции</b></p>",
"seo_description": "seo",
"field_values": [
{
"id": 1,
"collection_field_id": 1,
"value": "метка-1"
}
]
}
]
В ответе также есть created_at, updated_at и custom_template. Число страниц приходит в заголовке X-TOTAL-PAGES.
page=0 отвечает 422:
{"message":"page должен иметь значение, большее 0"}
Изменившиеся коллекции
updated_since оставляет коллекции с updated_at больше или равным переданному времени. Порядок такого ответа — updated_at, затем id. Время передают в query целиком, двоеточие и знак часового пояса кодируют.
Параметр from_id список коллекций не меняет: набор и порядок те же, что в запросе без него. Следующую пачку сдвигают новым updated_since. Одна и та же граница может прийти снова, потому что запись с этим временем входит в ответ.
Строка, которую нельзя разобрать как дату, фильтр не включает. Ответ приходит целиком, порядок у него уже по updated_at и id.
| Параметр | Описание |
|---|---|
updated_since обязательныйстрока |
Момент изменения. Коллекция с этим updated_at входит в ответ. |
GET /admin/collections.json?updated_since=2026-10-21T22%3A00%3A00%2B03%3A00
Authorization: Basic API_KEY:API_PASSWORD
Accept: application/json
Ответ · 200
[
{
"id": 53486015,
"updated_at": "2026-10-21T22:14:15.000+03:00",
"title": "docs-api Витрина"
},
{
"id": 53486016,
"updated_at": "2026-10-21T22:14:15.000+03:00",
"title": "docs-api dup"
}
]
У записи списка есть id, updated_at и title.
Создание и изменение
POST /admin/collections.json создаёт коллекцию и отвечает 201. parent_id обязателен. Занятый permalink запрос не отклоняет: к нему дописывается суффикс -2.
sort_type — код порядка товаров в коллекции. Чужой код отвечает 422, в ошибке sort_type со значением «имеет непредусмотренное значение».
| Код | Порядок |
|---|---|
| 1 | По алфавиту: А — Я |
| 2 | По алфавиту: Я — А |
| 3 | По дате: новые — старые |
| 4 | По дате: старые — новые |
| 5 | По цене: дорогие — дешёвые |
| 6 | По цене: дешёвые — дорогие |
| 7 | Ручная |
| 8 | По скидке: большая — маленькая |
| 9 | По скидке: маленькая — большая |
| 10 | По весовому коэффициенту: маленький — большой |
| 11 | По весовому коэффициенту: большой — маленький |
| 12 | Сначала непопулярные |
| 13 | Сначала популярные |
recursive: true сохраняется в ответе. description принимает HTML. Значения дополнительных полей пишутся массивом field_values_attributes и возвращаются в field_values.
PUT /admin/collections/:id.json меняет те же поля и отвечает 200 объектом коллекции.
| Параметр | Описание |
|---|---|
collection[title] обязательныйстрока |
Название коллекции. |
collection[parent_id] обязательныйчисло |
id родительской коллекции. |
collection[is_hidden] необязательныйлогический |
Скрыть коллекцию на витрине. |
collection[sort_type] необязательныйчисло |
Код порядка товаров, от 1 до 13. |
collection[permalink] необязательныйстрока |
Адрес коллекции. Занятое значение получает суффикс. |
collection[position] необязательныйчисло |
Позиция среди соседей. |
collection[recursive] необязательныйлогический |
Включать товары вложенных коллекций. |
collection[description] необязательныйстрока |
Описание, можно с HTML. |
collection[seo_description] необязательныйстрока |
SEO-описание. |
collection[html_title] необязательныйстрока |
Заголовок страницы. |
collection[meta_description] необязательныйстрока |
Мета-описание. |
collection[meta_keywords] необязательныйстрока |
Ключевые слова. |
collection[field_values_attributes] необязательныймассив |
Значения дополнительных полей: collection_field_id и value. |
POST /admin/collections.json
Authorization: Basic API_KEY:API_PASSWORD
Accept: application/json
Content-Type: application/json
{
"collection": {
"title": "docs-api Витрина",
"parent_id": 53486010,
"is_hidden": true,
"sort_type": 3,
"permalink": "docs-api-vitrina",
"position": 40,
"recursive": true,
"description": "<p>Описание <b>коллекции</b></p>",
"seo_description": "seo",
"html_title": "HTML title",
"meta_keywords": "kw",
"meta_description": "md",
"field_values_attributes": [
{
"collection_field_id": 1,
"value": "метка-1"
}
]
}
}
Ответ · 201
{
"id": 53486015,
"parent_id": 53486010,
"is_hidden": true,
"is_smart": null,
"position": 40,
"recursive": true,
"sort_type": 3,
"title": "docs-api Витрина",
"html_title": "HTML title",
"meta_description": "md",
"meta_keywords": "kw",
"permalink": "docs-api-vitrina",
"url": "/collection/docs-api-vitrina",
"description": "<p>Описание <b>коллекции</b></p>",
"seo_description": "seo",
"field_values": [
{
"id": 1,
"collection_field_id": 1,
"value": "метка-1"
}
]
}
Товар попадает в коллекцию отдельным запросом POST /admin/collects.json. Этот метод разобран в товарах.
Картинка
Картинка передаётся публичным адресом в image_attributes.src при создании и при PUT уже существующей коллекции. Пока файл обрабатывается, original_url равен /images/loading.gif.
| Параметр | Описание |
|---|---|
collection[title] обязательныйстрока |
Название коллекции. |
collection[parent_id] обязательныйчисло |
id родительской коллекции. |
collection[image_attributes][src] обязательныйстрока |
Публичный адрес файла картинки. |
POST /admin/collections.json
Authorization: Basic API_KEY:API_PASSWORD
Accept: application/json
Content-Type: application/json
{
"collection": {
"title": "docs-api Картинка",
"parent_id": 53486010,
"image_attributes": {
"src": "https://upload.wikimedia.org/wikipedia/commons/c/ca/1x1.png"
}
}
}
Ответ · 201
{
"id": 53486017,
"title": "docs-api Картинка",
"permalink": "docs-api-kartinka",
"image": {
"id": 1,
"created_at": "2026-10-21T22:14:16.000+03:00",
"original_url": "/images/loading.gif"
}
}
Тот же объект image_attributes в PUT /admin/collections/:id.json отвечает 200 и тоже отдаёт original_url равным /images/loading.gif, пока файл обрабатывается.
Умная коллекция
Умная коллекция собирает товары по фильтрам. POST с is_smart: true и пустым списком фильтров отвечает 422:
{"smart_collection_filters":["Настройте хотя бы один фильтр"]}
POST, в котором умная коллекция и фильтры приходят вместе, отвечает 500 и коллекцию не создаёт. Рабочий порядок — сначала обычная коллекция, затем PUT с is_smart и smart_collection_filters_attributes. Ответ 200, is_smart равен true. Сами фильтры в JSON коллекции не возвращаются.
method_or_field_name задаёт поле и ключ через двоеточие. Для названия это title:. values — массив.
| Поле | Операторы |
|---|---|
title: |
contain, not_contain |
price: |
between |
discount: |
greater_than |
created_at: |
greater_than, less_than, greater_than_or_equal, less_than_or_equal, older_than, younger_than |
property:ID |
in, empty, notempty |
Для свойства в method_or_field_name после двоеточия стоит id свойства. У empty и notempty список values может быть пустым. Запрос ниже оставляет коллекции, в названии которых есть строка.
Состав умной коллекции пересчитывается после сохранения. products_count может ещё не содержать эту коллекцию.
| Параметр | Описание |
|---|---|
id обязательныйчисло |
id уже созданной коллекции. |
collection[is_smart] обязательныйлогический |
Включить умную коллекцию. |
collection[smart_collection_filters_attributes] обязательныймассив |
Фильтры: method_or_field_name, operator, values. |
PUT /admin/collections/53486018.json
Authorization: Basic API_KEY:API_PASSWORD
Accept: application/json
Content-Type: application/json
{
"collection": {
"is_smart": true,
"smart_collection_filters_attributes": [
{
"method_or_field_name": "title:",
"operator": "contain",
"values": ["Gallery"]
}
]
}
}
Ответ · 200
{
"id": 53486018,
"parent_id": 53486010,
"is_hidden": false,
"is_smart": true,
"sort_type": 7,
"title": "docs-api page 0",
"permalink": "docs-api-page-0",
"url": "/collection/docs-api-page-0",
"field_values": []
}
Удаление
DELETE /admin/collections/:id.json у дочерней коллекции отвечает 200 и {"status":"ok"}. Следующий GET этой коллекции — 404 с HTML-страницей.
Тот же DELETE у корневой коллекции тоже отвечает {"status":"ok"}, и коллекция остаётся на месте.
| Параметр | Описание |
|---|---|
id обязательныйчисло |
id дочерней коллекции. |
DELETE /admin/collections/53486025.json
Authorization: Basic API_KEY:API_PASSWORD
Accept: application/json
Ответ · 200
{"status":"ok"}
Число товаров
GET /admin/collections/products_count.json отвечает массивом {id, count}. В нём только коллекции, у которых уже есть товары. Пустая коллекция и умная коллекция до пересчёта в массив не входят.
GET /admin/collections/products_count.json
Authorization: Basic API_KEY:API_PASSWORD
Accept: application/json
Ответ · 200
[
{
"id": 53486010,
"count": 5
},
{
"id": 53486014,
"count": 5
}
]
Категории
Категория — раздел учёта товара. В карточке товара это category_id. Коллекция витрины в это поле не подставляется.
GET /admin/categories.json отдаёт все категории без постраничной нарезки. Порядок и отбор updated_since и parent_id такие же, как у коллекций: from_id список не меняет. В объекте только id, parent_id, title, position, created_at, updated_at.
POST /admin/categories.json отвечает 201. Меняются title, parent_id и position.
| Параметр | Описание |
|---|---|
category[title] обязательныйстрока |
Название категории. |
category[parent_id] необязательныйчисло |
id родительской категории. |
category[position] необязательныйчисло |
Позиция среди соседей. |
POST /admin/categories.json
Authorization: Basic API_KEY:API_PASSWORD
Accept: application/json
Content-Type: application/json
{
"category": {
"title": "docs-api Учёт",
"parent_id": 1,
"position": 5
}
}
Ответ · 201
{
"id": 9,
"parent_id": 1,
"title": "docs-api Учёт",
"position": 5,
"created_at": "2026-10-21T22:14:20.000+03:00",
"updated_at": "2026-10-21T22:14:20.000+03:00"
}
Перенос товаров
PUT /admin/categories/set_products_category.json переносит перечисленные товары в категорию. Ответ {"status":"ok"}. В карточке товара category_id становится равным new_category_id.
| Параметр | Описание |
|---|---|
new_category_id обязательныйчисло |
id категории, в которую переносятся товары. |
product_ids обязательныймассив |
id товаров. |
PUT /admin/categories/set_products_category.json
Authorization: Basic API_KEY:API_PASSWORD
Accept: application/json
Content-Type: application/json
{
"new_category_id": 9,
"product_ids": [673]
}
Ответ · 200
{"status":"ok"}
Удаление
DELETE /admin/categories/:id.json у дочерней категории отвечает {"status":"ok"}, затем GET этой категории — 404. Товары этой категории уходят в архив.
DELETE корневой категории тоже отвечает {"status":"ok"}, и категория остаётся.
PUT /admin/categories/recover.json товары из архива не возвращает и отвечает ошибкой сервера.
Фильтры коллекций
Фильтр коллекции — SEO-страница внутри коллекции: название, адрес и набор параметров товара и свойств варианта. Методы доступны, когда фильтры коллекций есть в тарифе.
Список GET /admin/collection_filters.json постраничный. per_page меньше 10 поднимается до 10, больше 500 опускается до 500, без параметра страница содержит до 500 записей. Заголовка X-TOTAL-PAGES нет. collection_id оставляет фильтры одной коллекции; с ним порядок по position, без него — по коллекции и позиции.
Тело создания и изменения лежит в ключе filter. Ответ 201 на создание и 200 на изменение. Характеристики в ответе лежат в поле characteristis — так ключ называется в JSON. Значения дополнительных полей в этот JSON не входят.
properties_attributes и options_attributes ищут параметр и свойство по названию и создают отсутствующие. Повтор того же набора параметров и свойств в той же коллекции отвечает 422:
{"properties_attributes":["Уже существует фильтр с такими параметрами и свойствами"]}
Название фильтра уникально внутри коллекции.
| Параметр | Описание |
|---|---|
filter[title] обязательныйстрока |
Название фильтра. Уникально внутри коллекции. |
filter[collection_id] обязательныйчисло |
id коллекции. |
filter[permalink] необязательныйстрока |
Адрес фильтра. |
filter[description] необязательныйстрока |
Описание, можно с HTML. |
filter[seo_description] необязательныйстрока |
SEO-описание. |
filter[html_title] необязательныйстрока |
Заголовок страницы. |
filter[meta_keywords] необязательныйстрока |
Ключевые слова. |
filter[meta_description] необязательныйстрока |
Мета-описание. |
filter[properties_attributes] необязательныймассив |
Параметры товара: title параметра и value характеристики. |
filter[options_attributes] необязательныймассив |
Свойства варианта: title свойства и value значения. |
filter[field_values_attributes] необязательныймассив |
Значения полей коллекции: handle и value. В ответе фильтра их нет. |
POST /admin/collection_filters.json
Authorization: Basic API_KEY:API_PASSWORD
Accept: application/json
Content-Type: application/json
{
"filter": {
"title": "docs-api фильтр",
"collection_id": 53486010,
"permalink": "docs-api-filter",
"description": "<p>seo</p>",
"html_title": "t",
"meta_keywords": "k",
"meta_description": "m",
"properties_attributes": [
{
"title": "docs-api Материал",
"value": "Лён"
}
],
"options_attributes": [
{
"title": "Размер",
"value": "M"
}
]
}
}
Ответ · 201
{
"id": 1,
"collection_id": 53486010,
"title": "docs-api фильтр",
"permalink": "docs-api-filter",
"description": "<p>seo</p>",
"html_title": "t",
"meta_keywords": "k",
"meta_description": "m",
"seo_description": null,
"characteristis": [
{
"id": 609,
"property_id": 61541224,
"position": 1,
"title": "Лён",
"permalink": "lyon"
}
],
"option_values": [
{
"id": 21063150,
"option_name_id": 2517839,
"position": 13,
"title": "M",
"image_url": null,
"permalink": "m"
}
]
}
PUT /admin/collection_filters/:id.json с новым title и permalink отвечает 200 и тем же набором characteristis и option_values. DELETE /admin/collection_filters/:id.json удаляет фильтр.
Дополнительные поля коллекции
Поле коллекции создаётся с типом CollectionField::TextField или CollectionField::TextArea. Другой type отвечает 500, поле не создаётся.
POST /admin/collection_fields.json отвечает 201. В ответе есть application_id и application_title приложения, от имени которого создано поле. Повтор handle отвечает 422:
{"handle":["Свойство с таким пермалинком уже существует"]}
GET /admin/collection_fields/:id.json читает поле по числовому id. Если в сегменте пути есть не только цифры, поле ищется по handle.
| Параметр | Описание |
|---|---|
collection_field[title] обязательныйстрока |
Название поля. |
collection_field[handle] необязательныйстрока |
Системное имя. Уникально в магазине. |
collection_field[type] обязательныйстрока |
CollectionField::TextField или CollectionField::TextArea. |
collection_field[position] необязательныйчисло |
Позиция поля. |
collection_field[is_hidden] необязательныйлогический |
Скрыть поле. |
POST /admin/collection_fields.json
Authorization: Basic API_KEY:API_PASSWORD
Accept: application/json
Content-Type: application/json
{
"collection_field": {
"title": "docs-api Метка",
"handle": "docs_api_label",
"type": "CollectionField::TextField"
}
}
Ответ · 201
{
"id": 1,
"handle": "docs_api_label",
"type": "CollectionField::TextField",
"application_id": 12,
"position": 3,
"is_hidden": null,
"title": "docs-api Метка",
"application_title": "docs-catalog"
}
Значение поля
Значение можно передать при сохранении коллекции через field_values_attributes. Отдельные методы: список, чтение и изменение. Создания и удаления отдельным методом нет.
GET /admin/collections/:collection_id/collection_field_values.json — значения этой коллекции. GET и PUT одного значения идут по id поля или по его handle.
Если значения ещё нет, GET отвечает 200 и объект с пустыми id и value, запись при этом не создаётся. PUT создаёт или меняет значение и отвечает {"status":"ok"}. Новое значение читается следующим GET.
| Параметр | Описание |
|---|---|
collection_id обязательныйчисло |
id коллекции. |
id обязательныйстрока |
id поля или его handle. |
GET /admin/collections/53486015/collection_field_values/9.json
Authorization: Basic API_KEY:API_PASSWORD
Accept: application/json
Ответ · 200
{
"id": null,
"collection_field_id": 9,
"value": null
}
| Параметр | Описание |
|---|---|
collection_id обязательныйчисло |
id коллекции. |
id обязательныйстрока |
id поля или его handle. |
collection_field_value[value] обязательныйстрока |
Новое значение. |
PUT /admin/collections/53486015/collection_field_values/docs_api_label.json
Authorization: Basic API_KEY:API_PASSWORD
Accept: application/json
Content-Type: application/json
{
"collection_field_value": {
"value": "метка-2"
}
}
Ответ · 200
{"status":"ok"}
Значения дополнительных полей
Поля товара и варианта и запись значения вместе с товаром разобраны в товарах. Ниже те же значения отдельными методами. Пустой массив в карточке значит, что значений нет.
Товар
GET /admin/products/:product_id/product_field_values.json — значения товара. POST создаёт значение и отвечает 201. Повтор того же поля отвечает 422:
{"product_field_id":["уже существует"]}
В создании можно передать product_field_id или product_field_handle. Чтение, изменение и удаление идут по id значения или по handle поля.
PUT отвечает объектом значения. DELETE отвечает {"status":"ok"}, следующий список этого товара — [].
| Параметр | Описание |
|---|---|
product_id обязательныйчисло |
id товара. |
product_field_value[product_field_id] обязательныйчисло |
id поля. Вместо него можно передать product_field_handle. |
product_field_value[value] обязательныйстрока |
Значение. |
POST /admin/products/673/product_field_values.json
Authorization: Basic API_KEY:API_PASSWORD
Accept: application/json
Content-Type: application/json
{
"product_field_value": {
"product_field_id": 4586434,
"value": "значение"
}
}
Ответ · 201
{
"id": 895989818,
"product_field_id": 4586434,
"value": "значение"
}
| Параметр | Описание |
|---|---|
product_id обязательныйчисло |
id товара. |
id обязательныйстрока |
id значения или handle поля. |
product_field_value[value] обязательныйстрока |
Новое значение. |
PUT /admin/products/673/product_field_values/docs_api_pf.json
Authorization: Basic API_KEY:API_PASSWORD
Accept: application/json
Content-Type: application/json
{
"product_field_value": {
"value": "новое"
}
}
Ответ · 200
{
"id": 895989818,
"product_field_id": 4586434,
"value": "новое"
}
Вариант
Значения варианта лежат на пути /admin/variants/:variant_id/variant_field_values.json. Путь /admin/products/:product_id/variants/:variant_id/variant_field_values.json отвечает 404.
POST принимает variant_field_id или variant_field_handle и отвечает 201. PUT по handle отвечает объектом значения. После записи то же значение видно в variant_field_values карточки варианта.
| Параметр | Описание |
|---|---|
variant_id обязательныйчисло |
id варианта. |
variant_field_value[variant_field_handle] обязательныйстрока |
handle поля. Вместо него можно передать variant_field_id. |
variant_field_value[value] обязательныйстрока |
Значение. |
POST /admin/variants/2176487181/variant_field_values.json
Authorization: Basic API_KEY:API_PASSWORD
Accept: application/json
Content-Type: application/json
{
"variant_field_value": {
"variant_field_handle": "docs_api_vf",
"value": "метка"
}
}
Ответ · 201
{
"id": 1,
"variant_field_id": 1,
"value": "метка"
}
PUT /admin/variants/2176487181/variant_field_values/docs_api_vf.json с новым value отвечает 200 и объект {"id":1,"variant_field_id":1,"value":"метка-2"}.