Append Block Children
Append direct child blocks under a block and optionally choose the insertion point.
Append Block Children
Use Case
Use this endpoint to append new direct children under a block. You can optionally insert them before or after an existing child block.
Endpoint
| Item | Value |
|---|---|
| Method | PATCH |
| Path | /v2/blocks/:block_id/children |
| Request body | JSON |
| Returns | list of appended block objects |
| Scope | blocks.write |
Permissions
Requires blocks.write and write access to the parent block.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
block_id |
string | Yes | Parent block ID. |
children |
block input[] | Yes | Blocks to append. |
after |
string | No | Existing direct child block ID to insert after. Cannot be used with before. |
before |
string | No | Existing direct child block ID to insert before. Cannot be used with after. |
Request Example
{
"children": [
{
"object": "block",
"type": "paragraph",
"paragraph": {
"rich_text": [
{
"type": "text",
"text": {
"content": "Follow-up notes"
}
}
]
}
},
{
"object": "block",
"type": "to_do",
"to_do": {
"rich_text": [
{
"type": "text",
"text": {
"content": "Confirm launch date"
},
"annotations": {
"text_color": "black",
"background_color": "light_green"
}
}
],
"checked": false,
"text_color": "purple",
"background_color": "blue_purple"
}
}
],
"after": null
}
To insert before an existing direct child block, pass before instead:
{
"children": [
{
"object": "block",
"type": "paragraph",
"paragraph": {
"rich_text": [
{
"type": "text",
"text": {
"content": "Notes inserted before the target block"
}
}
]
}
}
],
"before": "12121212-1212-4212-8212-121212121212"
}
Nested Children
To append a subtree, put children on each block input, alongside type and its content object, not inside paragraph or toggle:
{
"children": [
{
"type": "toggle",
"toggle": {
"rich_text": [{ "type": "text", "text": { "content": "Topic" } }]
},
"children": [
{
"type": "bulleted_list_item",
"bulleted_list_item": {
"rich_text": [{ "type": "text", "text": { "content": "Item" } }]
},
"children": [
{
"type": "paragraph",
"paragraph": {
"rich_text": [{ "type": "text", "text": { "content": "Details" } }]
}
}
]
}
]
}
]
}
The entire subtree is validated before writing and submitted in one transaction. Each children array allows up to 100 blocks; only the request's root array must be nonempty. Sibling order is preserved at every level. before and after apply only to the root array, not to descendants. Invalid descendants reject the entire request, with a field path such as children.0.children.0.paragraph.text_color.
The response still lists only the directly appended blocks. A block with descendants has has_children: true; use Get Block Children to read each level. Native table rows must be nested under their table and have exactly table_width cells. Update Block cannot replace a subtree.
Response Example
{
"object": "list",
"results": [
{
"object": "block",
"id": "44444444-4444-4444-8444-444444444444",
"parent": {
"type": "page_id",
"page_id": "11111111-1111-4111-8111-111111111111"
},
"created_time": "2026-04-09T08:00:00.000Z",
"last_edited_time": "2026-04-09T09:30:00.000Z",
"created_by": {
"object": "user",
"id": "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb"
},
"last_edited_by": {
"object": "user",
"id": "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb"
},
"has_children": false,
"in_trash": false,
"type": "paragraph",
"paragraph": {
"rich_text": [
{
"type": "text",
"text": {
"content": "Project kickoff notes",
"link": null
},
"plain_text": "Project kickoff notes",
"href": null
}
],
"text_color": "default",
"background_color": "default"
}
}
],
"next_cursor": null,
"has_more": false
}
Behavior
childrenis required and can contain up to 100 blocks; the same limit applies to every nestedchildrenarray.- Only writable block types are accepted.
- Nested child blocks are supported for block types that can contain children.
- Page and inline mind maps use their type-specific
nodesfield for the initial node tree. Use the mind map endpoint for later node edits. - Existing databases, mind maps, and file blocks reject generic child appends. Create database records through the database API and edit mind-map nodes through the mind-map API.
- An existing
column_listaccepts only directcolumnchildren and cannot exceed 100 active columns after the append. - If neither
afternorbeforeis provided, new children are appended to the end of the parent block. - If
afteris provided, it must refer to an existing direct child of the parent block, and new children are inserted after it. - If
beforeis provided, it must refer to an existing direct child of the parent block, and new children are inserted before it. afterandbeforeare mutually exclusive. If both are provided, the request returns400 validation_error.- When multiple
childrenare provided, their array order is preserved at the insertion point. - Paragraphs, headings, list items, to-do items, quotes, toggles, and callouts can set
text_colorandbackground_colortogether. Theirrich_text[].annotationsobjects use the same two-channel format. - The legacy
colorfield remains accepted, but new integrations should use the explicit color fields.
Errors
400 validation_error: invalid children, bothafterandbeforeare provided, or theafter/beforevalue is not a direct child of the parent block.400 unsupported_block_type: child block type cannot be written.401 unauthorized: invalid or expired token.403 forbidden: missingblocks.writeor no access.404 not_found: parent block does not exist.