Portal Community
Notion does not send webhooks natively: As of 2026, the Notion API does not support outbound webhooks — Notion cannot call this endpoint on its own. To trigger workflows from Notion events, use trigger/pageAdded or trigger/pageUpdated (polling-based). Use trigger/webhook when an external system (not Notion) pushes a payload that should trigger Notion operations.

When to Use

Configuration

Authentication (for the webhook trigger itself)

FieldRequiredDescription
WebhookUrlRead-onlyGenerated endpoint URL for this trigger. Copy and configure in the calling system. Example: https://hooks.bizfirstai.com/wh/abc123xyz.
AuthenticationOptionalWebhook security method: "None", "BasicAuth", or "HeaderToken". Default: "None".
HeadersOptionalExpected request headers for validation. Define as a key-value object. For HeaderToken authentication, specify the expected token header and value.

Notion Operation (downstream)

After this trigger fires, configure downstream Notion nodes using the payload data available via {{ $trigger.* }} expressions. The Notion API token for downstream nodes should come from the Credentials Manager, not from the webhook payload.

Notion Automation button integration: In Notion, you can configure a Button property on a database page. Set the button action to "Send HTTP Request" pointing to this webhook URL. When a user clicks the button, Notion POSTs the page ID and other metadata to the workflow. This is currently the most practical way to trigger a BizFirstAI workflow from within the Notion UI.

Sample Configuration

{
  "resource": "trigger",
  "operation": "webhook",
  "Authentication": "HeaderToken",
  "Headers": {
    "x-bfai-secret": "{{ $credentials.webhookSecret }}"
  }
}

Validation Errors

Error CodeCause
NOTION_VALIDATION_FAILEDIncoming payload is missing a required field expected by downstream nodes (e.g., pageId not provided in the POST body).
NOTION_INVALID_CONFIGWebhook authentication credentials are missing or misconfigured.
HTTP_401Request authentication header does not match the expected token. The webhook returns HTTP 401 to the caller.

Output

Trigger Output

FieldTypeDescription
bodyobjectFull parsed JSON body of the incoming POST request.
headersobjectHTTP request headers from the incoming call.
queryobjectURL query string parameters, if any.
timestampstringISO 8601 timestamp when the webhook was received.

Error Port

Authentication failures return an HTTP error to the caller. Downstream Notion node failures route to the error port of their respective nodes.

Sample Output

{
  "body": {
    "event": "deployment.success",
    "service": "checkout-api",
    "environment": "production",
    "buildId": "build-4821",
    "notionPageId": "e5f6a7b8-c9d0-1234-efab-345678901234",
    "deployedBy": "ci-bot@acmecorp.com",
    "timestamp": "2024-06-11T14:32:00Z"
  },
  "headers": {
    "content-type": "application/json",
    "x-bfai-secret": "***redacted***"
  },
  "query": {},
  "timestamp": "2024-06-11T14:32:01.000Z"
}

Expression Reference

ExpressionTypeUse
{{ $trigger.body.notionPageId }}stringPass to page/update or block/appendChildren as the target page
{{ $trigger.body.event }}stringRoute by event type in an IfCondition or Switch node
{{ $trigger.body.environment }}stringInclude in a log block appended to the page
{{ $trigger.timestamp }}stringLog when the webhook was received
{{ $trigger.headers['x-bfai-secret'] }}stringInspect incoming auth header for custom validation logic

Node Policies & GuardRails

PolicyDetail
Always authenticate the webhookNever leave the webhook endpoint open with Authentication: "None" in production. Use HeaderToken or BasicAuth to prevent unauthorized workflow triggers. Store the expected token in Credentials Manager.
Validate payload before Notion callsUse a Function or IfCondition node to validate that required fields (e.g., notionPageId) are present in the payload before calling Notion operations. Missing fields will cause NOTION_VALIDATION_FAILED errors in downstream nodes.
Do not pass credentials in payloadNever include Notion API tokens or other secrets in the webhook payload. All credentials must come from the BizFirst Credentials Manager.
Idempotency key for retriesIf the calling system retries on failure (e.g., with exponential backoff), include an idempotency key in the payload and check it in a Function node to prevent duplicate Notion writes.
Notion does not push nativelyUse trigger/pageAdded or trigger/pageUpdated to react to Notion events. This trigger is for inbound calls from non-Notion systems.

Workflow Examples

Example 1 — CI/CD Pipeline Writes to Notion

A GitHub Actions workflow calls this endpoint after each deployment. The BizFirstAI workflow appends a deployment log entry to a Notion page.

// Calling system (GitHub Actions):
// curl -X POST https://hooks.bizfirstai.com/wh/abc123xyz \
//   -H "x-bfai-secret: $SECRET" \
//   -H "Content-Type: application/json" \
//   -d '{"notionPageId":"e5f6a7b8-...","service":"checkout-api","status":"success","buildId":"build-4821"}'

// BizFirstAI workflow:
// Step 1: trigger/webhook (HeaderToken auth)
// Step 2: Validate payload fields
// Step 3: block/appendChildren
{
  "BlockId": "{{ $trigger.body.notionPageId }}",
  "Blocks": [{
    "object": "block", "type": "paragraph",
    "paragraph": { "rich_text": [{ "text": { "content": "{{ $trigger.body.service }} deployed ({{ $trigger.body.buildId }}) at {{ $trigger.timestamp }}" } }] }
  }]
}

Example 2 — Notion Button Triggers Workflow

A Notion automation runs when a user clicks a button on a page, sending the page ID to this webhook and triggering a multi-step enrichment workflow.

// Notion Button automation sends POST to webhook URL with:
// { "pageId": "e5f6a7b8-...", "triggeredBy": "user-uuid" }

// BizFirstAI workflow:
// Step 1: trigger/webhook
// Step 2: page/get { "Page": "{{ $trigger.body.pageId }}" }
// Step 3: FlowAiAgent — analyze page content
// Step 4: block/appendChildren — append analysis summary
// Step 5: page/update — set AnalyzedAt date property

Example 3 — External CRM Pushes Contact to Notion

A Salesforce workflow calls this webhook when a deal closes, creating a corresponding Notion customer success page.

// Payload: { "company": "Acme Corp", "dealValue": 50000, "owner": "sarah@acme.com", "closeDate": "2024-06-11" }

// Step 1: trigger/webhook (HeaderToken)
// Step 2: database/createPage
{
  "Database": "{{ $vars.customerSuccessDbId }}",
  "Properties": {
    "Name": { "title": [{ "text": { "content": "{{ $trigger.body.company }}" } }] },
    "DealValue": { "number": "{{ $trigger.body.dealValue }}" },
    "CloseDate": { "date": { "start": "{{ $trigger.body.closeDate }}" } },
    "Status": { "select": { "name": "Onboarding" } }
  }
}