feat(triggers): add Notion webhook triggers (#3989)

* feat(triggers): add Notion webhook triggers for all event types

Add 9 Notion webhook triggers covering the full event lifecycle:
- Page events: created, properties updated, content updated, deleted
- Database events: created, schema updated, deleted
- Comment events: created
- Generic webhook trigger (all events)

Implements provider handler with HMAC SHA-256 signature verification,
event filtering via matchEvent, and structured input formatting.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(triggers): resolve type field collision in Notion trigger outputs

Rename nested `type` fields to `entity_type`/`parent_type` to avoid
collision with processOutputField's leaf node detection which checks
`'type' in field`. Remove spread of author outputs into `authors`
array which was overwriting `type: 'array'`.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(triggers): clarify Notion webhook signing secret vs verification_token

Update placeholder and description to distinguish the signing secret
(used for HMAC-SHA256 signature verification) from the verification_token
(one-time challenge echoed during initial setup).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor(webhooks): use createHmacVerifier for Notion provider handler

Replace inline verifyAuth boilerplate with createHmacVerifier utility,
consistent with Linear, Ashby, Cal.com, Circleback, Confluence, and
Fireflies providers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Waleed
2026-04-06 12:05:00 -07:00
committed by GitHub
parent 7ea06931c8
commit 21e5b5c594
16 changed files with 760 additions and 3 deletions

View File

@@ -8180,8 +8180,54 @@
"docsUrl": "https://docs.sim.ai/tools/notion",
"operations": [],
"operationCount": 0,
"triggers": [],
"triggerCount": 0,
"triggers": [
{
"id": "notion_page_created",
"name": "Notion Page Created",
"description": "Trigger workflow when a new page is created in Notion"
},
{
"id": "notion_page_properties_updated",
"name": "Notion Page Properties Updated",
"description": "Trigger workflow when page properties are modified in Notion"
},
{
"id": "notion_page_content_updated",
"name": "Notion Page Content Updated",
"description": "Trigger workflow when page content is changed in Notion"
},
{
"id": "notion_page_deleted",
"name": "Notion Page Deleted",
"description": "Trigger workflow when a page is deleted in Notion"
},
{
"id": "notion_database_created",
"name": "Notion Database Created",
"description": "Trigger workflow when a new database is created in Notion"
},
{
"id": "notion_database_schema_updated",
"name": "Notion Database Schema Updated",
"description": "Trigger workflow when a database schema is modified in Notion"
},
{
"id": "notion_database_deleted",
"name": "Notion Database Deleted",
"description": "Trigger workflow when a database is deleted in Notion"
},
{
"id": "notion_comment_created",
"name": "Notion Comment Created",
"description": "Trigger workflow when a comment or suggested edit is added in Notion"
},
{
"id": "notion_webhook",
"name": "Notion Webhook (All Events)",
"description": "Trigger workflow on any Notion webhook event"
}
],
"triggerCount": 9,
"authType": "oauth",
"category": "tools",
"integrationType": "documents",

View File

@@ -3,6 +3,7 @@ import type { BlockConfig } from '@/blocks/types'
import { AuthMode, IntegrationType } from '@/blocks/types'
import { createVersionedToolSelector } from '@/blocks/utils'
import type { NotionResponse } from '@/tools/notion/types'
import { getTrigger } from '@/triggers'
// Legacy block - hidden from toolbar
export const NotionBlock: BlockConfig<NotionResponse> = {
@@ -436,7 +437,34 @@ export const NotionV2Block: BlockConfig<any> = {
bgColor: '#181C1E',
icon: NotionIcon,
hideFromToolbar: false,
subBlocks: NotionBlock.subBlocks,
subBlocks: [
...NotionBlock.subBlocks,
// Trigger subBlocks
...getTrigger('notion_page_created').subBlocks,
...getTrigger('notion_page_properties_updated').subBlocks,
...getTrigger('notion_page_content_updated').subBlocks,
...getTrigger('notion_page_deleted').subBlocks,
...getTrigger('notion_database_created').subBlocks,
...getTrigger('notion_database_schema_updated').subBlocks,
...getTrigger('notion_database_deleted').subBlocks,
...getTrigger('notion_comment_created').subBlocks,
...getTrigger('notion_webhook').subBlocks,
],
triggers: {
enabled: true,
available: [
'notion_page_created',
'notion_page_properties_updated',
'notion_page_content_updated',
'notion_page_deleted',
'notion_database_created',
'notion_database_schema_updated',
'notion_database_deleted',
'notion_comment_created',
'notion_webhook',
],
},
tools: {
access: [
'notion_read_v2',

View File

@@ -0,0 +1,100 @@
import crypto from 'crypto'
import { createLogger } from '@sim/logger'
import { NextResponse } from 'next/server'
import { safeCompare } from '@/lib/core/security/encryption'
import type {
EventMatchContext,
FormatInputContext,
FormatInputResult,
WebhookProviderHandler,
} from '@/lib/webhooks/providers/types'
import { createHmacVerifier } from '@/lib/webhooks/providers/utils'
const logger = createLogger('WebhookProvider:Notion')
/**
* Validates a Notion webhook signature using HMAC SHA-256.
* Notion sends X-Notion-Signature as "sha256=<hex>".
*/
function validateNotionSignature(secret: string, signature: string, body: string): boolean {
try {
if (!secret || !signature || !body) {
logger.warn('Notion signature validation missing required fields', {
hasSecret: !!secret,
hasSignature: !!signature,
hasBody: !!body,
})
return false
}
const providedHash = signature.startsWith('sha256=') ? signature.slice(7) : signature
const computedHash = crypto.createHmac('sha256', secret).update(body, 'utf8').digest('hex')
logger.debug('Notion signature comparison', {
computedSignature: `${computedHash.substring(0, 10)}...`,
providedSignature: `${providedHash.substring(0, 10)}...`,
computedLength: computedHash.length,
providedLength: providedHash.length,
match: computedHash === providedHash,
})
return safeCompare(computedHash, providedHash)
} catch (error) {
logger.error('Error validating Notion signature:', error)
return false
}
}
export const notionHandler: WebhookProviderHandler = {
verifyAuth: createHmacVerifier({
configKey: 'webhookSecret',
headerName: 'X-Notion-Signature',
validateFn: validateNotionSignature,
providerLabel: 'Notion',
}),
async formatInput({ body }: FormatInputContext): Promise<FormatInputResult> {
const b = body as Record<string, unknown>
return {
input: {
id: b.id,
type: b.type,
timestamp: b.timestamp,
workspace_id: b.workspace_id,
workspace_name: b.workspace_name,
subscription_id: b.subscription_id,
integration_id: b.integration_id,
attempt_number: b.attempt_number,
authors: b.authors || [],
entity: b.entity || {},
data: b.data || {},
},
}
},
async matchEvent({ webhook, workflow, body, requestId, providerConfig }: EventMatchContext) {
const triggerId = providerConfig.triggerId as string | undefined
const obj = body as Record<string, unknown>
if (triggerId && triggerId !== 'notion_webhook') {
const { isNotionPayloadMatch } = await import('@/triggers/notion/utils')
if (!isNotionPayloadMatch(triggerId, obj)) {
const eventType = obj.type as string | undefined
logger.debug(
`[${requestId}] Notion event mismatch for trigger ${triggerId}. Event: ${eventType}. Skipping execution.`,
{
webhookId: webhook.id,
workflowId: workflow.id,
triggerId,
receivedEvent: eventType,
}
)
return NextResponse.json({
message: 'Event type does not match trigger configuration. Ignoring.',
})
}
}
return true
},
}

View File

@@ -23,6 +23,7 @@ import { jiraHandler } from '@/lib/webhooks/providers/jira'
import { lemlistHandler } from '@/lib/webhooks/providers/lemlist'
import { linearHandler } from '@/lib/webhooks/providers/linear'
import { microsoftTeamsHandler } from '@/lib/webhooks/providers/microsoft-teams'
import { notionHandler } from '@/lib/webhooks/providers/notion'
import { outlookHandler } from '@/lib/webhooks/providers/outlook'
import { resendHandler } from '@/lib/webhooks/providers/resend'
import { rssHandler } from '@/lib/webhooks/providers/rss'
@@ -64,6 +65,7 @@ const PROVIDER_HANDLERS: Record<string, WebhookProviderHandler> = {
linear: linearHandler,
resend: resendHandler,
'microsoft-teams': microsoftTeamsHandler,
notion: notionHandler,
outlook: outlookHandler,
rss: rssHandler,
slack: slackHandler,

View File

@@ -0,0 +1,38 @@
import { NotionIcon } from '@/components/icons'
import { buildTriggerSubBlocks } from '@/triggers'
import {
buildCommentEventOutputs,
buildNotionExtraFields,
notionSetupInstructions,
notionTriggerOptions,
} from '@/triggers/notion/utils'
import type { TriggerConfig } from '@/triggers/types'
/**
* Notion Comment Created Trigger
*/
export const notionCommentCreatedTrigger: TriggerConfig = {
id: 'notion_comment_created',
name: 'Notion Comment Created',
provider: 'notion',
description: 'Trigger workflow when a comment or suggested edit is added in Notion',
version: '1.0.0',
icon: NotionIcon,
subBlocks: buildTriggerSubBlocks({
triggerId: 'notion_comment_created',
triggerOptions: notionTriggerOptions,
setupInstructions: notionSetupInstructions('comment.created'),
extraFields: buildNotionExtraFields('notion_comment_created'),
}),
outputs: buildCommentEventOutputs(),
webhook: {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Notion-Signature': 'sha256=...',
},
},
}

View File

@@ -0,0 +1,38 @@
import { NotionIcon } from '@/components/icons'
import { buildTriggerSubBlocks } from '@/triggers'
import {
buildDatabaseEventOutputs,
buildNotionExtraFields,
notionSetupInstructions,
notionTriggerOptions,
} from '@/triggers/notion/utils'
import type { TriggerConfig } from '@/triggers/types'
/**
* Notion Database Created Trigger
*/
export const notionDatabaseCreatedTrigger: TriggerConfig = {
id: 'notion_database_created',
name: 'Notion Database Created',
provider: 'notion',
description: 'Trigger workflow when a new database is created in Notion',
version: '1.0.0',
icon: NotionIcon,
subBlocks: buildTriggerSubBlocks({
triggerId: 'notion_database_created',
triggerOptions: notionTriggerOptions,
setupInstructions: notionSetupInstructions('database.created'),
extraFields: buildNotionExtraFields('notion_database_created'),
}),
outputs: buildDatabaseEventOutputs(),
webhook: {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Notion-Signature': 'sha256=...',
},
},
}

View File

@@ -0,0 +1,38 @@
import { NotionIcon } from '@/components/icons'
import { buildTriggerSubBlocks } from '@/triggers'
import {
buildDatabaseEventOutputs,
buildNotionExtraFields,
notionSetupInstructions,
notionTriggerOptions,
} from '@/triggers/notion/utils'
import type { TriggerConfig } from '@/triggers/types'
/**
* Notion Database Deleted Trigger
*/
export const notionDatabaseDeletedTrigger: TriggerConfig = {
id: 'notion_database_deleted',
name: 'Notion Database Deleted',
provider: 'notion',
description: 'Trigger workflow when a database is deleted in Notion',
version: '1.0.0',
icon: NotionIcon,
subBlocks: buildTriggerSubBlocks({
triggerId: 'notion_database_deleted',
triggerOptions: notionTriggerOptions,
setupInstructions: notionSetupInstructions('database.deleted'),
extraFields: buildNotionExtraFields('notion_database_deleted'),
}),
outputs: buildDatabaseEventOutputs(),
webhook: {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Notion-Signature': 'sha256=...',
},
},
}

View File

@@ -0,0 +1,40 @@
import { NotionIcon } from '@/components/icons'
import { buildTriggerSubBlocks } from '@/triggers'
import {
buildDatabaseEventOutputs,
buildNotionExtraFields,
notionSetupInstructions,
notionTriggerOptions,
} from '@/triggers/notion/utils'
import type { TriggerConfig } from '@/triggers/types'
/**
* Notion Database Schema Updated Trigger
*
* Fires when a database schema (properties/columns) is modified.
*/
export const notionDatabaseSchemaUpdatedTrigger: TriggerConfig = {
id: 'notion_database_schema_updated',
name: 'Notion Database Schema Updated',
provider: 'notion',
description: 'Trigger workflow when a database schema is modified in Notion',
version: '1.0.0',
icon: NotionIcon,
subBlocks: buildTriggerSubBlocks({
triggerId: 'notion_database_schema_updated',
triggerOptions: notionTriggerOptions,
setupInstructions: notionSetupInstructions('database.schema_updated'),
extraFields: buildNotionExtraFields('notion_database_schema_updated'),
}),
outputs: buildDatabaseEventOutputs(),
webhook: {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Notion-Signature': 'sha256=...',
},
},
}

View File

@@ -0,0 +1,9 @@
export { notionCommentCreatedTrigger } from './comment_created'
export { notionDatabaseCreatedTrigger } from './database_created'
export { notionDatabaseDeletedTrigger } from './database_deleted'
export { notionDatabaseSchemaUpdatedTrigger } from './database_schema_updated'
export { notionPageContentUpdatedTrigger } from './page_content_updated'
export { notionPageCreatedTrigger } from './page_created'
export { notionPageDeletedTrigger } from './page_deleted'
export { notionPagePropertiesUpdatedTrigger } from './page_properties_updated'
export { notionWebhookTrigger } from './webhook'

View File

@@ -0,0 +1,40 @@
import { NotionIcon } from '@/components/icons'
import { buildTriggerSubBlocks } from '@/triggers'
import {
buildNotionExtraFields,
buildPageEventOutputs,
notionSetupInstructions,
notionTriggerOptions,
} from '@/triggers/notion/utils'
import type { TriggerConfig } from '@/triggers/types'
/**
* Notion Page Content Updated Trigger
*
* Fires when page content changes. High-frequency events may be batched.
*/
export const notionPageContentUpdatedTrigger: TriggerConfig = {
id: 'notion_page_content_updated',
name: 'Notion Page Content Updated',
provider: 'notion',
description: 'Trigger workflow when page content is changed in Notion',
version: '1.0.0',
icon: NotionIcon,
subBlocks: buildTriggerSubBlocks({
triggerId: 'notion_page_content_updated',
triggerOptions: notionTriggerOptions,
setupInstructions: notionSetupInstructions('page.content_updated'),
extraFields: buildNotionExtraFields('notion_page_content_updated'),
}),
outputs: buildPageEventOutputs(),
webhook: {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Notion-Signature': 'sha256=...',
},
},
}

View File

@@ -0,0 +1,41 @@
import { NotionIcon } from '@/components/icons'
import { buildTriggerSubBlocks } from '@/triggers'
import {
buildNotionExtraFields,
buildPageEventOutputs,
notionSetupInstructions,
notionTriggerOptions,
} from '@/triggers/notion/utils'
import type { TriggerConfig } from '@/triggers/types'
/**
* Notion Page Created Trigger
*
* This is the PRIMARY trigger - it includes the dropdown for selecting trigger type.
*/
export const notionPageCreatedTrigger: TriggerConfig = {
id: 'notion_page_created',
name: 'Notion Page Created',
provider: 'notion',
description: 'Trigger workflow when a new page is created in Notion',
version: '1.0.0',
icon: NotionIcon,
subBlocks: buildTriggerSubBlocks({
triggerId: 'notion_page_created',
triggerOptions: notionTriggerOptions,
includeDropdown: true,
setupInstructions: notionSetupInstructions('page.created'),
extraFields: buildNotionExtraFields('notion_page_created'),
}),
outputs: buildPageEventOutputs(),
webhook: {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Notion-Signature': 'sha256=...',
},
},
}

View File

@@ -0,0 +1,38 @@
import { NotionIcon } from '@/components/icons'
import { buildTriggerSubBlocks } from '@/triggers'
import {
buildNotionExtraFields,
buildPageEventOutputs,
notionSetupInstructions,
notionTriggerOptions,
} from '@/triggers/notion/utils'
import type { TriggerConfig } from '@/triggers/types'
/**
* Notion Page Deleted Trigger
*/
export const notionPageDeletedTrigger: TriggerConfig = {
id: 'notion_page_deleted',
name: 'Notion Page Deleted',
provider: 'notion',
description: 'Trigger workflow when a page is deleted in Notion',
version: '1.0.0',
icon: NotionIcon,
subBlocks: buildTriggerSubBlocks({
triggerId: 'notion_page_deleted',
triggerOptions: notionTriggerOptions,
setupInstructions: notionSetupInstructions('page.deleted'),
extraFields: buildNotionExtraFields('notion_page_deleted'),
}),
outputs: buildPageEventOutputs(),
webhook: {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Notion-Signature': 'sha256=...',
},
},
}

View File

@@ -0,0 +1,40 @@
import { NotionIcon } from '@/components/icons'
import { buildTriggerSubBlocks } from '@/triggers'
import {
buildNotionExtraFields,
buildPageEventOutputs,
notionSetupInstructions,
notionTriggerOptions,
} from '@/triggers/notion/utils'
import type { TriggerConfig } from '@/triggers/types'
/**
* Notion Page Properties Updated Trigger
*
* Fires when page properties (title, status, tags, etc.) are modified.
*/
export const notionPagePropertiesUpdatedTrigger: TriggerConfig = {
id: 'notion_page_properties_updated',
name: 'Notion Page Properties Updated',
provider: 'notion',
description: 'Trigger workflow when page properties are modified in Notion',
version: '1.0.0',
icon: NotionIcon,
subBlocks: buildTriggerSubBlocks({
triggerId: 'notion_page_properties_updated',
triggerOptions: notionTriggerOptions,
setupInstructions: notionSetupInstructions('page.properties_updated'),
extraFields: buildNotionExtraFields('notion_page_properties_updated'),
}),
outputs: buildPageEventOutputs(),
webhook: {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Notion-Signature': 'sha256=...',
},
},
}

View File

@@ -0,0 +1,201 @@
import type { SubBlockConfig } from '@/blocks/types'
import type { TriggerOutput } from '@/triggers/types'
/**
* Dropdown options for the Notion trigger type selector.
*/
export const notionTriggerOptions = [
{ label: 'Page Created', id: 'notion_page_created' },
{ label: 'Page Properties Updated', id: 'notion_page_properties_updated' },
{ label: 'Page Content Updated', id: 'notion_page_content_updated' },
{ label: 'Page Deleted', id: 'notion_page_deleted' },
{ label: 'Database Created', id: 'notion_database_created' },
{ label: 'Database Schema Updated', id: 'notion_database_schema_updated' },
{ label: 'Database Deleted', id: 'notion_database_deleted' },
{ label: 'Comment Created', id: 'notion_comment_created' },
{ label: 'Generic Webhook (All Events)', id: 'notion_webhook' },
]
/**
* Generates HTML setup instructions for Notion webhook triggers.
* Notion webhooks must be configured manually through the integration settings UI.
*/
export function notionSetupInstructions(eventType: string): string {
const instructions = [
'Go to <a href="https://www.notion.so/profile/integrations" target="_blank" rel="noopener noreferrer"><strong>notion.so/profile/integrations</strong></a> and select your integration (or create one).',
'Navigate to the <strong>Webhooks</strong> tab.',
'Click <strong>"Create a subscription"</strong>.',
'Paste the <strong>Webhook URL</strong> above into the URL field.',
`Select the <strong>${eventType}</strong> event type(s).`,
'Notion will send a verification request. Copy the <strong>verification_token</strong> from the payload and paste it into the Notion UI to complete verification.',
'Ensure the integration has access to the pages/databases you want to monitor (share them with the integration).',
]
return instructions
.map(
(instruction, index) =>
`<div class="mb-3"><strong>${index + 1}.</strong> ${instruction}</div>`
)
.join('')
}
/**
* Extra fields for Notion triggers (no extra fields needed since setup is manual).
*/
export function buildNotionExtraFields(triggerId: string): SubBlockConfig[] {
return [
{
id: 'webhookSecret',
title: 'Webhook Secret',
type: 'short-input',
placeholder: 'Enter your Notion webhook signing secret',
description:
'The signing secret from your Notion integration settings page, used to verify X-Notion-Signature headers. This is separate from the verification_token used during initial setup.',
password: true,
required: false,
mode: 'trigger',
condition: { field: 'selectedTriggerId', value: triggerId },
},
]
}
/**
* Base webhook outputs common to all Notion triggers.
*/
function buildBaseOutputs(): Record<string, TriggerOutput> {
return {
id: { type: 'string', description: 'Webhook event ID' },
type: {
type: 'string',
description: 'Event type (e.g., page.created, database.schema_updated)',
},
timestamp: { type: 'string', description: 'ISO 8601 timestamp of the event' },
workspace_id: { type: 'string', description: 'Workspace ID where the event occurred' },
workspace_name: { type: 'string', description: 'Workspace name' },
subscription_id: { type: 'string', description: 'Webhook subscription ID' },
integration_id: { type: 'string', description: 'Integration ID that received the event' },
attempt_number: { type: 'number', description: 'Delivery attempt number' },
}
}
/**
* Entity output schema (the resource that was affected).
*/
function buildEntityOutputs(): Record<string, TriggerOutput> {
return {
id: { type: 'string', description: 'Entity ID (page or database ID)' },
entity_type: { type: 'string', description: 'Entity type (page or database)' },
}
}
/**
* Build outputs for page event triggers.
*/
export function buildPageEventOutputs(): Record<string, TriggerOutput> {
return {
...buildBaseOutputs(),
authors: {
type: 'array',
description: 'Array of users who triggered the event',
},
entity: buildEntityOutputs(),
data: {
parent: {
id: { type: 'string', description: 'Parent page or database ID' },
parent_type: { type: 'string', description: 'Parent type (database, page, workspace)' },
},
},
}
}
/**
* Build outputs for database event triggers.
*/
export function buildDatabaseEventOutputs(): Record<string, TriggerOutput> {
return {
...buildBaseOutputs(),
authors: {
type: 'array',
description: 'Array of users who triggered the event',
},
entity: buildEntityOutputs(),
data: {
parent: {
id: { type: 'string', description: 'Parent page or workspace ID' },
parent_type: { type: 'string', description: 'Parent type (page, workspace)' },
},
},
}
}
/**
* Build outputs for comment event triggers.
*/
export function buildCommentEventOutputs(): Record<string, TriggerOutput> {
return {
...buildBaseOutputs(),
authors: {
type: 'array',
description: 'Array of users who triggered the event',
},
entity: {
id: { type: 'string', description: 'Comment ID' },
entity_type: { type: 'string', description: 'Entity type (comment)' },
},
data: {
parent: {
id: { type: 'string', description: 'Parent page ID' },
parent_type: { type: 'string', description: 'Parent type (page)' },
},
},
}
}
/**
* Build outputs for the generic webhook trigger (all events).
*/
export function buildGenericWebhookOutputs(): Record<string, TriggerOutput> {
return {
...buildBaseOutputs(),
authors: {
type: 'array',
description: 'Array of users who triggered the event',
},
entity: buildEntityOutputs(),
data: {
type: 'json',
description: 'Event-specific data including parent information',
},
}
}
/**
* Maps trigger IDs to the Notion event type strings they accept.
*/
const TRIGGER_EVENT_MAP: Record<string, string[]> = {
notion_page_created: ['page.created'],
notion_page_properties_updated: ['page.properties_updated'],
notion_page_content_updated: ['page.content_updated'],
notion_page_deleted: ['page.deleted'],
notion_database_created: ['database.created'],
notion_database_schema_updated: ['database.schema_updated'],
notion_database_deleted: ['database.deleted'],
notion_comment_created: ['comment.created'],
}
/**
* Checks if a Notion webhook payload matches a trigger.
*/
export function isNotionPayloadMatch(triggerId: string, body: Record<string, unknown>): boolean {
if (triggerId === 'notion_webhook') {
return true
}
const eventType = body.type as string | undefined
if (!eventType) {
return false
}
const acceptedEvents = TRIGGER_EVENT_MAP[triggerId]
return acceptedEvents ? acceptedEvents.includes(eventType) : false
}

View File

@@ -0,0 +1,38 @@
import { NotionIcon } from '@/components/icons'
import { buildTriggerSubBlocks } from '@/triggers'
import {
buildGenericWebhookOutputs,
buildNotionExtraFields,
notionSetupInstructions,
notionTriggerOptions,
} from '@/triggers/notion/utils'
import type { TriggerConfig } from '@/triggers/types'
/**
* Notion Generic Webhook Trigger (All Events)
*/
export const notionWebhookTrigger: TriggerConfig = {
id: 'notion_webhook',
name: 'Notion Webhook (All Events)',
provider: 'notion',
description: 'Trigger workflow on any Notion webhook event',
version: '1.0.0',
icon: NotionIcon,
subBlocks: buildTriggerSubBlocks({
triggerId: 'notion_webhook',
triggerOptions: notionTriggerOptions,
setupInstructions: notionSetupInstructions('all desired'),
extraFields: buildNotionExtraFields('notion_webhook'),
}),
outputs: buildGenericWebhookOutputs(),
webhook: {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Notion-Signature': 'sha256=...',
},
},
}

View File

@@ -189,6 +189,17 @@ import {
microsoftTeamsChatSubscriptionTrigger,
microsoftTeamsWebhookTrigger,
} from '@/triggers/microsoftteams'
import {
notionCommentCreatedTrigger,
notionDatabaseCreatedTrigger,
notionDatabaseDeletedTrigger,
notionDatabaseSchemaUpdatedTrigger,
notionPageContentUpdatedTrigger,
notionPageCreatedTrigger,
notionPageDeletedTrigger,
notionPagePropertiesUpdatedTrigger,
notionWebhookTrigger,
} from '@/triggers/notion'
import { outlookPollingTrigger } from '@/triggers/outlook'
import {
resendEmailBouncedTrigger,
@@ -353,6 +364,15 @@ export const TRIGGER_REGISTRY: TriggerRegistry = {
linear_customer_request_updated: linearCustomerRequestUpdatedTrigger,
microsoftteams_webhook: microsoftTeamsWebhookTrigger,
microsoftteams_chat_subscription: microsoftTeamsChatSubscriptionTrigger,
notion_page_created: notionPageCreatedTrigger,
notion_page_properties_updated: notionPagePropertiesUpdatedTrigger,
notion_page_content_updated: notionPageContentUpdatedTrigger,
notion_page_deleted: notionPageDeletedTrigger,
notion_database_created: notionDatabaseCreatedTrigger,
notion_database_schema_updated: notionDatabaseSchemaUpdatedTrigger,
notion_database_deleted: notionDatabaseDeletedTrigger,
notion_comment_created: notionCommentCreatedTrigger,
notion_webhook: notionWebhookTrigger,
outlook_poller: outlookPollingTrigger,
resend_email_sent: resendEmailSentTrigger,
resend_email_delivered: resendEmailDeliveredTrigger,