Webhooks
Webhooks in jekcms are inbound: external tools push content and commands into your site. An n8n workflow finishes writing an article — it POSTs the result to your site and the post appears as a draft, a scheduled post, or goes live, whichever you asked for. The same endpoints drive media uploads, bulk imports and status checks.
For the reverse direction (jekcms notifying other services when something happens), pair these endpoints with an n8n polling trigger or the REST API — see the API reference for read endpoints.
Endpoints
All webhook calls are POST https://yoursite.com/api/v1/webhook/{action} with a JSON body. Supported actions:
publish— create a post and publish it immediatelyschedule— create a post scheduled for a future datedraft— create a draft postupdate— update an existing postdelete— delete a postmedia— upload media from a URLmedia-base64— upload media from base64 databulk-publish— publish multiple posts in one callbulk-import— import multiple posts from RSS/JSONai-enhance— enrich content with AI metadatastatus— get a post's current statuscheck-source— check whether a source URL was already importedtrigger— fire a custom automation trigger
Authentication
Two ways to authenticate a webhook call; either one is enough:
- API key — send a key created under Admin → API Keys (
admin/api-keys.php) as a Bearer token. Recommended for n8n and Zapier, where a header field is easy to configure. - HMAC signature — define
N8N_WEBHOOK_SECRETin your config, then sign every request: theX-Webhook-Signatureheader (also accepted:X-N8N-Signature) must contain the HMAC-SHA256 of the raw request body using the secret as key. If neither an API key nor a valid signature is present, the call is rejected with401 Invalid webhook signature.
Signing examples (sender side)
PHP
$body = json_encode(['title' => 'Hello', 'content' => '...']);
$signature = hash_hmac('sha256', $body, getenv('JEKCMS_WEBHOOK_SECRET'));
$ch = curl_init('https://yoursite.com/api/v1/webhook/draft');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $body,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'X-Webhook-Signature: ' . $signature,
],
CURLOPT_RETURNTRANSFER => true,
]);
echo curl_exec($ch);
Node.js
const crypto = require('crypto');
const body = JSON.stringify({ title: 'Hello', content: '...' });
const signature = crypto
.createHmac('sha256', process.env.JEKCMS_WEBHOOK_SECRET)
.update(body)
.digest('hex');
await fetch('https://yoursite.com/api/v1/webhook/draft', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Webhook-Signature': signature,
},
body,
});
Python
import hmac, hashlib, json, os, requests
body = json.dumps({'title': 'Hello', 'content': '...'})
signature = hmac.new(
os.environ['JEKCMS_WEBHOOK_SECRET'].encode(),
body.encode(),
hashlib.sha256,
).hexdigest()
requests.post(
'https://yoursite.com/api/v1/webhook/draft',
data=body,
headers={
'Content-Type': 'application/json',
'X-Webhook-Signature': signature,
},
)
The signature is computed over the exact bytes you send — serialize once and sign that string; re-encoding on the way out will invalidate it.
Editorial safety
If you want a human in the loop, target draft (or schedule) instead of publish: content lands in the admin as a normal draft and goes live only when an editor publishes it. The content queue (see Content Queue) gives you a review pipeline on top.
n8n quick start
- Create an API key under Admin → API Keys.
- In n8n, add an HTTP Request node: method
POST, URLhttps://yoursite.com/api/v1/webhook/draft, authentication Bearer token with your key. - Map your workflow fields into the JSON body (
title,content,category,tags,featured_image…). - Run the workflow — the post appears in your admin as a draft.