mxHeadless
REST API gateway for headless frontends on MODX 3. Resources, objects, OpenAPI, API keys, and OAuth

After create/update/delete, mxHeadless enqueues events in the outbox. Delivery runs via CLI worker.
resources.created, resources.updated, resources.deleted, and {name}.* analogs for generic objects.
php core/components/mxheadless/bin/webhook-subscribe.php \
--name=isr \
--url=https://frontend.example/api/revalidate \
--events=resources.created,resources.updated,resources.deleted \
--secret=YOUR_HMAC_SECRETTables: mxheadless_webhook_subscriptions, mxheadless_webhook_deliveries.
php core/components/mxheadless/bin/webhook-worker.php --limit=50Default --limit from mxheadless_webhook_worker_limit. Schedule on cron every minute.
POST JSON to subscriber URL:
| Header | Value |
|---|---|
Content-Type | application/json |
User-Agent | MxHeadless-Webhook/1.0 |
X-MxHeadless-Event | event type |
X-MxHeadless-Delivery-Id | delivery id |
X-MxHeadless-Signature | sha256=... when secret is set |
Retries: exponential backoff, max mxheadless_webhook_max_attempts (5) → failed.
By default blocks localhost, private IP, .local/.test. Dev override: mxheadless_webhook_allow_private_urls=true (also relaxes TLS verify).
{
"id": "...",
"type": "resources.updated",
"created_at": "...",
"data": {
"object": "resources",
"action": "updated",
"id": 12,
"context": "web",
"uri": "about",
"parent": 0
},
"meta": {
"revalidate": []
}
}Cron and systemd for the worker: Workers. meta.revalidate tags for Next.js and Nuxt: ISR revalidation.