Send a Webhook to Notion: Transform & Forward Any Payload
Send any webhook to Notion. Step-by-step guide to forward incoming webhooks into a Notion database, transforming the payload into the Notion API format in flight.

You have a service that fires webhooks — a signup form, a payment provider, a CRM, a monitoring tool — and you want each event to land as a row in a Notion database. The problem: the Notion API won't accept the raw webhook. It expects a bearer token, a Notion-Version header and a properties object that matches your database schema exactly, and the payload your source sends never looks like that.
Webhook Relay sits in the middle. It receives the incoming webhook at a stable public URL, transforms the payload into the Notion "create a page" format, and delivers it to the Notion API — no glue server, no Lambda, no maintenance.
How it works
- Your source service POSTs its webhook to a Webhook Relay endpoint.
- A transformation function parses the payload and builds a Notion API request body.
- Webhook Relay forwards that to
https://api.notion.com/v1/pageswith your integration token, and a new row appears in your database.
Step 1: Create a Notion integration and share your database
- Go to notion.so/my-integrations and create a new internal integration. Copy its secret (it starts with
secret_orntn_). - Open the database you want to write to, click the ••• menu → Connections → add your integration so it has access.
- Note the database ID — it's the 32-character string in the database URL.
Step 2: Create a Webhook Relay output to the Notion API
Create a bucket with a public input, then add an output pointing at the Notion API:
- Output destination:
https://api.notion.com/v1/pages - Headers:
Authorization: Bearer <your-integration-secret>Notion-Version: 2022-06-28Content-Type: application/json
Step 3: Add a transformation function
Attach a function to the output that reshapes the incoming webhook into a Notion page. Map the fields you care about to your database's property names:
-- incoming payload is in r.RequestBody
local body = json.decode(r.RequestBody)
local page = {
parent = { database_id = "YOUR_DATABASE_ID" },
properties = {
Name = {
title = { { text = { content = body.name or "New event" } } }
},
Email = {
rich_text = { { text = { content = body.email or "" } } }
},
Amount = { number = body.amount or 0 }
}
}
r:SetRequestBody(json.encode(page))
Make sure each key under properties matches a column in your Notion database and uses the correct type (title, rich_text, number, select, date, checkbox).
Step 4: Point your source at the URL and test
Configure your source service's webhook to point at your Webhook Relay public URL. Trigger an event — or replay one from the Webhook Bin — and a new row appears in Notion within seconds. If the API rejects the request, the Webhook Relay logs show Notion's exact error so you can fix the property mapping.
Going further
- Fan out: send the same event to Slack, Discord or a Google Sheet at the same time with multiple destinations.
- Test locally first: receive the webhook on localhost to inspect the real payload before you write the mapping.
- Secure it: verify the source signature before forwarding so only legitimate events reach Notion.
Get started
Create a free Webhook Relay account and turn any webhook into Notion rows — no servers to run. New to webhooks? Start with what is a webhook and how to transform webhooks.
