Skip to content
Back to skills

Notion Management

ASecurity

Complete guide for working with Notion API in Node.js/JavaScript projects. Use when creating, updating, fetching, or managing Notion pages, databases, and properties. Includes proper handling of rich text, database schemas, multi-select fields, dates, and complex content structures. Triggers on tasks like "create a Notion page," "update database properties," "add content to Notion," or "manage Notion workflows."

  • 57 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 17, 2026
developmentjavascripttypescriptgojavanodegitapidatabaseperformance

Works with

  • cli
  • api

Security analysis

A100/100

Scanned October 17, 2026

npx -y skills add diegosouzapw/awesome-omni-skill --skill notion-management --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Notion Management?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Notion Management
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/diegosouzapw-notion-management/badge)](https://www.skillsdirectory.com/skills/diegosouzapw-notion-management)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: notion-management
description: Complete guide for working with Notion API in Node.js/JavaScript projects. Use when creating, updating, fetching, or managing Notion pages, databases, and properties. Includes proper handling of rich text, database schemas, multi-select fields, dates, and complex content structures. Triggers on tasks like "create a Notion page," "update database properties," "add content to Notion," or "manage Notion workflows."
license: MIT
---

# Notion Management Skill

Master working with the Notion API for Node.js/JavaScript development. This skill provides patterns, tools, and references for all common Notion operations.

## Quick Start

### Fetching Notion Resources

```typescript
// Fetch a page or database
const page = await notion_notion-fetch({
  id: "page-id-or-url"
});

// Pages return markdown content and properties
// Databases return schema, data sources, and views
```

### Creating Pages

```typescript
// Single page creation
const pages = await notion_notion-create-pages({
  pages: [{
    properties: {
      title: "My Page Title",
      // Other properties based on database schema
    },
    content: "# Markdown content here\n\nSupports rich markdown."
  }],
  parent: {
    data_source_id: "collection-id" // or page_id, or database_id
  }
});
```

### Updating Pages

```typescript
// Update properties
await notion_notion-update-page({
  page_id: "page-id",
  command: "update_properties",
  properties: {
    title: "Updated Title",
    status: "Done"
  }
});

// Replace all content
await notion_notion-update-page({
  page_id: "page-id",
  command: "replace_content",
  new_str: "# New content here"
});

// Replace specific section
await notion_notion-update-page({
  page_id: "page-id",
  command: "replace_content_range",
  selection_with_ellipsis: "# Old heading...last paragraph.",
  new_str: "# New heading\nNew content"
});

// Insert content after a section
await notion_notion-update-page({
  page_id: "page-id",
  command: "insert_content_after",
  selection_with_ellipsis: "## Section...end of section.",
  new_str: "\n## New Section\nNew content here"
});
```

## Common Property Types and Formats

### Simple Properties
- **title** (string): Page title, shown as large heading
- **rich_text** (string): Text field
- **url** (string): URL field
- **email** (string): Email field
- **phone_number** (string): Phone number
- **checkbox** (string): Use `"__YES__"` or `"__NO__"`
- **number** (number): Use JavaScript numbers, not strings

### Select Properties
```typescript
// single_select: Just use the option name
properties: {
  Status: "In Progress"  // Must match exact option name
}

// multi_select: Single string or comma-separated
// ❌ WRONG: ["option1", "option2"]  // Don't use arrays
// ❌ WRONG: "option1,option2"       // Don't use commas
// ✅ CORRECT: Need to use separate API calls or specific format
```

### Date Properties
```typescript
// Date properties use expanded format with three keys
properties: {
  "date:Due Date:start": "2025-01-30",
  "date:Due Date:end": null,  // Optional end date
  "date:Due Date:is_datetime": 0  // 0 for date, 1 for datetime
}
```

### Place Properties
```typescript
// Place/location properties use expanded format
properties: {
  "place:Office:name": "HQ",
  "place:Office:address": "123 Main St",
  "place:Office:latitude": 37.7749,
  "place:Office:longitude": -122.4194,
  "place:Office:google_place_id": "optional-id"
}
```

### Special Property Names
Properties named "id" or "url" (case-insensitive) must be prefixed with "userDefined:":
```typescript
properties: {
  "userDefined:id": "value",
  "userDefined:URL": "https://example.com"
}
```

## Multi-Select Fields - CRITICAL

**Common mistake**: Multi-select fields have strict validation. When creating or updating pages in a database with multi_select properties:

1. **Fetch the database first** to see available options:
   ```typescript
   const db = await notion_notion-fetch({ id: "database-id" });
   // Response shows: "Tags": {"options": [{"name": "Option1"}, {"name": "Option2"}]}
   ```

2. **Use only valid option names**:
   ```typescript
   properties: {
     Tags: "Option1"  // Single option as string
   }
   ```

3. **For multiple options**: Currently the API has limitations. Best practice:
   - Create the page with one tag
   - Update it with additional tags if needed
   - Or pass multiple tags separated by specific format (check database schema)

4. **Error handling**: If you get "Invalid multi_select value", check:
   - Is the option name spelled exactly as shown in database?
   - Are you passing a string, not an array?
   - Does the database schema allow this option?

## Database Operations

### Fetch Database Schema
```typescript
const db = await notion_notion-fetch({
  id: "database-id-or-url"
});

// Returns:
// - Database title and icon
// - Data sources (collections) within the database
// - Schema for each data source
// - Views available
```

### Creating Databases
```typescript
const db = await notion_notion-create-database({
  title: [{type: "text", text: {content: "My Database"}}],
  parent: {page_id: "parent-page-id"},
  properties: {
    "Task Name": {type: "title"},
    "Status": {
      type: "select",
      select: {
        options: [
          {name: "To Do", color: "red"},
          {name: "In Progress", color: "yellow"},
          {name: "Done", color: "green"}
        ]
      }
    },
    "Due Date": {type: "date"}
  }
});
```

### Updating Database Schema
```typescript
await notion_notion-update-database({
  database_id: "db-id",
  title: [{type: "text", text: {content: "New Title"}}],
  properties: {
    "New Property": {type: "rich_text"},
    "Property to Rename": {name: "Renamed Property"},
    "Property to Delete": null  // Set to null to remove
  }
});
```

## Content (Markdown) Guidelines

### Supported Markdown
- **Headings**: `# H1`, `## H2`, etc.
- **Lists**: Unordered `- item`, ordered `1. item`
- **Code**: Inline `` `code` `` and code blocks
- **Bold/Italic**: `**bold**`, `*italic*`
- **Links**: `[text](url)`
- **Tables**: Full markdown table support
- **Quotes**: `> quoted text`
- **Toggles/Collapsible**: `▶ Collapsed content\n\tHidden items` (Note: indentation with tabs)

### Toggle/Collapsible Sections
Toggles are created with the `▶` character followed by content that should be hidden:

```markdown
▶ Click to expand
	Hidden content line 1
	Hidden content line 2
	- Nested list item
```

**Important**: Content after `▶` must be indented with tabs or spaces.

### Rich Text Annotations
Content can include color and style annotations:

```markdown
# Heading {color="blue"}
Some text {color="red"} and {bold="true"}
```

## Search and Navigation

### Search Notion
```typescript
const results = await notion_notion-search({
  query: "search term",
  query_type: "internal"  // or "user" for user search
});

// Filter by creation date
const filtered = await notion_notion-search({
  query: "recent docs",
  filters: {
    created_date_range: {
      start_date: "2025-01-01",
      end_date: "2025-01-31"
    }
  }
});
```

### Fetch Teams and Users
```typescript
// List teams
const teams = await notion_notion-get-teams({
  query: "engineering"  // optional search
});

// List users
const users = await notion_notion-get-users({
  query: "john",  // optional search
  page_size: 100
});

// Get specific user
const user = await notion_notion-get-users({
  user_id: "user-id-or-self"
});
```

## Error Handling

### Common Errors and Solutions

#### "Invalid multi_select value"
**Cause**: Option name doesn't exist or format is wrong
**Solution**: 
1. Fetch database to see valid options
2. Use exact option names
3. Pass as string, not array

#### "Invalid input" / Validation error
**Cause**: Wrong property format or type
**Solution**:
1. Check property type in database schema
2. Use correct format (e.g., date properties need date:Property:start format)
3. Verify special names use userDefined: prefix

#### "Page not found"
**Cause**: Wrong ID or insufficient permissions
**Solution**:
1. Verify page/database ID is correct
2. Check you have access to the resource
3. Use full URL if ID doesn't work

#### "Unauthorized"
**Cause**: Notion integration doesn't have permission
**Solution**:
1. Verify integration is shared with the database/page
2. Check integration scopes in Notion settings
3. Re-authenticate if needed

## Best Practices

1. **Always fetch first**: Before creating content in a database, fetch the database to understand its schema
2. **Validate option names**: Multi-select options are strictly validated—check exact spellings
3. **Use data_source_id for databases**: When a database has multiple data sources, use `data_source_id` instead of `database_id` as parent
4. **Handle IDs flexibly**: Most tools accept page IDs with or without dashes
5. **Content indentation**: Toggle/collapsible content must use tabs or spaces for indentation
6. **Break up complex updates**: Large content updates are safer when split into smaller operations
7. **Test with simple cases first**: Before complex automation, test with a single page/field
8. **Document environment**: Store Notion integration tokens securely, never in git

## Advanced Patterns

See [references/advanced-patterns.md](references/advanced-patterns.md) for:
- Batch operations and performance optimization
- Syncing external data to Notion
- Creating dynamic databases and views
- Handling relationships and rollups
- Complex filtering and sorting

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.