Получайте товары Royal Rolls для вашего приложения, каталога или помощника: состав, цены, фотографии, КБЖУ, категории и добавки. Опубликованные товары доступны без регистрации и API-ключа.
https://royal-rolls.com/wp-json/royal/v1/Первый запрос
Откройте адрес в браузере или отправьте обычный GET-запрос. Ответ имеет тип application/json. Список товаров — массив объектов; запрос одного товара возвращает один объект.
curl 'https://royal-rolls.com/wp-json/royal/v1/products?per_page=1&modifiers=true'Сокращённый пример ответа. Цены и состав каталога обновляются; значения ниже приведены для иллюстрации.
[
{
"id": 3865,
"slug": "c-kurinoj-grudkoj-s-imbirnoj-zapravkoj",
"sku": "112224",
"name": "C куриной грудкой с имбирной заправкой",
"price": 360,
"sale_price": null,
"weight": "163 г",
"calories": "227",
"calories100": "139",
"modifiers": []
}
]Адреса запросов
| Метод и путь | Что возвращает |
|---|---|
GET /products | Опубликованные товары, по страницам. |
GET /products/{id} | Один товар с соусами и добавками. Вместо ID можно передать slug. |
GET /categories | Категории: id, name, slug, parent, count. Включая пустые. |
GET /tags | Теги: id, name, slug, parent, count. Включая пустые. |
Например: /products/3865. Артикул sku не заменяет ID в этом адресе. У корневой категории parent = 0; поле count считает товары непосредственно в категории, без суммирования дочерних разделов.
Фильтры списка
| Параметр | Значение | По умолчанию |
|---|---|---|
page | Номер страницы, начиная с 1. | 1 |
per_page | Товаров на странице, максимум 100. | 50 |
search | Текст для поиска по названию и описанию. | Без поиска |
category | ID или slug категории, например rolly. | Все категории |
tag | ID или slug тега, например losos. | Все теги |
modifiers | true включает группы соусов и добавок. | false |
Фильтры можно сочетать. Кириллицу и специальные символы кодируйте через URLSearchParams или средствами вашей HTTP-библиотеки.
https://royal-rolls.com/wp-json/royal/v1/products?category=rolly&tag=losos&per_page=100&modifiers=trueЕсли per_page больше 100, сервер вернёт до 100 записей; если значение ≤ 0 — до 50. Значение page меньше 1 приводится к 1. Без modifiers=true массив modifiers в списке пуст; это не означает, что у товара нет добавок.
Поля товара
| Поля | Тип и смысл |
|---|---|
id, slug, sku, iiko_id | ID — число; остальные — строки. Идентификаторы товара. |
name, desc | Строки: название, описание и состав. Описание может содержать HTML. |
price, sale_price | Цена в рублях: числа; sale_price также может быть null. При скидке price — старая цена. |
weight, quantity, unit | Строки: вес или объём, количество в порции, единица продажи. |
image_url, thumbnail_id, permalink | URL оригинального фото, числовой ID изображения, URL страницы товара. |
calories, proteins, fats, carbs | Строки: калории (ккал), белки, жиры и углеводы (г) на порцию. |
calories100, proteins100, fats100, carbs100 | Те же показатели на 100 г, также строки. |
tags, categories | Массивы объектов с id, name, slug; у категорий также parent. |
has_sauces, has_mods, modifiers | Признаки выбора соуса и добавок; массив групп модификаторов. |
force_sale_badge, cashback_boost, priority | Акционный бейдж (boolean), дополнительный кешбэк и приоритет (числа). |
post_status, publish_date | Строки: publish и дата публикации во времени сайта (Ижевск, UTC+4). |
Как читать цену
Актуальная цена — sale_price, если она не null, иначе price. Используйте проверку на null, чтобы корректно обработать нулевую цену.
const currentPrice = product.sale_price ?? product.price;Соусы и добавки
В каждой группе modifiers есть name, iiko_id, minAmount, maxAmount, required и массив items. У каждой добавки: name, price, iiko_item_id, iiko_group_id. Цена добавки указана в рублях.
Отсутствующие текстовые данные могут быть пустой строкой, списки — пустыми массивами. КБЖУ передаются строками. Не выводите незаполненные значения как подтверждённый ноль.
Для отображения названий используйте textContent. Если выводите HTML из desc, обработайте его проверенным HTML-санитайзером вашего приложения.
Как получить весь каталог
Запрашивайте страницы последовательно с per_page=100. Заголовок X-WP-Total содержит общее число товаров после фильтрации, X-WP-TotalPages — число страниц. Не фиксируйте количество страниц в коде.
interface ProductSummary {
id: number;
name: string;
price: number;
sale_price: number | null;
}
function isProduct(value: unknown): value is ProductSummary {
if (typeof value !== 'object' || value === null) return false;
return 'id' in value && typeof value.id === 'number'
&& 'name' in value && typeof value.name === 'string'
&& 'price' in value && typeof value.price === 'number'
&& 'sale_price' in value
&& (value.sale_price === null || typeof value.sale_price === 'number');
}
async function loadCatalog(): Promise<ProductSummary[]> {
const products: ProductSummary[] = [];
let totalPages = 1;
for (let page = 1; page <= totalPages; page += 1) {
const url = new URL('https://royal-rolls.com/wp-json/royal/v1/products');
url.search = new URLSearchParams({
per_page: '100', page: String(page), modifiers: 'true',
}).toString();
const response = await fetch(url);
if (!response.ok) throw new Error('HTTP ' + response.status);
const data: unknown = await response.json();
if (!Array.isArray(data) || !data.every(isProduct)) {
throw new Error('Unexpected API response');
}
const paginationHeader = response.headers.get('X-WP-TotalPages');
if (paginationHeader === null) {
throw new Error('Missing pagination header');
}
const pages = Number(paginationHeader);
if (!Number.isInteger(pages) || pages < 0) {
throw new Error('Invalid pagination header');
}
totalPages = pages;
products.push(...data);
}
return products;
}
const products = await loadCatalog();
for (const product of products) {
const currentPrice = product.sale_price ?? product.price;
console.log(product.name, currentPrice);
}Пример проверяет минимальные поля для названия и цены; в исходном JSON доступны остальные поля карточки. Порядок API — заданный порядок товаров, затем название; он может отличаться от сортировки витрины по популярности. Между страницами данные могут обновляться: для периодической синхронизации сопоставляйте товары по id.
Ошибки и ограничения
| Код | Что означает |
|---|---|
200 | Успешный ответ. Пустой массив списка тоже корректный результат. |
400 | Некорректный тип параметра, например текст вместо номера страницы. |
404 | Товар не найден, не опубликован или адрес API не существует. |
{
"code": "rr_not_found",
"message": "Товар не найден",
"data": {
"status": 404
}
}- Публичное чтение возвращает опубликованные товары. Черновики, отложенные и закрытые товары не доступны без дополнительных прав.
- Отдельного признака текущей доступности, стоп-листа и расписания продаж в этом ответе нет. Наличие товара в API не гарантирует возможность заказать его прямо сейчас.
- Этот API предназначен для чтения каталога. Адресов создания заказа, оплаты или изменения товаров здесь нет.
- Цены и данные могут меняться. Обновляйте их перед использованием и обрабатывайте ошибки HTTP и сети.
Для программ и AI-агентов
Спецификация OpenAPI 3.0.3 описывает четыре адреса, параметры, заголовки пагинации и схемы ответов. Её можно импортировать в Postman, Swagger Editor или использовать для создания клиента.
В HTML страницы встроена разметка JSON-LD: TechArticle для документации и WebAPI для сервиса, со ссылкой на OpenAPI. Весь текст документации доступен в исходном HTML без выполнения JavaScript.
Стандарты: Schema.org WebAPI, Schema.org TechArticle, OpenAPI 3.0.3.