Notion Webhook Integration​Notion ​Webhook ​Integration

Use Notion webhooks to trigger Kestra flows when pages or databases are updated in your Notion workspace.

This guide shows you how to create a workflow that responds to Notion database changes, retrieves page details, and sends notifications to Slack when new tasks are assigned.

Prerequisites

Before you begin, you need:

Create a Notion integration

  1. Go to Notion's My Integrations page
  2. Click "New integration"
  3. Give your integration a name and select your workspace
  4. Copy the Internal Integration Token - you'll need this for the NOTION_API_KEY secret

Share your database with the integration

  1. Open your Notion database
  2. Click the "..." menu in the top right
  3. Select "Add connections"
  4. Find and select your integration
  5. Click "Confirm" to grant access

Set up secrets in Kestra

Store your sensitive credentials as secrets or key-value pairs:

  1. Navigate to your namespace in the Kestra UI
  2. Go to the Secrets tab (Alternatively go to the KV Store tab and do the same)
  3. Create these secrets:
    • NOTION_API_KEY: Your Notion integration token
    • SLACK_WEBHOOK_URL: Your Slack incoming webhook URL

Create the webhook flow

Create a flow that listens for Notion webhook events and processes them:

yaml
id: notion-webhook
namespace: company.team

tasks:
  - id: get_notion_page_details
    type: io.kestra.plugin.notion.page.Read
    apiToken: "{{ secret('NOTION_API_KEY') }}"
    pageId: "{{ trigger.body.entity.id }}"
  
  - id: send_slack_alert
    type: io.kestra.plugin.notifications.slack.SlackIncomingWebhook
    url: "{{ secret('SLACK_WEBHOOK_URL') }}"
    messageText: "New task titled {{ outputs.get_notion_page_details | jq('.properties.Button.title[0].text.content') | first }} assigned to {{ outputs.get_notion_page_details | jq('.properties.Assignee.multi_select[0].name') | first }} on the Product team Notion board! Link: {{ outputs.get_notion_page_details.url }}"

triggers:
  - id: notion_new_task_webhook
    type: io.kestra.plugin.core.trigger.Webhook
    key: my-notion-product-alert-key # Replace with a secure key

Configure Notion webhooks

Set up webhooks directly in your Notion integration:

  1. Go to your Notion integration settings
  2. Select your integration
  3. Navigate to the "Webhooks" section
  4. Click "Add webhook"
  5. Enter your Kestra webhook URL (see format below)
  6. Select the events you want to listen for:
    • page.property_values.updated - When page properties change
    • page.created - When new pages are created
    • database.created - When new databases are created
  7. Click "Create" to save the webhook

Notion Integration UI

For more details, see the Notion Webhooks API documentation.

Webhook URL format

Your Kestra webhook URL follows this pattern:

text
http://your-kestra-host:8080/api/v1/main/executions/webhook/{namespace}/{flow_id}/{key}

For this example:

  • Namespace: company.team
  • Flow ID: notion-webhook
  • Key: my-notion-product-alert-key

Complete URL:

text
http://your-kestra-host:8080/api/v1/main/executions/webhook/company.team/notion-webhook/my-notion-product-alert-key

You can copy your webhook URL directly from the Kestra UI from the Triggers tab and paste it in Notion:

Copy Webhook URL

Testing the integration

Test your webhook flow manually:

bash
curl -X POST \
  http://your-kestra-host:8080/api/v1/main/executions/webhook/company.team/notion-webhook/my-notion-product-alert-key \
  -H "Content-Type: application/json" \
  -d '{"entity": {"id": "your-notion-page-id"}}'

Replace your-notion-page-id with an actual page ID from your Notion database.

Understanding the flow

The flow performs these steps:

  1. Webhook trigger: Listens for incoming webhook requests from Notion on the specified endpoint
  2. Get page details: Uses the Notion plugin to fetch complete page information from Notion
  3. Send notification: Extracts the task title and assignee information, then sends a formatted message to Slack

Customizing the flow

Different Notion properties

Modify the Slack message to use different Notion properties. Common property types include:

yaml
# For title properties
title: "{{ outputs.get_notion_page_details | jq('.properties.Title.title[0].text.content') | first }}"

# For select properties
status: "{{ outputs.get_notion_page_details | jq('.properties.Status.select.name') | first }}"

# For date properties
due_date: "{{ outputs.get_notion_page_details | jq('.properties.DueDate.date.start') | first }}"

# For people properties
assignee: "{{ outputs.get_notion_page_details | jq('.properties.Assignee.people[0].name') | first }}"

Adding conditional logic

Add conditions to process only specific types of changes:

yaml
tasks:
  - id: check_status
    type: io.kestra.plugin.core.flow.If
    condition: "{{ outputs.get_notion_page_details | jq('.properties.Status.select.name') | first == 'In Progress' }}"
    then:
      - id: send_slack_alert
        type: io.kestra.plugin.notifications.slack.SlackIncomingWebhook
        url: "{{ secret('SLACK_WEBHOOK_URL') }}"
        messageText: "Task moved to In Progress: {{ outputs.get_notion_page_details | jq('.properties.Title.title[0].text.content') | first }}"

Multiple notification channels

Send notifications to different channels based on the assignee or project:

yaml
tasks:
  - id: send_to_team_channel
    type: io.kestra.plugin.core.flow.If
    condition: "{{ outputs.get_notion_page_details | jq('.properties.Project.select.name') | first == 'Product' }}"
    then:
      - id: product_team_notification
        type: io.kestra.plugin.notifications.slack.SlackIncomingWebhook
        url: "{{ secret('PRODUCT_SLACK_WEBHOOK_URL') }}"
        messageText: "New product task assigned!"
    else:
      - id: general_notification
        type: io.kestra.plugin.notifications.slack.SlackIncomingWebhook
        url: "{{ secret('GENERAL_SLACK_WEBHOOK_URL') }}"
        messageText: "New task assigned!"

Security considerations

  • Use strong, randomly generated webhook keys
  • Store all sensitive tokens as secrets or key-value pairs
  • Consider implementing request validation in your webhook handler
  • Regularly rotate your API tokens and webhook URLs

Was this page helpful?