Webhooks let your integration receive real-time updates from Notion. Whenever a page or database changes, Notion sends a secure HTTP POST request to your webhook endpoint. This allows your application to respond to workspace activity as it happens — whether that’s syncing data, triggering automation, or keeping your UI in sync with user activity.
Think of it like this: Instead of repeatedly polling the Notion API to check if anything has changed, Notion will tell you the moment something important happens.
How webhooks work: A simple example
Let’s walk through an example from start to finish:
This flow lets you react quickly to user activity, without polling or guessing when something has changed.
Getting started with webhooks
Step 1 - Creating a webhook subscription
To receive webhook events, you’ll need to create a subscription through your integration settings. You’ll need to:
At this point, your webhook is created but not yet verified. To complete the setup, you’ll need to confirm that your endpoint can receive and respond to verification.
Step 2 - Verifying the subscription
When you create a subscription, Notion sends a one-time POST request to your webhook URL. The body of the request contains a verification_token, which proves that Notion can successfully reach your endpoint.
Example payload with verification_token:
You’ll need to:
Once submitted, your webhook subscription is considered active, and will start receiving events.
Step 3 - Validating event payloads (Recommended)
To help ensure the security of your integration, Notion includes a cryptographic signature with every webhook event we send. This allows you to verify that the payload was sent by Notion and hasn’t been modified in transit. While payload validation is optional, we recommend implementing it for any production environment.
How it works
In the previous step, Notion sent a one-time verification_token to your webhook URL. You’ll use this token to verify the authenticity of all subsequent webhook events.
Every webhook request from Notion includes an X-Notion-Signature header, which contains an HMAC-SHA256 hash of the request body, signed with your verification_token.
Sample X-Notion-Signature from Notion:
To validate the request, you can use the verification_token along with the event’s payload to recompute the signature and verify the request’s authenticity. If they match, the payload is trustworthy.
Sample code for computing the signature and validating the webhook payload:
Implementing this validation step is a small lift that adds a strong layer of security to your webhook integration. If you ever rotate or recreate your webhook subscription, be sure to update your stored verification_token.
Testing your webhook subscription
Once your webhook subscription is set up and verified, it’s a good idea to test that everything is working as expected. Below are three common test scenarios you can try, each corresponding to a supported event type. These tests simulate typical content updates and help ensure your endpoint is receiving and processing events correctly.
Test 1 - Change a page title
This test checks your webhook’s ability to handle aggregated events, which are delivered with a short delay to avoid sending redundant updates. You’ll need to:
This test checks event delivery for comments, which require specific capabilities. You’ll need to:
Important:
To receive this event, your integration must include the comment read capability in its configuration. You can confirm this in the Capabilities tab of your integration’s settings.
Test 3 - Modify a database schema
This test verifies that structural changes to databases are triggering events. You’ll need to:
Troubleshooting tips
If your webhook isn’t receiving events as expected, here are a few things to double-check. These are the most common reasons developers miss events during setup or testing.
🔒 1. Check access permissions
Make sure the integration has access to the object that triggered the event. For example, if a new page is created inside a private page your integration doesn’t have access to, the event won’t be triggered.
✅ 2. Confirm capabilities
Some event types require specific capabilities to be enabled for your integration.
For instance, to receive comment.created events, your integration must have the “comment read” capability selected. Without it, even if your integration has access to the page, the comment event won’t be delivered.
You can view and update your integration’s capabilities in the Capabilities section of your integration settings.
⏳ 3. Understand aggregated event timing
Not all webhook events are sent immediately. Some, like page.content_updated, are aggregated to reduce noise from frequent edits (e.g., typing, formatting, moving blocks). This is normal and helps group multiple rapid changes into a single webhook event. See Event Delivery for a deeper explanation.
☑️ Confirm your subscription status
Even if everything else is configured correctly, your webhook won’t receive events unless the subscription is active. Head to the Webhooks tab under your integration settings and make sure your subscription is active. If the status shows as paused, pending verification, or if the subscription was deleted, events won’t be delivered to your endpoint.
- Event types & delivery — Full list of supported event types, payload structure, and delivery behavior.
- Webhook event reference — API reference pages for each webhook event type with payload schemas.