Skip to content
  1. Компоненты
  2. mxHeadless
  3. API
  4. Мутации

Мутации ​

POST, PUT, PATCH, DELETE на resources и objects требуют учётные данные и scopes записи.

МетодPathScopeУспех
POST/resources, /objects/{name}{name}.create201
PUT, PATCH/resources/{id}, /objects/{name}/{id}{name}.update200
DELETE/resources/{id}, /objects/{name}/{id}{name}.delete200

Общий путь мутации от проверок до ответа:

Тело ​

Content-Type: application/json (для POST/PUT/PATCH). Размер ограничен mxheadless_max_body_bytes (1 MB).

bash
curl -s -X POST https://example.com/api/v1/resources \
  -H 'Authorization: Bearer mxh_...' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: create-about-001' \
  -d '{"pagetitle":"About","template":1,"published":1}'

Пустое тело на PUT / PATCH допустимо только для PATCH. Сессионные мутации требуют заголовок X-CSRF-Token.

PUT и PATCH ​

PATCH присылает дельту: меняются только переданные поля, остальные остаются как были.

PUT проверяется как полная замена. Все поля из списка required определения объекта должны присутствовать в теле, иначе 422 validation_failed. Для resources это pagetitle.

Один и тот же запрос с разным методом даёт разный результат:

http
PATCH /api/v1/resources/12 HTTP/1.1
Content-Type: application/json

{"menuindex":3}

Ответ 200: меняется только menuindex.

http
PUT /api/v1/resources/12 HTTP/1.1
Content-Type: application/json

{"menuindex":3}

Тот же запрос на PUT даёт 422:

json
{
  "type": "https://mxheadless.dev/problems/validation",
  "title": "Unprocessable Entity",
  "status": 422,
  "detail": "Missing required fields",
  "instance": "/api/v1/resources/12",
  "code": "validation_failed",
  "errors": {
    "pagetitle": ["This field is required."]
  }
}

Поля из required нельзя и очищать: null, пустая строка, массив или boolean дают 422.

Почему приходит 422 ​

Валидация тела идёт после проверки прав и до записи в базу. Проверки одинаковы для resources и для extras-объектов, но часть правил имеет смысл только у ресурсов.

ПроверкаУсловиеКод ответа
Поля из requiredНе передан (на PUT), null, пустая строка, массив или boolean422
Поле из immutableЛюбая явная запись: id, createdon, createdby, editedon, editedby, deletedon422
Поле из hiddenFieldsЛюбая запись: например properties у resources422
Поле не из fieldsНеизвестное имя в теле422
Поле из protectedFieldsНет field-level права: fields.{field} у ключа, mxheadless_fields_{field} у сессии422
Значение не scalarМассив или объект вместо строки, числа, boolean422
Тип поляtemplate, parent, content_type, menuindex должны быть целым числом422
Тип booleanpublished, deleted, hidemenu, isfolder и другие: 0, 1, true, false422
Тело не JSONPOST/PUT/PATCH без разбираемого JSON-объекта422
Idempotency-KeyДлиннее 128 символов или вне A-Za-z0-9._:-422

Дополнительно для ресурсов:

ПроверкаУсловиеКод ответа
Уникальность aliasТакой alias уже есть среди живых ресурсов с тем же parent и тем же context_key422
alias длиннее 255 символовЗначение отклоняется, а не обрезается422
Цикл по parentНовый parent указывает на самого ресурса или на его потомка422
Существование parentРесурса с таким id нет422
Состояние parentРесурс-родитель помечен deleted422
class_keyКласса нет или он не наследует modResource422
template0 или id существующего modTemplate, иначе 422422
content_typeПоложительный id существующего modContentType, иначе 422422
context_keyНе из mxheadless_allowed_contexts, не существует или не загружается в текущем запросе422

Целочисленные строки приводятся к числу ("3" → 3), значения boolean-полей принимаются как 0, 1, true, false. Остальные значения отклоняются.

Ошибка всегда приходит в errors с именем поля:

json
{
  "type": "https://mxheadless.dev/problems/validation",
  "title": "Unprocessable Entity",
  "status": 422,
  "detail": "Invalid field value",
  "instance": "/api/v1/resources",
  "code": "validation_failed",
  "errors": {
    "alias": ["Alias already exists for this parent and context"]
  }
}

Уникальность alias — самая частая причина 422 на практике: в MODX это стандартное ограничение на пару alias + parent + context_key, и проверка повторяет его на уровне API.

Полный набор проверяемых полей: Schema.

Idempotency ​

При mxheadless_idempotency_enabled=true (по умолчанию) на POST можно передать:

text
Idempotency-Key: <unique-string>

Ключ: 1–128 символов A-Za-z0-9._:-. Ответ на первый запрос несёт Idempotency-Key в заголовке. Повтор с тем же ключом и тем же телом возвращает сохранённый ответ с заголовком Idempotency-Replayed: true. Другое тело или параллельный запрос с тем же ключом → 409 idempotency_conflict.

Ключ включает метод, путь и тело, поэтому один и тот же ключ на разных путях не конфликтует. TTL: mxheadless_idempotency_ttl (86400 с).

Мягкое удаление ​

DELETE на resources мягкий: помечает deleted ресурс и заодно всех его потомков. Окончательное удаление одной строки: ?force=1.

Восстановление: PATCH с {"deleted":0}. Параметр include_deleted=1 в этой операции не читается, но update() ищет строку и среди soft-deleted, поэтому PATCH восстанавливает ресурс и без него.

Удаление ресурса каскадное

DELETE /resources/{id} без force собирает всех потомков по дереву Children рекурсивно и помечает их deleted, deletedby, deletedon в одной операции (ObjectService::softDeleteResourceTree). Ответ содержит только id удалённого ресурса, но из выборки исчезает вся ветка целиком, включая опубликованные страницы вложенных разделов.

Как избежать:

  • ?force=1 удаляет строку ресурса окончательно и потомков не трогает. Дети остаются с parent, указывающим на несуществующий id.
  • Перед удалением папки переведите нужных потомков на другого родителя: PATCH /resources/{id} с {"parent":0} или {"parent":<id>}. Дети не попадут в дерево удаляемой ветки.
  • Обходной путь для extras-объектов: каскад есть только у modResource. Для остальных объектов DELETE трогает одну запись.

Восстановление PATCH {"deleted":0} возвращает в выдачу только сам ресурс, потомков нужно восстанавливать отдельно.

bash
curl -s -X DELETE 'https://example.com/api/v1/resources/12?force=1' \
  -H 'Authorization: Bearer mxh_...'

Ответ мягкого удаления:

json
{
  "data": { "id": "12", "deleted": true, "permanent": false },
  "meta": {}
}

У любого объекта без поля deleted в определении permanent всегда true.

Webhooks ​

После успешной мутации core ставит события в outbox (resources.created и т.д.). Доставка идёт через CLI worker. См. Webhooks.

См. также ​