block/getChildren
Retrieve the direct child blocks of a Notion page or block. Notion content is organized as a tree of blocks — pages contain blocks, and blocks can contain nested child blocks. This operation retrieves one level of children at a time.
Block tree structure: Notion content is organized as a tree of blocks. A page's body is its top-level children. Toggle blocks, callouts, and lists may contain nested children — check the
has_children field on each returned block. To retrieve nested content, call block/getChildren again with the child block's ID.
When to Use
- AI summarization of meeting notes: Read the body blocks of a meeting notes page, concatenate the text content, and send it to a FlowAiAgent node to generate a summary or extract action items.
- Checklist extraction: Retrieve to-do blocks from a page and process each item as a task. Check
to_do.checkedto filter incomplete items for follow-up workflows. - Technical documentation extraction: Pull code blocks from a documentation page and use the code content in downstream processing — for example, to auto-deploy a configuration or validate syntax.
- Content migration: Read blocks from source Notion pages to reconstruct page content for migration to another workspace or content system.
- Table row reading: Retrieve table row blocks from a Notion inline table, extract cell text values, and use them as structured data in downstream nodes.
Configuration
Authentication
| Field | Required | Description |
|---|---|---|
AuthenticationMethod | Required | "ApiToken" or "OAuth2". |
ApiToken | Required | Notion Internal Integration Token starting with secret_. |
ClientId | OAuth2 | OAuth2 client ID. |
ClientSecret | OAuth2 | OAuth2 client secret. |
AccessToken | OAuth2 | OAuth2 access token. |
Operation Fields
| Field | Required | Description |
|---|---|---|
BlockId | Required | UUID of the parent page or block. Pass a page UUID to get the top-level body blocks of that page. |
ReturnAll | Optional | When true, automatically pages through all children. Default: false. |
Limit | Optional | Max blocks to return (1–100). Default: 100. |
StartCursor | Optional | Pagination cursor for fetching additional blocks beyond the initial set. |
Sample Configuration
{
"resource": "block",
"operation": "getChildren",
"AuthenticationMethod": "ApiToken",
"ApiToken": "{{ $credentials.notionApiToken }}",
"BlockId": "{{ $json.pageId }}",
"ReturnAll": true
}
Validation Errors
| Error Code | Cause |
|---|---|
NOTION_VALIDATION_FAILED | BlockId is empty or not a valid UUID. |
NOTION_NOT_FOUND | No page or block exists with the given UUID. |
NOTION_PERMISSION_DENIED | Integration not shared with the page containing this block. |
NOTION_RATE_LIMITED | Rate limit exceeded. |
NOTION_INVALID_REQUEST | StartCursor is invalid. |
Output
Success Port
| Field | Type | Description |
|---|---|---|
results | array | Array of block objects. Each block contains id, type, created_time, last_edited_time, has_children, and a type-specific content object (e.g., paragraph.rich_text, to_do.rich_text, to_do.checked). |
has_more | boolean | Whether additional sibling blocks exist beyond the current page. |
next_cursor | string | Pagination cursor for the next set of siblings. Null when has_more is false. |
Error Port
On failure the error port receives errorCode, message, and httpStatus.
Sample Output
{
"results": [
{
"id": "d0e1f2a3-b4c5-6789-defa-890123456789",
"type": "heading_2",
"created_time": "2024-06-10T09:00:00.000Z",
"last_edited_time": "2024-06-10T09:00:00.000Z",
"has_children": false,
"heading_2": {
"rich_text": [{ "type": "text", "text": { "content": "Action Items" }, "plain_text": "Action Items" }]
}
},
{
"id": "e1f2a3b4-c5d6-7890-efab-901234567890",
"type": "to_do",
"has_children": false,
"to_do": {
"rich_text": [{ "plain_text": "Send follow-up email to client" }],
"checked": false
}
},
{
"id": "f2a3b4c5-d6e7-8901-fabc-012345678901",
"type": "paragraph",
"has_children": false,
"paragraph": {
"rich_text": [{ "plain_text": "Deployment completed at 14:32 UTC" }]
}
}
],
"has_more": false,
"next_cursor": null
}
Expression Reference
| Expression | Type | Use |
|---|---|---|
{{ $output.getBlockChildren.results.length }} | number | Count total blocks on the page |
{{ $output.getBlockChildren.results[0].type }} | string | Check block type to filter by type in a Function node |
{{ $output.getBlockChildren.results[0].paragraph.rich_text[0].plain_text }} | string | Extract plain text from a paragraph block |
{{ $output.getBlockChildren.results[0].to_do.checked }} | boolean | Check whether a to-do item is complete |
{{ $output.getBlockChildren.results[0].has_children }} | boolean | Determine if a block has nested children to retrieve recursively |
Node Policies & GuardRails
| Policy | Detail |
|---|---|
| One level at a time | This operation retrieves only direct children. For deeply nested content (e.g., content inside a toggle inside a callout), call block/getChildren again with each child block's ID where has_children === true. |
| Extract text via plain_text | Each rich_text array item has a plain_text field that provides the raw string without annotations. Use this for downstream text processing rather than reconstructing text from the nested text.content structure. |
| Filter by type in Function node | Use a Function node after block/getChildren to filter for specific block types: results.filter(b => b.type === 'to_do'). This avoids processing irrelevant blocks in downstream loop iterations. |
| Page body vs block children | A page's UUID can be used as BlockId — this returns the top-level body blocks of the page, not its subpage list. There is no separate "get page content" endpoint; blocks are the content model. |
| Credentials in Credentials Manager | Always use {{ $credentials.notionApiToken }} — never hard-code the token. |
Workflow Examples
Example 1 — AI Meeting Notes Summarization
After a meeting trigger fires, read the meeting notes page blocks and send the text to FlowAiAgent for summarization.
// Step 1: trigger/pageAdded (meeting notes DB)
// Step 2: block/getChildren { "BlockId": "{{ $trigger.pageId }}", "ReturnAll": true }
// Step 3: Function node — extract all plain text
const text = $output.getBlockChildren.results
.filter(b => b.paragraph || b.heading_1 || b.heading_2 || b.bulleted_list_item)
.map(b => {
const key = b.type;
return b[key].rich_text.map(r => r.plain_text).join('');
}).join('\n');
return { pageText: text };
// Step 4: FlowAiAgent — summarize and extract action items
// Step 5: block/appendChildren — append summary back to the page
Example 2 — Incomplete To-Do Extraction
Read to-do blocks from a daily planning page and create Jira issues for any unchecked items.
// Step 1: block/getChildren (ReturnAll: true)
// Step 2: Function node — filter unchecked to-dos
const todos = $output.getBlockChildren.results
.filter(b => b.type === 'to_do' && !b.to_do.checked)
.map(b => b.to_do.rich_text[0]?.plain_text ?? '');
return { pendingTasks: todos };
// Step 3: Loop over pendingTasks → Jira issue/create
Example 3 — Recursive Deep Content Extraction
Extract all text from a page including nested blocks inside toggles.
// Step 1: block/getChildren (top level)
// Step 2: For each block where has_children === true:
// block/getChildren with that block's ID (nested level)
// Step 3: Merge all plain_text from both levels for processing