A submission that lands in an inbox is a message; the same submission in a Notion database is a row with a status. It can be assigned, filtered, given a Kanban lane, and seen by the whole team without forwarding. If your team already runs on Notion, sending forms anywhere else means someone copies them in by hand - and eventually stops.
Set up the database and integration
- Create a Notion database with properties matching your form: Name (title), Email (email), Message (text), plus workflow properties like Status.
- Create an internal integration at notion.so/my-integrations and copy the secret.
- Share the database with the integration (Connections menu on the database page) - forgetting this is the classic silent failure; the API returns 404 as if the database does not exist.
The relay
Until the native Notion adapter ships, a small serverless function receives the WebForms webhook and creates the page. This is the whole thing:
export default async function handler(req, res) {
const body = req.body;
await fetch("https://api.notion.com/v1/pages", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.NOTION_TOKEN}`,
"Notion-Version": "2022-06-28",
"Content-Type": "application/json",
},
body: JSON.stringify({
parent: { database_id: process.env.NOTION_DATABASE_ID },
properties: {
Name: { title: [{ text: { content: body.data.name } }] },
Email: { email: body.data.email },
Message: {
rich_text: [{ text: { content: body.data.message ?? "" } }],
},
},
}),
});
res.status(200).json({ ok: true });
}Deploy it anywhere that runs a function, add the URL as a webhook destination, and submit once. The row appears with your workflow properties empty, ready for triage. Because spam is filtered before delivery, the database only accumulates real enquiries - a lead tracker full of junk rows stops being looked at within a week, which quietly kills the whole system.
Verify the webhook signature in the relay if the function URL is guessable; the delivery includes a signed header for exactly this. And set the Notion token as an environment variable, never in the code - the snippet above assumes both.