Перейти к содержимому

REST API V1

/api/v1/* — публичный контур PageCraft. Всё, что можно сделать в интерфейсе руками — завести блок, собрать из блоков страницу, опубликовать её на витрину, — делается и через это API.

Ресурс Адрес
Базовый URL https://page-craft.4partners.io/api/v1
Swagger UI /api/v1/docs
OpenAPI (JSON) /api/v1/docs.json

Спецификация — источник правды: она порождается из кода контроллеров, а не пишется руками. Разошлось что-то с этой страницей — верьте спецификации.

Есть и второй контур, /api/* со своим Swagger на /api/docs: он обслуживает интерфейс, авторизуется cookie-сессией и не предназначен для интеграций. Единственное, что нужно оттуда, — управление API-ключами.

Каждый запрос — заголовок Authorization с ключом:

Окно терминала
export API='https://page-craft.4partners.io/api/v1'
export KEY='pb_a1b2c3d4e5f6...'
curl -s -H "Authorization: Bearer $KEY" "$API/sites"

Ключ видит только данные своего владельца — плюс глобальные блоки и макеты, доступные всем.

Все списочные эндпоинты принимают limit и offset и отвечают одинаково:

{ "data": [ ... ], "total": 137, "limit": 50, "offset": 0 }

limit по умолчанию 50, максимум 200; offset по умолчанию 0. Значение больше максимума — ошибка запроса, а не тихое обрезание.

Любой ответ 4xx и 5xx — объект с полем error:

{ "error": "Ошибка валидации блоков" }

Там, где ошибку можно привязать к конкретному месту payload, добавляется errors[]:

{
"error": "Ошибка валидации блоков",
"errors": [
{ "path": "blocks[0].placeholder_values.title", "message": "поле обязательно" },
{ "path": "site_id", "message": "This value should be of type int." }
]
}

path — dot-путь внутри отправленного тела. По нему исправляется ровно одно поле, и запрос повторяется. Полный разбор кодов — Коды ошибок.

Группа Эндпоинты Зачем
Сайты GET /sites, GET /sites/{id}/provider, PUT /sites/{id}/provider/fourcms выбрать сайт, посмотреть и настроить провайдера публикации
Медиа GET /sites/{id}/s3/status, POST /sites/{id}/s3/upload залить картинку и получить публичный URL
Блоки GET/POST /blocks, GET/PUT/DELETE /blocks/{id}, POST /blocks/{id}/cover, POST /blocks/{id}/fork библиотека блоков
Контракт блока GET /blocks/{id}/placeholder-schema JSON Schema значений блока — ключевой эндпоинт при сборке страницы
Использование блока GET /blocks/{id}/usages где блок стоит на страницах
Каталог GET /block-submissions, POST /blocks/{id}/submit, DELETE /block-submissions/{id} заявки в глобальный каталог
Коллекции GET/POST /collections, …/{id}/blocks, …/{id}/blocks/order подборки блоков
Макеты GET/POST /layouts, GET/PUT/DELETE /layouts/{id}, /layouts/{id}/fork обёртки страницы
Страницы GET/POST /pages, GET/PUT/DELETE /pages/{id} страницы сайта
Блоки на странице POST /pages/{id}/blocks, PUT/DELETE /pages/{pageId}/blocks/{pbId}, …/move, …/replace, …/upgrade, POST /pages/{pageId}/blocks/upgrade-all точечная правка состава страницы
Публикация GET /pages/{id}/publication, POST /pages/{id}/publish, POST /pages/{id}/publish-update выкладка на витрину
Папки GET/POST /folders, GET/PUT/DELETE /folders/{id} дерево папок внутри сайта
Данные GET /data-sources, GET /data-sources/{id}, GET /data-result-types, GET /data-result-types/{id} источники живых данных и форма их результата
Типы страниц GET /page-types допустимые значения kind у шаблона
Поиск и теги GET /search/blocks, GET /search/pages, GET /tags, GET /layout-tags навигация по библиотеке

Пять шагов от пустого места до страницы на витрине. Подробная версия с обработкой ошибок — Playbook: фабрика страниц.

Страница обязана принадлежать сайту: site_id — обязательное поле.

Окно терминала
curl -s -H "Authorization: Bearer $KEY" "$API/sites?limit=50" | jq '.data[] | {id, name}'

Поиском по названию и описанию либо по тегам (GET /tags вернёт их список):

Окно терминала
curl -s -H "Authorization: Bearer $KEY" "$API/blocks?search=hero&limit=20" \
| jq '.data[] | {id, name, description}'

Шаг, который нельзя пропускать. Он отвечает, какие поля у блока есть и какого они типа, — угадывать по названию блока бессмысленно.

Окно терминала
curl -s -H "Authorization: Bearer $KEY" "$API/blocks/3/placeholder-schema" | jq '.'

В ответе:

  • block_typeschema (обычный блок) или markdown (WYSIWYG-блок, значения кладутся в зарезервированный ключ _markdown);
  • schema — JSON Schema (Draft-07) для placeholder_values;
  • example — минимальный валидный пример, собранный из значений по умолчанию; его можно отправить как есть;
  • binding_slots — слоты живых данных с допустимыми источниками; пустой массив у обычных блоков.

Про типы полей — Схема полей, про слоты — Биндинги и слоты.

Окно терминала
curl -s -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{
"site_id": 1,
"name": "О компании",
"slug": "about",
"blocks": [
{ "block_id": 3, "placeholder_values": { "title": "Добро пожаловать" } },
{ "block_id": 7, "placeholder_values": { "_markdown": "## О нас\n\nТекст." } }
]
}' "$API/pages" | jq '{id, name, slug}'

Порядок элементов blocks[] задаёт порядок блоков на странице. Ответ — 201 с созданной страницей; проверить состав можно запросом GET /pages/{id}?with_blocks=1.

Публикация — отдельное действие: страница в PageCraft и статья на витрине — разные сущности.

Окно терминала
# что со страницей сейчас
curl -s -H "Authorization: Bearer $KEY" "$API/pages/42/publication" | jq '.'
# первая публикация
curl -s -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{ "rubric_ids": [42] }' "$API/pages/42/publish" | jq '.'

Если is_published уже true — вызывается POST /pages/{id}/publish-update, иначе придёт 400. Подробности — Публикация и обновление.

  • openapi/v1.json — спецификация, из неё взяты пути, коды и схемы
  • backend/src/Controller/V1/** — экшены контура v1
  • backend/config/routes.yaml — маршруты /api/v1/docs и /api/v1/docs.json
  • backend/config/packages/nelmio_api_doc.yaml — разделение контуров default и v1
  • backend/src/EventListener/ApiExceptionListener.php — формат тела ошибок