Webhooks Builder plan or higher
Webhooks make every submission a trigger: score a lead in n8n before it's even stored, reject spam with a rule you control, draft the reply email, open the Jira ticket, ping the on-call channel. Snapi calls your endpoint (or n8n, Make, Zapier — anything with a URL) at two moments — before a record is saved, where you can modify or veto it, and after, where the downstream automation begins. Configure both per page.
Webhook types
Each page supports two submission-timing webhooks, plus a third that fires when the page itself loads:
- Pre-event — fires before the record is saved. Your endpoint can return modified data, or reject the submission by responding with
{ "abort": true }. - Post-event — fires after the record is saved (fire-and-forget). The response is ignored; used for notifications, sync, and automation triggers.
- Onload — fires when the page opens, before any submission. Its response feeds
displayfield interpolation and, when atable/chartfield has no data source picked (see below), that field's rows too.
Configuring a webhook
- Optionally, open Settings → External APIs and add your n8n instance or any generic HTTP base URL as a reusable connection.
- Open the page in the builder and go to its Webhooks tab.
- For the Pre-Webhook and/or Post-Webhook, choose Manual URL or External API.
- Enter the full webhook URL (manual mode), or select a connection and enter the endpoint path to append to its base URL (external mode).
- Save.
Webhook URLs must use HTTPS and cannot point at private or local addresses.
Payload format
Snapi sends a POST request (or the method you configure) with Content-Type: application/json. When a new record is submitted, the pre-event webhook receives the page and the submitted data:
{
"entity": {
"id": "ent_abc123xyz",
"name": "Contact",
"slug": "contact"
},
"data": {
"name": "Alice Johnson",
"email": "alice@example.com",
"message": "Interested in a demo"
}
}
entities in the API and webhook payloads for backwards compatibility.Post-event webhooks include an event field, which is one of:
record.created— a record was created by a signed-in user or via the API; the payload includes the full savedrecord.record.updated— a record was updated; the payload includes the fullrecordplus achangesobject with old and new values.record.submitted— a public page submission; the payload is{ "event": "record.submitted", "recordId": "...", "data": { ... } }.
Deleting a record does not fire a webhook.
Pre-event webhooks
For pre-event webhooks, your endpoint can modify the record before it is saved. Return a JSON object with a data key containing the modified fields:
// Enrich or validate — return modified data
{
"data": {
"name": "Alice Johnson",
"email": "alice@example.com",
"score": 82
}
}
To reject the record, respond with a JSON body containing { "abort": true }. Snapi rejects the submission with a 409 Conflict error and includes your full response body in the error's details field.
When an existing record is updated, the pre-event payload is { "event": "record.updating", "record": { "id": "...", "data": { ... } }, "newData": { ... } } — respond the same way to modify or abort the update.
Securing your webhook endpoint
Snapi does not currently sign webhook payloads. To make sure requests hitting your endpoint really come from Snapi, include a secret token in the webhook URL and verify it on your server:
// Configure the webhook URL as:
// https://your-server.com/webhook/snapi?token=YOUR_SECRET
// Express example — reject requests without the shared secret
app.post('/webhook/snapi', (req, res) => {
if (req.query.token !== process.env.SNAPI_SHARED_SECRET) {
return res.status(401).end();
}
// ...handle the payload
});
Retry policy
Webhooks are not retried:
- Post-event webhooks are fire-and-forget — if your endpoint is down or returns an error, the delivery is skipped and the failure is logged on the server. The saved record is unaffected.
- Pre-event webhooks that time out or error are treated as a pass — the record is saved unchanged.
If you need guaranteed processing, point the webhook at a highly available receiver (such as an n8n instance) and queue the work there.
Pass-through pages (no persistence)
Sometimes you don't want Snapi storing anything at all — the page is just a secure front door to a workflow you're already running elsewhere, most often n8n. In the page's Webhooks tab, turn off Save submissions as records and submissions stop being written to Snapi's database entirely. Everything else about the page is unchanged: the pre-event webhook still runs first and can still modify or abort the submission, and the post-event webhook still fires after — there's just no record on the other end of it.
The response shape changes slightly since there's no saved record to return:
- Authenticated create (
POST /api/v1/entities/:id/records) responds with{ "persisted": false, "data": { ...whatever was submitted... } }instead of the usual saved record. - Public submit responds with
{ "success": true, "message": "...", "persisted": false }— norecordId, since none was created. - The post-event webhook payload drops the
record(orrecordId) field it would normally include, since neither exists — you get{ "event": "record.created", "data": { ... } }or{ "event": "record.submitted", "data": { ... } }. - Uploaded files aren't stored either (there's no record to attach them to), but they aren't dropped — each one is included in the post-event payload as
{ "files": [{ "field", "filename", "mime_type", "size", "data_base64" }] }so your workflow still receives it.
File uploads on the Free plan
Free- and Builder-plan pages don't accept file uploads at all — the rest of a submission still saves normally, but an uploaded file is neither stored nor forwarded anywhere. Webhooks are a Builder-plan-and-up feature (see Plans), so on Free there's no post-event webhook a file could be handed to the way a pass-through page's files are. File storage itself requires a Team plan or higher.
n8n integration
Snapi has first-class support for n8n. In Settings → External APIs, add an n8n connection with your instance's base URL. When configuring a webhook on a page, select this connection and enter your workflow's webhook path — Snapi combines it with the base URL for you.
Use the Webhook trigger node in n8n with POST method. The body will contain the full Snapi payload.