Portal Community
Append-only: The Notion API supports appending blocks at the end of a page but does not support inserting blocks at a specific position or replacing existing block content. If you need to update content, consider creating a new page or archiving and recreating the page with updated blocks.

When to Use

Configuration

Authentication

FieldRequiredDescription
AuthenticationMethodRequired"ApiToken" or "OAuth2".
ApiTokenRequiredNotion Internal Integration Token starting with secret_.
ClientIdOAuth2OAuth2 client ID.
ClientSecretOAuth2OAuth2 client secret.
AccessTokenOAuth2OAuth2 access token.

Operation Fields

FieldRequiredDescription
BlockIdRequiredUUID of the parent page or block to append content to. Use a page UUID to append to the page body.
BlocksRequiredArray of Notion block objects to append. Maximum 100 blocks per call. See block format examples below.

Sample Configuration

{
  "resource": "block",
  "operation": "appendChildren",
  "AuthenticationMethod": "ApiToken",
  "ApiToken": "{{ $credentials.notionApiToken }}",
  "BlockId": "{{ $json.pageId }}",
  "Blocks": [
    {
      "object": "block",
      "type": "heading_2",
      "heading_2": {
        "rich_text": [{ "type": "text", "text": { "content": "Deployment — {{ $now | date: 'YYYY-MM-DD HH:mm' }} UTC" } }]
      }
    },
    {
      "object": "block",
      "type": "paragraph",
      "paragraph": {
        "rich_text": [{ "type": "text", "text": { "content": "Environment: {{ $json.environment }}\nBuild: {{ $json.buildId }}\nStatus: {{ $json.status }}" } }]
      }
    },
    {
      "object": "block",
      "type": "divider",
      "divider": {}
    }
  ]
}

Block Type Reference

Block TypeKeyDescription
paragraphparagraph.rich_textStandard text paragraph.
heading_1heading_1.rich_textLarge heading.
heading_2heading_2.rich_textMedium heading.
heading_3heading_3.rich_textSmall heading.
bulleted_list_itembulleted_list_item.rich_textBulleted list item.
numbered_list_itemnumbered_list_item.rich_textNumbered list item.
to_doto_do.rich_text, to_do.checkedCheckbox to-do item.
codecode.rich_text, code.languageCode block with syntax highlighting.
dividerdivider: {}Horizontal rule separator.
calloutcallout.rich_text, callout.iconCallout box with icon.

Validation Errors

Error CodeCause
NOTION_VALIDATION_FAILEDBlockId is empty, not a valid UUID, or Blocks array is empty.
NOTION_INVALID_REQUESTA block object is malformed — missing required type key or rich_text structure. Verify each block has object: "block", type, and the type-specific content object.
NOTION_NOT_FOUNDParent page or block UUID does not exist.
NOTION_PERMISSION_DENIEDIntegration not shared with this page.
NOTION_RATE_LIMITEDRate limit exceeded.

Output

Success Port

FieldTypeDescription
resultsarrayArray of the newly created block objects, each with id, type, created_time, and type-specific content.

Error Port

On failure the error port receives errorCode, message, and httpStatus. A malformed block at any position causes the entire call to fail — none of the blocks in the array are appended on error.

Sample Output

{
  "results": [
    {
      "id": "a3b4c5d6-e7f8-9012-abcd-234567890123",
      "type": "heading_2",
      "created_time": "2024-06-11T14:32:00.000Z",
      "heading_2": {
        "rich_text": [{ "plain_text": "Deployment — 2024-06-11 14:32 UTC" }]
      }
    },
    {
      "id": "b4c5d6e7-f8a9-0123-bcde-345678901234",
      "type": "paragraph",
      "created_time": "2024-06-11T14:32:00.000Z",
      "paragraph": {
        "rich_text": [{ "plain_text": "Environment: production\nBuild: build-4821\nStatus: Success" }]
      }
    }
  ]
}

Expression Reference

ExpressionTypeUse
{{ $output.appendBlocks.results.length }}numberConfirm number of blocks appended
{{ $output.appendBlocks.results[0].id }}stringGet ID of first appended block for nested appends
{{ $output.appendBlocks.results[0].created_time }}stringLog append timestamp for audit

Node Policies & GuardRails

PolicyDetail
Maximum 100 blocks per callThe Notion API enforces a 100-block limit per append call. For large content sets, split into batches of 100 and call block/appendChildren multiple times sequentially.
All-or-nothing appendIf any block in the Blocks array is malformed, the entire call fails and no blocks are appended. Validate block structure in a Function node before calling this operation.
No insert or replaceBlocks are always appended at the end. There is no way to insert blocks at a specific position. Plan page structure so that appended content goes at the bottom, or use page/create with blocks for fully structured pages.
Check parent exists firstIf the parent page ID comes from a prior workflow step (e.g., a newly created page), verify the create operation succeeded before calling this node. An invalid parent ID causes NOTION_NOT_FOUND.
Credentials in Credentials ManagerAlways use {{ $credentials.notionApiToken }} — never hard-code the token.

Workflow Examples

Example 1 — Running Deployment Log

Each time a deployment pipeline fires, append a timestamped entry to a central deployment log page.

// Step 1: WebhookTrigger (CI/CD pipeline complete)
// Step 2: block/appendChildren
{
  "BlockId": "{{ $vars.deploymentLogPageId }}",
  "Blocks": [
    {
      "object": "block", "type": "heading_3",
      "heading_3": { "rich_text": [{ "text": { "content": "{{ $now | date: 'YYYY-MM-DD HH:mm' }} — {{ $json.service }}" } }] }
    },
    {
      "object": "block", "type": "bulleted_list_item",
      "bulleted_list_item": { "rich_text": [{ "text": { "content": "Status: {{ $json.status }}" } }] }
    },
    {
      "object": "block", "type": "bulleted_list_item",
      "bulleted_list_item": { "rich_text": [{ "text": { "content": "Build: {{ $json.buildId }}" } }] }
    },
    { "object": "block", "type": "divider", "divider": {} }
  ]
}

Example 2 — Append AI Summary to Meeting Notes

After summarizing a meeting page with FlowAiAgent, append the summary and action items back to the original page.

// Step 1: block/getChildren (read existing meeting notes)
// Step 2: FlowAiAgent (summarize + extract action items)
// Step 3: Function node — build block array from AI output
const blocks = [
  { object: "block", type: "divider", divider: {} },
  { object: "block", type: "heading_2", heading_2: { rich_text: [{ text: { content: "AI Summary" } }] } },
  { object: "block", type: "paragraph", paragraph: { rich_text: [{ text: { content: $json.summary } }] } },
  { object: "block", type: "heading_3", heading_3: { rich_text: [{ text: { content: "Action Items" } }] } },
  ...$json.actionItems.map(item => ({
    object: "block", type: "to_do",
    to_do: { rich_text: [{ text: { content: item } }], checked: false }
  }))
];
return { blocks };
// Step 4: block/appendChildren with generated blocks

Example 3 — Batch Large Content Append

Append more than 100 blocks by splitting into batches.

// Step 1: Build allBlocks array (200 items)
// Step 2: Split into batches of 100
const batches = [];
for (let i = 0; i < allBlocks.length; i += 100) {
  batches.push(allBlocks.slice(i, i + 100));
}
// Step 3: Loop over batches
// Step 4 per batch: block/appendChildren with batch items