Webhooks & Integrations
Техническое руководство из исходного проекта Notty. Примеры, параметры и эксплуатационные ограничения.
Notty CMS fires webhooks on content events, letting you connect external services, trigger builds, or sync data.
Create a Webhook
curl -X POST http://localhost:2102/api/webhooks \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Deploy on Publish",
"url": "https://api.vercel.com/v1/integrations/deploy/prj_...",
"events": ["entry.publish"],
"enabled": true
}'
Webhook Events
| Event | Trigger |
|---|---|
entry.create |
New content entry created |
entry.update |
Content entry updated |
entry.delete |
Content entry deleted |
entry.publish |
Content entry published |
entry.unpublish |
Content entry unpublished |
entry.preview.invalidate |
Preview cache should be cleared |
Filter by Content Type
Only fire the webhook for specific content types:
{
"name": "Article Events",
"url": "https://hooks.example.com/notty",
"events": ["entry.create", "entry.update", "entry.publish"],
"content_types": ["article", "page"],
"enabled": true
}
Webhook Signing
Add a secret to verify that webhook payloads come from your Notty instance:
{
"name": "Signed Webhook",
"url": "https://hooks.example.com/notty",
"events": ["entry.publish"],
"secret": "whsec_my-signing-secret"
}
Notty signs each payload with HMAC-SHA256. Verify the signature in your handler:
// Node.js webhook handler example
import crypto from 'crypto';
function verifyWebhook(payload, signature, secret) {
const expected = crypto.createHmac('sha256', secret).update(payload).digest('hex');
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}
// Express handler
app.post('/webhook', (req, res) => {
const signature = req.headers['x-webhook-signature'];
const isValid = verifyWebhook(JSON.stringify(req.body), signature, 'whsec_my-signing-secret');
if (!isValid) {
return res.status(401).send('Invalid signature');
}
const { event, data } = req.body;
console.log(`Received ${event}:`, data);
res.status(200).send('OK');
});
Custom Headers
Add custom headers to webhook requests:
{
"name": "With Auth Header",
"url": "https://hooks.example.com/notty",
"events": ["entry.publish"],
"headers": {
"X-API-Key": "your-external-api-key",
"X-Source": "notty-cms"
}
}
Webhook Management
| Method | Path | Description |
|---|---|---|
| GET | /api/webhooks |
List all webhooks |
| POST | /api/webhooks |
Create webhook |
| GET | /api/webhooks/:id |
Get webhook details |
| PUT | /api/webhooks/:id |
Update webhook |
| DELETE | /api/webhooks/:id |
Delete webhook |
| POST | /api/webhooks/:id/test |
Send a test payload |
| GET | /api/webhooks/:id/logs |
View delivery logs |
| POST | /api/webhooks/:id/replay/:logId |
Replay a failed delivery |
| GET | /api/webhooks/:id/stats |
Delivery statistics |
Delivery Logs
Every webhook delivery is logged. View delivery history:
curl http://localhost:2102/api/webhooks/1/logs \
-H "Authorization: Bearer $TOKEN"
Each log entry includes: status code, response time, request/response headers, and payload.
Failed Deliveries & Retry
Notty retries failed deliveries automatically. View the dead letter queue:
curl http://localhost:2102/api/webhooks/dead-letter \
-H "Authorization: Bearer $TOKEN"
Replay a specific failed delivery:
curl -X POST http://localhost:2102/api/webhooks/1/replay/42 \
-H "Authorization: Bearer $TOKEN"
Test a Webhook
Send a test payload without triggering real events:
curl -X POST http://localhost:2102/api/webhooks/1/test \
-H "Authorization: Bearer $TOKEN"
Use Cases
Trigger Static Site Rebuild
Fire a webhook on entry.publish to trigger a Vercel/Netlify deploy:
{
"name": "Vercel Deploy",
"url": "https://api.vercel.com/v1/integrations/deploy/prj_...",
"events": ["entry.publish", "entry.unpublish"],
"enabled": true
}
Sync to Search Engine
Push content updates to Algolia or Meilisearch:
{
"name": "Algolia Sync",
"url": "https://your-api.com/webhooks/algolia-sync",
"events": ["entry.create", "entry.update", "entry.delete", "entry.publish"],
"content_types": ["article", "product"],
"secret": "whsec_algolia-sync-secret"
}
Notify a Slack Channel
Send notifications when content is published:
{
"name": "Slack Notification",
"url": "https://hooks.slack.com/services/T.../B.../...",
"events": ["entry.publish"],
"headers": { "Content-Type": "application/json" }
}
OpenAPI Documentation
Notty auto-generates an OpenAPI specification for your content API. Access the interactive docs at:
http://localhost:2102/api/_docs
The spec is generated from your content schemas, so it always reflects the current data model. The viewer uses Scalar UI and requires authenticated access.
Full-Text Search
Search across all content types:
curl "http://localhost:2102/api/search?q=typescript&limit=20" \
-H "Authorization: Bearer $TOKEN"
Or search within a specific content type with searchFields:
curl "http://localhost:2102/api/content/article?search=typescript&searchFields=title,body" \
-H "Authorization: Bearer $TOKEN"
Aggregation API
Run aggregate queries for dashboards and analytics:
# Count articles by category
curl "http://localhost:2102/api/content/article/aggregate?function=count&field=id&groupBy[]=category_id" \
-H "Authorization: Bearer $TOKEN"
# Average product price
curl "http://localhost:2102/api/content/product/aggregate?function=avg&field=price" \
-H "Authorization: Bearer $TOKEN"
Available functions: count, sum, avg, min, max.
GraphQL API
Notty also provides a GraphQL endpoint auto-generated from your content schemas:
curl -X POST http://localhost:2102/api/graphql \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"query": "{ articles { data { id title body category { name } } } }"
}'
Interactive GraphiQL playground is available at http://localhost:2102/api/graphql in the browser.
Источник: docs/guide/webhooks.md. Снимок документации исходного проекта. Технический справочник сохраняет язык оригинала.