Skip to content
mxHeadless
REST API gateway for headless frontends on MODX 3. Resources, objects, OpenAPI, API keys, and OAuth
  1. Extras
  2. mxHeadless
  3. Operations
  4. Webhooks

Webhooks

After create/update/delete, mxHeadless enqueues events in the outbox. Delivery runs via CLI worker.

Core events

resources.created, resources.updated, resources.deleted, and {name}.* analogs for generic objects.

Subscribe

bash
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_SECRET

Tables: mxheadless_webhook_subscriptions, mxheadless_webhook_deliveries.

Worker

bash
php core/components/mxheadless/bin/webhook-worker.php --limit=50

Default --limit from mxheadless_webhook_worker_limit. Schedule on cron every minute.

Delivery

POST JSON to subscriber URL:

HeaderValue
Content-Typeapplication/json
User-AgentMxHeadless-Webhook/1.0
X-MxHeadless-Eventevent type
X-MxHeadless-Delivery-Iddelivery id
X-MxHeadless-Signaturesha256=... when secret is set

Retries: exponential backoff, max mxheadless_webhook_max_attempts (5) → failed.

SSRF

By default blocks localhost, private IP, .local/.test. Dev override: mxheadless_webhook_allow_private_urls=true (also relaxes TLS verify).

Payload (v1)

json
{
  "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.