A webhook sends a signed POST to your address when something changes in a project: rebuild a static site, revalidate a page or copy form submissions into another tool.
Add endpoints in Developers → Webhooks: a name, an https address and the events you want.
Events
| Event | When | data |
|---|---|---|
entry.published | an entry is published, or republished with changes | type, entry (id, title, locales, revision) |
entry.unpublished | an entry is taken off the live site | type, entry |
entry.deleted | an entry is deleted | type, entry |
type.updated | a type's structure changes | type, revision |
form.submitted | a form receives a submission | form, submission (data, page) |
ping | you press Send test |
Deliveries are written in the same transaction as the change and leave after it commits, so a change that fails sends nothing.
The request
POST https://your-site.com/api/manifolio
content-type: application/json
user-agent: Manifolio-Webhooks/1
manifolio-event: entry.published
manifolio-delivery: 01a1b2c3-0000-7000-8000-000000000009
manifolio-signature: t=1760300000,v1=5f2c4e1a9b{
"id": "evt_01a1b2c3",
"event": "entry.published",
"createdAt": "2026-10-12T09:00:00.000Z",
"project": { "id": "01a1b2c3-0000-7000-8000-000000000000", "slug": "aurora-coffee" },
"data": { "type": "article", "entry": { "id": "01a1b2c3-0000-7000-8000-000000000001", "title": "First post", "locales": ["en", "ro"], "revision": 7 } }
}Verifying the signature
Each endpoint has its own secret (whsec_), shown in the admin. The signature header is t=<unix seconds>,v1=<hex HMAC-SHA256 of "t.body">, computed over the raw body. Verify it before you trust anything in the request.
// app/api/manifolio/route.ts (Next.js)
import { revalidateTag } from "next/cache";
import { parseWebhook } from "@manifolio/sdk";
export async function POST(req: Request) {
const body = await req.text();
const event = await parseWebhook(process.env.MANIFOLIO_WEBHOOK_SECRET!, body, req.headers.get("manifolio-signature"));
if (event.event === "entry.published") revalidateTag(`manifolio:${event.data.type}`);
return new Response("ok");
}Without the SDK, compute HMAC-SHA256(secret, t + "." + body) in hex, compare it in constant time with v1 and reject a t more than five minutes away from your clock.
Retries
- Delivery is at least once. A retry can arrive after the first attempt succeeded, so keep the event
id(it stays the same on Retry) and skip what you have already handled. - Any answer other than
2xxcounts as a failure. Retries follow after 1 minute, 10 minutes and 1 hour, four attempts in total; then the delivery stays failed until you press Retry. - The timeout is 10 seconds. Redirects are not followed. The first 4 KB of your response are kept in the delivery history.
- Addresses must be public
httpson the standard port. Private, loopback and metadata addresses are refused when you save the endpoint and again on every delivery.
When a form or a submission is deleted, the copies in the delivery history lose their fields too.