Webhooks
Subscribe external systems to events inside DM Editors — entry publishes, form submissions, media uploads — with signed payloads, retries, and a delivery log.
Routes
| Route | Method | Purpose |
|---|---|---|
/admin/webhooks | GET | List subscriptions |
/admin/webhooks/create | GET | New subscription |
/admin/webhooks | POST | Create |
/admin/webhooks/{webhook} | GET | Subscription detail + delivery log |
/admin/webhooks/{webhook}/edit | GET | Edit |
/admin/webhooks/{webhook} | PUT | Update |
/admin/webhooks/{webhook} | DELETE | Delete |
/admin/webhooks/{webhook}/toggle-active | PATCH | Pause / resume deliveries |
/admin/webhooks/{webhook}/test | POST | Send a sample payload to the URL |
Subscription attributes
- name — internal label
- url — destination endpoint (https recommended)
- secret — used to compute the
X-DM Editors-SignatureHMAC - events — JSON array of subscribed event names
- headers — JSON map of custom headers added to each request
- is_active — pause without deletion
- retry_policy — max attempts & backoff (default: 5 attempts, exponential)
Available events
| Event | Trigger |
|---|---|
entry.created | New content entry saved |
entry.updated | Entry edited |
entry.published | Entry transitions to published |
entry.unpublished | Entry transitions away from published |
entry.deleted | Entry soft-deleted |
form.submission.created | New form submission |
media.uploaded | File uploaded |
media.deleted | File deleted |
user.created | New admin user |
Payload shape
POST https://example.com/webhooks/DM Editors
Content-Type: application/json
X-DM Editors-Event: entry.published
X-DM Editors-Delivery: <uuid>
X-DM Editors-Signature: sha256=<hex hmac of body using webhook.secret>
User-Agent: DM Editors-Webhooks/1.0
{
"event": "entry.published",
"occurred_at": "2026-05-29T10:15:00Z",
"data": {
"id": "…",
"model_slug": "blog-posts",
"title": "Hello",
"slug": "hello",
"locale": "en",
"status": "published",
"published_at": "2026-05-29T10:14:58Z"
}
}
Signature verification
// Node.js example
const crypto = require('crypto');
function verify(req, secret) {
const sig = req.headers['x-DM Editors-signature'];
const computed = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(JSON.stringify(req.body))
.digest('hex');
return crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(computed));
}
Delivery log
webhook_deliveries stores one row per attempt: target URL, payload, response code, response body (truncated), latency, and attempt number. Retries are queued via Laravel's job system; failed deliveries keep retrying with exponential backoff until they succeed or hit the retry cap.
Testing
The "Send test" button posts a synthetic payload to the URL so you can verify connectivity without waiting for a real event. The response is shown inline and logged like any other delivery.