Models
All API methods return model instances with typed properties and helper methods. Every model validates raw API data through its Zod schema on construction.
Table of Contents
Section titled “Table of Contents”The Page model represents a Notion page.
Properties
Section titled “Properties”const page = await notion.pages.retrieve('page-id');
page.id; // UUIDpage.url; // Notion URLpage.publicUrl; // Public URL (if shared)page.createdTime; // Datepage.lastEditedTime; // Datepage.inTrash; // booleanpage.isArchived; // booleanpage.isLocked; // booleanpage.properties; // Record of property valuespage.parent; // Parent referenceNote: There is no
page.archivedgetter. Usepage.inTrashto check trash status instead.isArchivedis a separate, independent flag. It is distinct from trash status.
Methods
Section titled “Methods”// Get page title as plain textpage.getTitle(); // "My Page Title"
// Get specific property valuepage.getProperty('Name');page.getProperty('Status');
// Check parent typepage.isInDatabase(); // true if parent is a databasepage.isSubpage(); // true if parent is a page
// Get raw validated datapage.toJSON();Markdown Content
Section titled “Markdown Content”pages.create() accepts a markdown string as an alternative to properties/children.
pages.getMarkdown() and pages.updateMarkdown() read and write a page’s content as markdown
directly, instead of a block tree. updateMarkdown() returns an AsyncTask handle instead of the
finished content when allow_async: true triggers asynchronous processing; poll it with
notion.asyncTasks.poll(). See
Working with Markdown Content for a
full example.
Example Usage
Section titled “Example Usage”const page = await notion.pages.retrieve('page-id');
console.log(`Title: ${page.getTitle()}`);console.log(`URL: ${page.url}`);console.log(`Created: ${page.createdTime}`);console.log(`In trash: ${page.inTrash}`);
if (page.isInDatabase()) { console.log('This page is in a database');}
// Access propertiesif (page.properties.Status?.type === 'status') { console.log(`Status: ${page.properties.Status.status?.name}`);}The Block model represents any Notion block. The schema has 35 block types. See
Helpers for the block types that have a dedicated factory
function.
Properties
Section titled “Properties”const block = await notion.blocks.retrieve('block-id');
block.id; // UUIDblock.type; // 'paragraph' | 'heading_1' | 'heading_2' | ...block.hasChildren; // booleanblock.createdTime; // Dateblock.lastEditedTime; // Dateblock.inTrash; // booleanMethods
Section titled “Methods”// Type guardsblock.isTextBlock(); // paragraph, heading, list item, and moreblock.isHeading(); // heading_1, heading_2, heading_3, heading_4block.canHaveChildren(); // toggle, column, synced_block, tab, table, and more
// Extract text contentblock.getPlainText(); // Extract all text from the block
// Get raw validated datablock.toJSON();Example Usage
Section titled “Example Usage”const blocks = await notion.blocks.children.list('page-id');
for (const block of blocks.results) { console.log(`Type: ${block.type}`);
if (block.isTextBlock()) { console.log(`Text: ${block.getPlainText()}`); }
if (block.isHeading()) { console.log('This is a heading block'); }
if (block.hasChildren) { console.log('This block has children'); }}Accessing Block Content
Section titled “Accessing Block Content”The Block model exposes only the fields common to every block type. To read a
block-type-specific field, such as paragraph or code, call block.toJSON()
first. This returns the raw, schema-validated block object.
const block = await notion.blocks.retrieve('block-id');const data = block.toJSON();
// Paragraph blockif (data.type === 'paragraph') { console.log(data.paragraph?.rich_text); console.log(data.paragraph?.color);}
// Heading blockif (data.type === 'heading_1') { console.log(data.heading_1?.rich_text); console.log(data.heading_1?.is_toggleable);}
// Code blockif (data.type === 'code') { console.log(data.code?.rich_text); console.log(data.code?.language); console.log(data.code?.caption);}
// Image blockif (data.type === 'image' && data.image) { if (data.image.type === 'external') { console.log(data.image.external.url); } else if (data.image.type === 'file') { console.log(data.image.file.url); }}Database
Section titled “Database”The Database model represents a Notion database.
Properties
Section titled “Properties”const db = await notion.databases.retrieve('database-id');
db.id; // UUIDdb.title; // NotionRichTextdb.description; // NotionRichTextdb.dataSources; // DataSourceRef[]db.url; // Notion URLdb.publicUrl; // Public URL (if shared)db.isInline; // booleandb.parent; // Parent referencedb.icon; // Icon object (if set)db.cover; // Cover object (if set)db.createdTime; // Datedb.lastEditedTime; // Datedb.inTrash; // booleandb.isLocked; // booleanNote: There is no
db.archivedgetter. Usedb.inTrashto check trash status instead.
Methods
Section titled “Methods”// Get title and description as plain textdb.getTitle(); // "My Database"db.getDescription(); // "Database description"
// Check database typedb.isFullPage(); // true if not inline
// Check parent typedb.hasPageParent();db.hasWorkspaceParent();
// Get raw validated datadb.toJSON();Example Usage
Section titled “Example Usage”const db = await notion.databases.retrieve('database-id');
console.log(`Title: ${db.getTitle()}`);console.log(`URL: ${db.url}`);console.log(`Is inline: ${db.isInline}`);console.log(`Data sources: ${db.dataSources.length}`);
// Access first data sourceconst dataSourceId = db.dataSources[0].id;const dataSourceName = db.dataSources[0].name;
console.log(`Primary data source: ${dataSourceName} (${dataSourceId})`);DataSource
Section titled “DataSource”The DataSource model represents a database data source. This model was added in API version
2025-09-03.
Properties
Section titled “Properties”const ds = await notion.dataSources.retrieve('data-source-id');
ds.id; // UUIDds.title; // NotionRichTextds.description; // NotionRichTextds.properties; // Property configurationsds.parent; // Parent database referenceds.createdTime; // Dateds.lastEditedTime; // Dateds.inTrash; // booleanNote: There is no
ds.archivedgetter. Useds.inTrashto check trash status instead.
Methods
Section titled “Methods”// Get title and description as plain textds.getTitle(); // Plain-text version of ds.titleds.getDescription(); // Description or empty string
// Get parent database IDds.getParentDatabaseId(); // Database ID
// Property methodsds.getProperty('Name'); // Get specific property configds.getPropertyNames(); // Get all property namesds.hasProperty('Status'); // Check if property exists
// Get raw validated datads.toJSON();Example Usage
Section titled “Example Usage”const db = await notion.databases.retrieve('database-id');const dataSourceId = db.dataSources[0].id;
const ds = await notion.dataSources.retrieve(dataSourceId);
console.log(`Name: ${ds.getTitle()}`);console.log(`Properties: ${ds.getPropertyNames().join(', ')}`);
// Check for specific propertyif (ds.hasProperty('Status')) { const statusProp = ds.getProperty('Status'); console.log('Status property exists:', statusProp);}
// Update data source propertiesawait notion.dataSources.update(dataSourceId, { properties: { 'New Field': { number: {} }, },});The User model represents a Notion user. A user is either a person or a bot.
Properties
Section titled “Properties”const user = await notion.users.retrieve('user-id');
user.id; // UUIDuser.type; // 'person' | 'bot' | undefineduser.name; // string | undefineduser.avatarUrl; // string | null | undefinedMethods
Section titled “Methods”// Type guardsuser.isPerson(); // true if type === 'person'user.isBot(); // true if type === 'bot'
// Person-specificuser.getEmail(); // Email (person users only)
// Bot-specificuser.getBotInfo(); // Bot workspace info
// Get raw validated datauser.toJSON();Example Usage
Section titled “Example Usage”const user = await notion.users.retrieve('user-id');
console.log(`Name: ${user.name}`);console.log(`Avatar: ${user.avatarUrl}`);
if (user.isPerson()) { console.log(`Email: ${user.getEmail()}`);} else if (user.isBot()) { const botInfo = user.getBotInfo(); console.log(`Bot workspace: ${botInfo?.workspace_name}`);}
// List all usersconst users = await notion.users.list();for (const u of users.results) { console.log(`${u.name} (${u.type})`);}Comment
Section titled “Comment”The Comment model represents a comment on a page or block.
Properties
Section titled “Properties”const comments = await notion.comments.list('page-id');const comment = comments.results[0];
comment.id; // UUIDcomment.discussionId; // UUIDcomment.richText; // NotionRichTextcomment.createdTime; // Datecomment.createdBy; // User referencecomment.parent; // Parent referencecomment.attachments; // File attachmentscomment.displayName; // Custom display name (if set)Methods
Section titled “Methods”// Get comment textcomment.getPlainText(); // Plain text content
// Get display name (custom or from user)comment.getDisplayName(); // Resolved display name
// Check for attachments and custom namecomment.hasAttachments();comment.hasCustomDisplayName();
// Check parent typecomment.hasPageParent();comment.hasBlockParent();
// Get raw validated datacomment.toJSON();Example Usage
Section titled “Example Usage”const comments = await notion.comments.list('page-id');
for (const comment of comments.results) { console.log(`${comment.getDisplayName()}: ${comment.getPlainText()}`); console.log(`Created: ${comment.createdTime}`);
if (comment.hasAttachments()) { console.log(`Attachments: ${comment.attachments?.length}`); }}
// Create a commentawait notion.comments.create({ parent: { page_id: 'page-id' }, rich_text: [{ type: 'text', text: { content: 'Great work!' } }],});FileUpload
Section titled “FileUpload”The FileUpload model represents an uploaded file.
Properties
Section titled “Properties”const upload = await notion.fileUploads.retrieve('upload-id');
upload.id; // UUIDupload.status; // 'pending' | 'uploaded' | 'expired' | 'failed'upload.filename; // stringupload.contentType; // MIME typeupload.contentLength; // number (bytes)upload.uploadUrl; // Upload endpointupload.completeUrl; // Completion endpointMethods
Section titled “Methods”// Status checksupload.isPending(); // status === 'pending'upload.isUploaded(); // status === 'uploaded'upload.isExpired(); // status === 'expired'upload.isFailed(); // status === 'failed'
// Get raw validated dataupload.toJSON();Example Usage
Section titled “Example Usage”import { readFileSync } from 'fs';
// One-step uploadconst upload = await notion.fileUploads.uploadFile( 'document.pdf', readFileSync('./document.pdf'), 'application/pdf',);
console.log(`Upload status: ${upload.status}`);console.log(`File ID: ${upload.id}`);
if (upload.isUploaded()) { // Use the file in a page await notion.blocks.children.append('page-id', { children: [ { type: 'pdf', pdf: { type: 'file_upload', file_upload: { id: upload.id } }, }, ], });}
// Check upload status laterconst status = await notion.fileUploads.retrieve(upload.id);console.log(`Current status: ${status.status}`);AsyncTask
Section titled “AsyncTask”The AsyncTask model represents a long-running operation, for example an async markdown write.
You must poll this operation until it reaches a terminal status.
Properties
Section titled “Properties”const task = await notion.asyncTasks.retrieve('task-id');
task.id; // stringtask.status; // 'queued' | 'running' | 'retrying' | 'succeeded' | 'failed'task.statusUrl; // URL that can be polled for statustask.createdTime; // Datetask.operation; // { surface: 'rest' | 'mcp', name: string }task.pollAfterSeconds; // number | undefined: minimum seconds to wait before polling againtask.result; // unknown: present only when status === 'succeeded'task.error; // present only when status === 'failed'Methods
Section titled “Methods”task.isSucceeded(); // status === 'succeeded'task.isFailed(); // status === 'failed'task.isTerminal(); // isSucceeded() || isFailed()Example Usage
Section titled “Example Usage”const task = await notion.asyncTasks.poll('task-id', { timeoutMs: 60_000 });
if (task.isSucceeded()) { console.log(task.result);} else if (task.isFailed()) { console.error(task.error);}CustomEmoji
Section titled “CustomEmoji”The CustomEmoji model represents a custom emoji available in the workspace.
Properties
Section titled “Properties”const emojis = await notion.customEmojis.list();const emoji = emojis.results[0];
emoji.id; // stringemoji.name; // stringemoji.url; // string: the emoji's image URLExample Usage
Section titled “Example Usage”const emojis = await notion.customEmojis.list({ name: 'party-parrot' });
for (const emoji of emojis.results) { console.log(`${emoji.name}: ${emoji.url}`);}Reference a custom emoji as an icon with the icon.customEmoji(id) helper.
The View model represents how a database or data source displays its rows. Examples: table,
board, and calendar.
Properties
Section titled “Properties”const view = await notion.views.retrieve('view-id');
view.id; // stringview.parent; // Parent referenceview.dataSourceId; // string | null: null for dashboard viewsview.name; // stringview.type; // 'table' | 'board' | 'list' | 'calendar' | 'timeline' | 'gallery' | 'form' | 'chart' | 'map' | 'dashboard'view.filter; // Record<string, unknown> | null | undefinedview.sorts; // Record<string, unknown>[] | null | undefinedview.quickFilters; // Record<string, unknown> | null | undefinedview.configuration; // Per-layout configuration, if anyview.createdTime; // Dateview.lastEditedTime; // Dateview.createdBy; // User referenceview.lastEditedBy; // User referenceview.url; // Notion URLview.dashboardViewId; // string | undefined: set if this view is a dashboard widgetMethods
Section titled “Methods”view.isWidgetView(); // true if this view is a widget embedded in a dashboardExample Usage
Section titled “Example Usage”const views = await notion.views.list({ data_source_id: 'data-source-id' });
for (const view of views.results) { console.log(`${view.name} (${view.type})`);}
const query = await notion.views.queries.create('view-id', { filter: { property: 'Status', status: { equals: 'Done' } },});
for (const page of query.results) { console.log(page.getTitle());}RichText Utility
Section titled “RichText Utility”The RichText utility class parses and converts Notion rich text to other formats.
Constructor
Section titled “Constructor”import { RichText } from '@visus-io/notion-sdk-ts';
const rt = new RichText(page.properties.Name.title);Methods
Section titled “Methods”// Convert to different formatsrt.toPlainText(); // "Project Documentation"rt.toMarkdown(); // "**Project** Documentation"rt.toHTML(); // "<strong>Project</strong> Documentation"
// Link detectionrt.hasLinks(); // booleanrt.getLinks(); // string[] of all URLs
// Get raw datart.toJSON(); // Raw NotionRichTextSupported Conversions
Section titled “Supported Conversions”| Format | Bold | Italic | Strikethrough | Underline | Code | Link |
|---|---|---|---|---|---|---|
| Markdown | **text** |
*text* |
~~text~~ |
– | `text` |
[text](url) |
| HTML | <strong> |
<em> |
<s> |
<u> |
<code> |
<a href=""> |
Example Usage
Section titled “Example Usage”const page = await notion.pages.retrieve('page-id');const titleRichText = page.properties.Name.title;
const rt = new RichText(titleRichText);
console.log('Plain text:', rt.toPlainText());console.log('Markdown:', rt.toMarkdown());console.log('HTML:', rt.toHTML());
if (rt.hasLinks()) { console.log('Links:', rt.getLinks());}
// Use with any rich text propertyconst descriptionRt = new RichText(page.properties.Description.rich_text);console.log(descriptionRt.toMarkdown());Working with Block Text
Section titled “Working with Block Text”const blocks = await notion.blocks.children.list('page-id');
for (const block of blocks.results) { const data = block.toJSON(); if (data.type === 'paragraph' && data.paragraph) { const rt = new RichText(data.paragraph.rich_text); console.log('Plain:', rt.toPlainText()); console.log('HTML:', rt.toHTML()); }}Related Pages
Section titled “Related Pages”- Helpers: how to create data with helper functions.
- API Reference: API methods that return models.
- TypeScript Support: type definitions for models.
- Common Use Cases: practical examples that use models.