trigger/webhook
Inbound webhook trigger that starts the workflow when an HTTP POST request is received at the generated webhook URL. Use this to accept calls from external systems that push data to trigger Notion-related workflows on demand.
trigger/webhook when an external system (not Notion) pushes a payload that should trigger Notion operations.
When to Use
- External system triggers Notion write: A GitHub Actions pipeline completes deployment and calls this webhook endpoint with deployment metadata. The workflow creates a Notion page or updates a database row with the deployment details.
- Zapier / third-party integration bridge: A Zapier automation or external tool that lacks a native Notion integration sends a structured payload to this webhook. The workflow parses the payload and performs the appropriate Notion operations.
- Notion Automation callback: Use Notion's built-in automations (button press, status change) to call a BizFirst webhook URL, bridging Notion's limited automation capabilities with BizFirstAI's full workflow engine.
- On-demand data push: An operator runs a script or uses a REST client to manually trigger a Notion data import by POSTing a payload to this endpoint, without needing to use the BizFirstAI UI.
- Cross-workflow chaining: Another BizFirstAI workflow calls this webhook to hand off work to a Notion-focused sub-workflow, decoupling complex multi-system automations into smaller maintainable workflows.
Configuration
Authentication (for the webhook trigger itself)
| Field | Required | Description |
|---|---|---|
WebhookUrl | Read-only | Generated endpoint URL for this trigger. Copy and configure in the calling system. Example: https://hooks.bizfirstai.com/wh/abc123xyz. |
Authentication | Optional | Webhook security method: "None", "BasicAuth", or "HeaderToken". Default: "None". |
Headers | Optional | Expected 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.
Sample Configuration
{
"resource": "trigger",
"operation": "webhook",
"Authentication": "HeaderToken",
"Headers": {
"x-bfai-secret": "{{ $credentials.webhookSecret }}"
}
}
Validation Errors
| Error Code | Cause |
|---|---|
NOTION_VALIDATION_FAILED | Incoming payload is missing a required field expected by downstream nodes (e.g., pageId not provided in the POST body). |
NOTION_INVALID_CONFIG | Webhook authentication credentials are missing or misconfigured. |
HTTP_401 | Request authentication header does not match the expected token. The webhook returns HTTP 401 to the caller. |
Output
Trigger Output
| Field | Type | Description |
|---|---|---|
body | object | Full parsed JSON body of the incoming POST request. |
headers | object | HTTP request headers from the incoming call. |
query | object | URL query string parameters, if any. |
timestamp | string | ISO 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
| Expression | Type | Use |
|---|---|---|
{{ $trigger.body.notionPageId }} | string | Pass to page/update or block/appendChildren as the target page |
{{ $trigger.body.event }} | string | Route by event type in an IfCondition or Switch node |
{{ $trigger.body.environment }} | string | Include in a log block appended to the page |
{{ $trigger.timestamp }} | string | Log when the webhook was received |
{{ $trigger.headers['x-bfai-secret'] }} | string | Inspect incoming auth header for custom validation logic |
Node Policies & GuardRails
| Policy | Detail |
|---|---|
| Always authenticate the webhook | Never 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 calls | Use 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 payload | Never include Notion API tokens or other secrets in the webhook payload. All credentials must come from the BizFirst Credentials Manager. |
| Idempotency key for retries | If 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 natively | Use 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" } }
}
}