Бесплатно
Загрузите дополнение из админки вашего сайта.
Как загрузить?
Как загрузить?
Версия
1.0.42-pl
Дата выпуска
31.08.2026
Загрузки
0
Просмотры
29
Внимание, этот компонент требует PHP
8.2
или выше!
Внимание, этот компонент требует MODX 3 или выше.
mxHeadless — отдаёт ресурсы, страницы, элементы, контексты и зарегистрированные xPDO-объекты в JSON. Закрытый registry: наружу попадают только объявленные объекты и поля. Аутентификация через API keys, OAuth `client_credentials` и сессию Manager. Live OpenAPI и Swagger UI на `/api/v1/docs`.
Плагин OnHandleRequest отдаёт /api/v1/*. Если rewrite недоступен, используйте assets/components/mxheadless/api.php?route=/v1/health.
Зачем
Extension API
Требования
Быстрый старт
Плагин OnHandleRequest отдаёт /api/v1/*. Если rewrite недоступен, используйте assets/components/mxheadless/api.php?route=/v1/health.
Зачем
Нужен JSON для фронтенда или мобильного клиента, без произвольного доступа к PHP-классам. mxHeadless открывает только объекты и поля из registry. ACL MODX сохраняется.
Возможности
- CRUD ресурсов, страницы по URI, элементы (chunks, templates, snippets, TVs, categories, content types), контексты
- универсальный /objects/{name} для объектов из Extension API
- фильтры, сортировка, пагинация, fields, include, tv_fields, поиск q
- soft delete, ?force=1, preview неопубликованного, include_deleted
- API keys (mxh_…), OAuth client_credentials (mxt_…), сессия Manager + CSRF
- CORS, rate limit, HTTP cache (ETag / 304), idempotency, kill switch
- webhooks (outbox + worker), audit log
- live OpenAPI и Swagger UI на /api/v1/docs
Extension API
- Extras регистрируют объекты на событии OnMxHeadlessRegister
- типичный кейс магазина: каталог через registered objects, корзина через native API MiniShop3
Требования
- MODX ≥ 3.2.3, PHP ≥ 8.1, MySQL/MariaDB (xPDO 3)
Быстрый старт
curl -s https://your-site.example/api/v1 | jq curl -s https://your-site.example/api/v1/health | jq curl -s 'https://your-site.example/api/v1/resources?limit=5&filter[published]=1' | jq
Ключ: Manager или
php core/components/mxheadless/bin/api-key-create.php --name="CI" --scopes="resources.read" Changelog - mxHeadless
Format: Keep a Changelog Versioning: Semantic Versioning
[1.0.42-pl] - 2026-08-30
Changed
- System settings: dotted keys (
mxheadless.cors.enabled) → underscores (mxheadless_cors_enabled). - Upgrade resolver copies values from old keys and removes them.
- Docs EN/RU, lexicons, and OpenAPI updated for the new keys.
- API bootstrap context is now configurable via
mxheadless_context(defaultweb);mgris ignored and falls back toweb.
[1.0.41-pl] - 2026-08-30
Fixed
- CLI bins resolve the MODX root by walking up to
core/config/config.inc.php(works from Extra source and installedcore/components/mxheadless/bin).
Changed
- Unit coverage for CORS, CSRF, body limit, request ID, trusted proxy, errors, HTTP cache, routing, and media URLs.
[1.0.40-pl] - 2026-08-30
Fixed
- Fallback
assets/components/mxheadless/api.phpmapped the request path incorrectly and returned 404. - On nginx/Herd without PATH_INFO, use
?route=/v1/health(or?route=/api/v1/...). PATH_INFOapi.php/v1/...still works when the server provides it.
[1.0.39-pl] - 2026-08-30
Fixed
pageandoffsettogether used to silently preferoffset. Now 422.
Changed
- OpenAPI:
forceon DELETE for soft-delete objects;include_deletedon resource GET by id.
[1.0.38-pl] - 2026-08-30
Fixed
- Second soft
DELETEof the same resource returned 200. Now 404.?force=1still purges an already deleted row.
[1.0.37-pl] - 2026-08-30
Fixed
Accept: text/htmlon JSON endpoints returned 200. HTML is allowed only on/docs; otherwise 406.fields=` on a protected field (e.g. `createdby) returned 200 with the field omitted. Now 422, same as hidden fields.- OpenAPI path for contexts by primary key is
/contexts/{key}(not{id}).
[1.0.36-pl] - 2026-08-30
Added
- Relations
category(chunks, templates, snippets, TVs) andparent(categories). - Filter operator alias
ne→neq. - Endpoint catalog
pathalias forpattern.
Changed
- OpenAPI
includeonly when the object has relations;preview/include_deletedonly whenpublished/deletedexist. - OpenAPI root
tagslists the API groups (was empty).
[1.0.35-pl] - 2026-08-30
Changed
- Live OpenAPI list query params come from each
ObjectDefinition(filterable, sorts, relations). Templates no longer advertisefilter[published]. - OpenAPI tags:
ContentTypes,TVs.
[1.0.34-pl] - 2026-08-30
Added
- Read-only collections:
templates,snippets,tvs,categories,content_types(scopes*.read). - Static OpenAPI:
POST /auth/token. Discovery links for resources, elements, auth,openapi.json. - Docs:
docs/api/elements.md(EN/RU).
[1.0.33-pl] - 2026-08-30
Fixed
- Manager session without
resources.readblocked public GET (Swagger in the same browser returned 403). Session on public safe reads is treated like anonymous; API key / OAuth still need the scope.
Changed
- OpenAPI: list/get query parameters; public operations use optional security
[{}, {bearerAuth}]so Authorize still attaches a Bearer.
[1.0.32-pl] - 2026-08-30
Changed
- OpenAPI
requestBodyon POST/PUT/PATCH (MutationBody,OAuthTokenRequest); create responses 201. - Swagger UI:
validatorUrldisabled (no validator.swagger.io for local hosts).
[1.0.31-pl] - 2026-08-30
Added
GET /api/v1/docsSwagger UI;GET /api/v1/meta/openapi.jsonraw spec.- Setting
mxheadless.swagger.enabled(default Yes). Discoverylinks.docs.
Fixed
- HTTP cache stores
Content-Type(cached/docsno longer comes back as JSON). Accept: text/htmlandapplication/openapi+jsonno longer 406 on those routes.
[1.0.30-pl] - 2026-08-30
Fixed
- Creating a resource with
parentpointing at a soft-deleted row. Now 422.
[1.0.29-pl] - 2026-08-30
Fixed
- Boolean filters:
filter[published][eq]=truecompared as a string and matched nothing.true/false/yes/nocoerce; garbage is 422.
[1.0.28-pl] - 2026-08-30
Changed
PATCH {"deleted":true}uses the same soft-delete path asDELETE(audit fields + resource tree).PATCH {"deleted":0}clearsdeletedon/deletedby.
[1.0.27-pl] - 2026-08-30
Changed
deletedon(and other immutable/hidden fields) rejected on write with 422 instead of ignored.aliaslonger than 255 characters is 422.
[1.0.26-pl] - 2026-08-30
Fixed
- Duplicate
aliasamong non-deleted siblings. Now 422. templatemust be0or an existing template id.
[1.0.25-pl] - 2026-08-30
Fixed
- Parent cycle (
A → B → A) hung inmodResource::save. Detected before write, 422. content_typemust exist and be ≥ 1.
[1.0.24-pl] - 2026-08-30
Fixed
class_keymust name an existingmodResourcesubclass (unknown class used to save and then 404 on read).parentmust be0or an existing id, not self.templatemust be ≥ 0.
[1.0.23-pl] - 2026-08-30
Fixed
- Writing
context_keyto an unknown or unloadable context caused 500. Now 422 / 403 (whitelist, ACL, exists, loadable). - Mutations by id look up the row across contexts, then check access to the object's context.
- 500 log lines include
file:line.
[1.0.22-pl] - 2026-08-30
Changed
- Mutations reject arrays/objects in scalar fields (422).
- Booleans: only
true/false/0/1. Integers (parent,template, …) must be integers.
[1.0.21-pl] - 2026-08-30
Changed
limit/offset/pageof0, negative, or non-numeric is 422 (no silent clamp).- Unknown
include=` relation is 422 (`Include not allowed).
[1.0.20-pl] - 2026-08-30
Added
include_deleted=trueon GET list/get (requirespreview,resources.update, orresources.delete; also skips published-only).
Fixed
- Update/delete could not see soft-deleted rows, so restore was impossible. Mutations find trash;
PATCH {"deleted":0}restores. PUT {}without required fields is 422 (was 200, like PATCH).
[1.0.19-pl] - 2026-08-30
Added
- Schema lists
required,protected, andimmutablefields.
Fixed
PATCHwith emptypagetitleis 422.
[1.0.18-pl] - 2026-08-30
Fixed
- Unknown filter operator (
filter[id][drop]=1) was 500. Now 422. POST /resourceswith{}or blankpagetitlewas 201. Resources require a non-emptypagetitle(422).bootstrap.phpwithout$namespace(CLI) used a missing path. Fallback to__DIR__/.
[1.0.17-pl] - 2026-08-30
Changed
DELETE /resources/{id}is soft-delete (deleted/deletedon/deletedby+ children).?force=trueremoves the row (including already deleted).- List pagination:
pagepluslinks.self|next|prev.
Fixed
- Concurrent
Idempotency-Keycould produce two 201s. Lock via cacheadd(), then re-find. - Malformed JSON body is 422 (not 400).
- Webhook
attemptsincrements on successful delivery.
[1.0.16-pl] - 2026-08-30
Fixed
- Same
Idempotency-Keywith a different body used to replay the first 2xx. Now 409idempotency_conflict. - OAuth:
Authorization: Basic base64(client_id:client_secret)with form or JSON body (RFC 6749).
[1.0.15-pl] - 2026-08-30
Fixed
- OAuth
mxt_*tokens never authenticated protected routes: MySQLexpires_ondatetime was cast with(int)and treated as expired.normalizeTimestamp()in token and API-key repositories.
Added
POST /auth/tokenacceptsapplication/x-www-form-urlencoded.include=tvsas an alias ofinclude=tv.
[1.0.14-pl] - 2026-08-30
Added
- Sort aliases
field:asc/field:desc(alongside+field/-field). last_used_onon API keys and OAuth tokens (updated on successful auth, 60s throttle).
Fixed
- Manager API-key grid search: Enter via
specialkeyinstead of a fragile DOMkeydown.
[1.0.13-pl] - 2026-08-30
Fixed
- Missing credential still
token_required. Present but invalid, expired, or revoked Bearer isinvalid_token(wastoken_required).
[1.0.12-pl]
Added
- Manager UI: Components → mxHeadless (API keys grid create/update/revoke).
- Lexicon EN/RU for settings labels and mgr strings.
- Permission
mxheadless_apikeyson Administrator policy.
Fixed
oauth-client-createCLI usesMxHeadless\Model\modMxHeadlessOAuthClient(mysql subclass failed to save).
[1.0.11-pl]
Added
- List meta:
count+has_morefor Nuxt/Next pagination. - Problem codes:
not_found,validation_failed; discoverycors.allowed_origins. - OpenAPI ProblemDetails enum extended.
Changed
- API responses no longer set PHPSESSID (ISR/CDN-friendly); session still read from Cookie.
[1.0.10-pl]
Added
- Resources filterable:
hidemenu,isfolder,menuindex(Nuxt/Next nav menus). - HEAD authorized like GET; ETag on GET/HEAD for anonymous and API-key clients (Nuxt/Next SSR).
- OpenAPI
info.versionfollowsVersion::STRING.
Changed
- ResponseEmitter replaces headers (Content-Type/ETag) and skips body on HEAD.
[1.0.9-pl]
Added
- Page URI aliases for Nuxt/Next:
/pages/aboutresolvesabout.html; index/empty →index.html. meta.resolved_urion page responses; discovery exposescors.enabledand pages link.- CORS: expose ETag/rate-limit/idempotency headers;
Idempotency-Keyin allow list; Max-Age on preflight. - Docs: pages aliases, CORS for browser fetch, preview scope for Draft Mode.
[1.0.8-pl]
Fixed
- Qualify SELECT/ORDER columns with table alias so reserved names like context
keyhydrate correctly. - Reject unknown/hidden
fieldswith 422 (docs contract); honorfieldson single-object GET/pages.
[1.0.7-pl]
Fixed
- Query parsing when QUERY_STRING is HTML-entity-encoded (
&) — prefer$_GET. - Strip MODX friendly-URL
qpath from query params so it does not become a search term. - Include query string in anonymous HTTP cache keys (sort/filter/fields no longer collide).
- Discovery version comes from
Version::STRING(was hardcoded 1.0.0). - Unknown
/objects/{name}returns 404 instead of 403. - Support
filter[field]=valueshorthand aseq.
Changed
- POST
*.createroutes return 201 Created.
[1.0.6-pl]
Added
- Rate-limit response headers (
X-RateLimit-Limit/Remaining/Reset) andRetry-Afteron 429. - CLI
bin/webhook-subscribe.phpto create webhook subscriptions. - Docs: webhook subscribe CLI (EN/RU).
Fixed
- Audit-prune CLI (array criteria for
removeCollection) and--help/--days.
[1.0.5-pl]
Added
- Built-in curl PSR-18 client for webhook delivery.
- Setting
mxheadless_webhook_allow_private_urlsfor local webhook targets. - CLI
bin/api-key-create.phpfor long-livedmxh_*keys. - Local webhook catcher asset for smoke testing.
[1.0.4-pl]
Fixed
- Resource listing: drop removed MODX columns from schema; use xPDO
where()without broken table alias. - Use
getCount()for list totals. - Allow update/delete of unpublished resources (mutation lookup skips published filter).
- Do not overwrite existing system settings on package update.
- Add
idto resources filterable fields.
[1.0.2-pl]
Fixed
- xPDO lookups use
MxHeadless\Model\modMxHeadless*base classes (mysql subclasses did not hydrate API keys, OAuth, audit). - Public POST routes (OAuth
POST /auth/token) no longer require a GET-only public check. - OPTIONS preflight returns 204 even when CORS is disabled.
[1.0.1-pl]
Fixed
- HTTP gateway recursion: plugin listens only to
OnHandleRequest(droppedOnMxHeadlessRegisterbinding). - Upgrade resolver removes a leftover
OnMxHeadlessRegisterplugin event from 1.0.0 installs.
[1.0.0-pl]
Added
- Initial release: REST API, API keys, OAuth tokens, audit log, webhooks, idempotency.




Последние обсуждения в сообществе MODX.pro