notion-content-management

'Create, update, archive, and compose Notion pages and block content.

Allowed Tools

ReadWriteEdit

Provided by Plugin

notion-pack

Claude Code skill pack for Notion (30 skills)

saas packs v1.38.0
View Plugin

Installation

This skill is included in the notion-pack plugin:

/plugin install notion-pack@claude-code-plugins-plus

Click to copy

Instructions

Notion Content Management

Overview

Complete guide to creating, updating, archiving, and composing Notion pages and block content using the @notionhq/client SDK. Covers page lifecycle, all common block types, rich text formatting, and bulk content operations. The core workflow lives here at a high level; deep code walkthroughs are extracted into references/ so this file stays scannable.

Prerequisites

  • Completed notion-install-auth setup
  • NOTION_TOKEN environment variable set
  • Target database or page shared with the integration (via Connections menu)
  • @notionhq/client v2+ installed (TypeScript) or notion-client (Python)

Instructions

Step 1: Create, Update, and Archive Pages

Create a page in a database with typed properties (title, select, multi_select, date, people, number, checkbox, url), an optional icon/cover, and initial children block content. Update properties with pages.update (set a property to null to clear it). Archive is a soft-delete via archived: true, and restore flips it back to false.

Minimal skeleton:


import { Client } from '@notionhq/client';
const notion = new Client({ auth: process.env.NOTION_TOKEN });

const page = await notion.pages.create({
  parent: { database_id: databaseId },
  properties: { Name: { title: [{ text: { content: 'Q1 Retro' } }] } },
});
await notion.pages.update({ page_id: page.id, properties: { Status: { select: { name: 'Done' } } } });
await notion.pages.update({ page_id: page.id, archived: true });  // archive

Full typed-property create, update-with-clear, and archive/restore functions: page lifecycle walkthrough.

Step 2: Compose Content with Block Types

Append blocks to an existing page with blocks.children.append. Each block type has its own payload shape — headings, paragraphs (with rich text annotations), bulleted/numbered lists, to-dos, toggles, code blocks, callouts, quotes, dividers, images, and tables are all supported. The full catalog with the exact shape for every block type is in the block type catalog.

The minimal pattern:


await notion.blocks.children.append({
  block_id: pageId,
  children: [
    { heading_2: { rich_text: [{ text: { content: 'Notes' } }] } },
    {
      paragraph: {
        rich_text: [
          { text: { content: 'Plain and ' } },
          { text: { content: 'bold' }, annotations: { bold: true } },
        ],
      },
    },
    { to_do: { rich_text: [{ text: { content: 'Review PRs' } }], checked: false } },
  ],
});

Step 3: Update and Delete Individual Blocks

Retrieve, modify, and remove specific blocks: blocks.children.list (paginate with start_cursor), blocks.update to change content or toggle a to-do's checked state, blocks.delete to trash a block (recoverable for 30 days), and blocks.retrieve to fetch one block.

Minimal skeleton:


await notion.blocks.update({ block_id: blockId, to_do: { checked: true } });
await notion.blocks.delete({ block_id: blockId });

Full paginated list, rich-text update, to-do toggle, delete, and retrieve helpers: block editing walkthrough.

Output

  • Created pages with typed properties, icons, covers, and initial block content
  • Updated page properties and metadata
  • Archived and restored pages
  • Appended all common block types: headings, paragraphs, lists, to-dos, toggles, code, callouts, quotes, dividers, images, and tables
  • Retrieved, updated, and deleted individual blocks

Error Handling

Error Cause Solution
validation_error (400) Wrong property type or name Retrieve database schema with databases.retrieve() to confirm property names and types
objectnotfound (404) Page/block not shared with integration Open the page in Notion, click ... > Connections > add the integration
unauthorized (401) Invalid or expired token Regenerate at notion.so/my-integrations and update NOTION_TOKEN
rate_limited (429) Over 3 requests/second Implement exponential backoff; read Retry-After header
conflict_error (409) Concurrent edit to same block Retry with fresh block data from blocks.retrieve()
body too large (413) Over 100 blocks in one append Batch into chunks of 100 blocks per blocks.children.append call

Examples

A page builder composes a create call plus a structured blocks.children.append in sequence — for example, a standup note with heading2 sections, bulletedlistitem history, todo tasks, and a callout for blockers:


const page = await notion.pages.create({
  parent: { database_id: databaseId },
  properties: { Name: { title: [{ text: { content: `Standup ${new Date().toISOString().slice(0, 10)}` } }] } },
});
await notion.blocks.children.append({
  block_id: page.id,
  children: [
    { heading_2: { rich_text: [{ text: { content: 'Today' } }] } },
    { to_do: { rich_text: [{ text: { content: 'Build content module' } }], checked: false } },
  ],
});

Full worked examples — the complete page builder, a Python (notion-client) equivalent, and a chunked batch-append helper for payloads over 100 blocks — are in the worked examples reference.

Resources

Next, proceed to notion-data-handling for database queries, filtering, sorting, and pagination patterns.

Ready to use notion-pack?