Skip to main content
PATCH
Edits a document’s content as text. Requires Update content. Creating a subpage with a <page> tag also requires Insert content. Set type to one operation and send that operation’s object under the same key.
string
required
Bearer <token>. See Tokens.
string
Optional. Only 2026-03-11 is accepted. Without it, the current version is used. A different value returns 400.
string
required
A document ID. A block ID or database ID returns 400.
string
required
insert_content, update_content, replace_content_range, or replace_content.
string
default:"v2"
Only v2 is accepted. v1 returns 400.
boolean
true returns 202 with a task. See Retrieve an async task.

Operations

insert_content

Adds content to the document.
string
required
The Markdown to add.
object
{ "type": "start" } or { "type": "end" }. The default is the end.
string
Adds it on a new line after this text, instead of using position. Uses the same pattern as content_range.

update_content

Replaces pieces of text. This is the safest way to edit a document people may be typing in, because lines you don’t change are left alone.
object[]
required
Applied in order. Each has old_str, new_str, and optional replace_all_matches.
boolean
true lets the edit remove subpages and inline databases.
  • old_str matching more than once returns 400 unless replace_all_matches is true.
  • If no old_str matches, the response is 400. If only some don’t match, the others are applied and the response has warnings with code no_match.

replace_content_range

Replaces one stretch of text.
string
required
start text...end text, or one piece of text. There must be exactly one match.
string
required
The new Markdown.
boolean
true lets the edit remove subpages and inline databases.

replace_content

Replaces the whole content.
string
required
The new Markdown.
boolean
true lets the edit remove subpages and inline databases.
replace_content has no version check. Anything a person typed after you read the document is overwritten. Use update_content when people may be editing.

How matching works

old_str, after, and content_range match the text from Retrieve as Markdown, not the text you sent earlier. Bold text reads as <b>text</b>, so **text** doesn’t match it. Read the document first. Uploaded file URLs change every time you read them. Match ![]( and not the full URL. replace_content compares files by the file itself, so it keeps them.

How edits are saved

The new text is compared to the current content, block by block.
  • Blocks with the same content are left alone and keep their IDs.
  • A changed block keeps its ID, even if its type changes.
  • A removed block goes to the trash and can be restored. See Delete a block.
  • Mentions always send notifications. notifications isn’t accepted here.

Markdown format

Send what Retrieve as Markdown returns. Reading a document and writing the same text back changes nothing. An unclosed tag returns 400 Markdown errors blocked parsing: followed by the problems.

Subpages, databases, and other kept blocks

<page url>, <database url>, <unknown>, synced blocks, and uploaded files stand for blocks already in this document. They only work in the document they came from. You can move the tag to move the block.

Limits

The block limits for Append block children don’t apply here, but the document limit does. Long text is split into items of 2,000 characters.

Response

A page_markdown object, the same as Retrieve as Markdown, plus warnings when there’s something to report.

Errors

See Common rules for shared errors.