Helpers
The SDK provides namespace objects. These objects replace the verbose JSON the Notion API
requires. All text-accepting helpers accept a string, a RichTextBuilder, or a raw
NotionRichText.
Table of Contents
Section titled “Table of Contents”Rich Text
Section titled “Rich Text”Build formatted rich text with a chainable API.
Basic Usage
Section titled “Basic Usage”import { richText } from '@visus-io/notion-sdk-ts';
// Plain textrichText('Hello world').build();
// Chained formattingrichText('Important').bold().italic().color('red').build();
// LinkrichText('Notion').link('https://notion.so').build();Combining Multiple Segments
Section titled “Combining Multiple Segments”// Use richText.join() to combine multiple segmentsrichText.join( richText('Normal '), richText('bold').bold(), richText(' and '), richText('italic').italic(),);Formatting Methods
Section titled “Formatting Methods”richText('text').bold(); // BoldrichText('text').italic(); // ItalicrichText('text').strikethrough(); // StrikethroughrichText('text').underline(); // UnderlinerichText('text').code(); // Inline coderichText('text').color('red'); // Text colorrichText('text').link('url'); // HyperlinkAvailable Colors
Section titled “Available Colors”'default', 'gray', 'brown', 'orange', 'yellow', 'green', 'blue', 'purple', 'pink', 'red', 'gray_background', 'brown_background', 'orange_background', 'yellow_background', 'green_background', 'blue_background', 'purple_background', 'pink_background', 'red_background'
Mentions
Section titled “Mentions”// Page mentionrichText.mentionPage('page-id').build();
// Database mentionrichText.mentionDatabase('db-id').build();
// User mentionrichText.mentionUser({ object: 'user', id: 'user-id' }).build();
// Date mentionrichText.mentionDate('2025-03-01').build();richText.mentionDate('2025-03-01', { end: '2025-03-15' }).build();
// Link preview mentionrichText.mentionLinkPreview('https://example.com').build();Equations
Section titled “Equations”// Inline equation (LaTeX syntax)richText.equation('E=mc^2').build();richText.equation('\\sum_{i=1}^{n} i').build();Block Builder
Section titled “Block Builder”These factory functions cover 32 of Notion’s 35 block types. Each function returns a plain
object ready for blocks.children.append() or pages.create(). The block types
child_database, child_page, and unsupported have no dedicated block.* factory. Create
child_database and child_page blocks with the Databases or Pages APIs
instead. The unsupported type is read-only.
Text Blocks
Section titled “Text Blocks”All text blocks accept string, RichTextBuilder, or NotionRichText.
import { block, richText } from '@visus-io/notion-sdk-ts';
// Headingsblock.heading1('Title');block.heading2('Subtitle');block.heading3('Section');block.heading4('Detail');
// Toggleable headingsblock.heading2('Subtitle', { isToggleable: true });
// Paragraphblock.paragraph('Plain text');block.paragraph(richText('Styled text').bold().color('blue'));
// Listsblock.bulletedListItem('First item');block.numberedListItem('Step one');block.toDo('Task', { checked: true });
// Toggle (collapsible)block.toggle('Click to expand', { children: [block.paragraph('Hidden content')],});
// Quoteblock.quote('A wise saying');
// Calloutblock.callout('Heads up!', { icon: { type: 'emoji', emoji: '⚠️' }, color: 'yellow_background',});
// Templateblock.template('Section template');block.template('Template with content', { children: [block.paragraph('Default content')],});Notion manages meeting notes blocks on the server. Client code cannot build them. Notion’s AI meeting notes feature sets a
meeting_notesblock’s title, status, and child block IDs: summary, notes, and transcript. A client cannot build this structure by hand.block.meetingNotes()is the renamed successor to the oldblock.transcription(). See the Migration Guide for details. The SDK keeps this method only to avoid a sudden removal from the helper surface.block.meetingNotes()is now@deprecated. Do not use it in new code. To read meeting notes, useblocks.meetingNotes.query()orpages.getMarkdown({ include_transcript: true }).
Code & Math
Section titled “Code & Math”// Code blockblock.code('const x = 42;', 'typescript');block.code('console.log("hello")', 'javascript', { caption: 'Example' });
// Equation blockblock.equation('\\sum_{i=1}^{n} i');Supported languages: abap, arduino, bash, basic, c, clojure, coffeescript, c++, c#, css, dart, diff, docker, elixir, elm, erlang, flow, fortran, f#, gherkin, glsl, go, graphql, groovy, haskell, html, java, javascript, json, julia, kotlin, latex, less, lisp, livescript, lua, makefile, markdown, markup, matlab, mermaid, nix, objective-c, ocaml, pascal, perl, php, plain text, powershell, prolog, protobuf, python, r, reason, ruby, rust, sass, scala, scheme, scss, shell, sql, swift, typescript, vb.net, verilog, vhdl, visual basic, webassembly, xml, yaml, java/c/c++/c#
Media Blocks
Section titled “Media Blocks”Media blocks accept a URL string or a FileSource object.
// Imagesblock.image('https://example.com/photo.png');block.image('https://example.com/photo.png', { caption: 'Photo' });
// Videoblock.video('https://example.com/video.mp4');
// Audioblock.audio('https://example.com/song.mp3');
// Fileblock.file('https://example.com/doc.pdf');
// PDFblock.pdf('https://example.com/doc.pdf');
// Using file upload IDsimport { notionFile } from '@visus-io/notion-sdk-ts';
block.image(notionFile.upload('upload-id'));Embed Blocks
Section titled “Embed Blocks”// Generic embedblock.embed('https://twitter.com/example/status/123');
// Bookmarkblock.bookmark('https://example.com');block.bookmark('https://example.com', { caption: 'Example site' });
// Link previewblock.linkPreview('https://github.com/example/repo');Structural Blocks
Section titled “Structural Blocks”// Dividerblock.divider();
// Breadcrumbblock.breadcrumb();
// Table of contentsblock.tableOfContents();block.tableOfContents({ color: 'gray_background' });
// Tableblock.table(3, { hasColumnHeader: true, hasRowHeader: false, children: [ block.tableRow(['Name', 'Role', 'Status']), block.tableRow(['Alice', 'Engineer', 'Active']), block.tableRow(['Bob', 'Designer', 'Active']), ],});
// Column list (multi-column layout)block.columnList([ [block.paragraph('Column 1')], [block.paragraph('Column 2')], [block.paragraph('Column 3')],]);
// Tabs: only paragraph blocks can be direct children of a tab block. Each tab// is modeled as one paragraph. Its rich text is the label. Its `children`// field holds the tab's content.import { icon } from '@visus-io/notion-sdk-ts';
block.tab([ { label: 'Overview', children: [block.paragraph('Intro text')] }, { label: 'Details', icon: icon.emoji('📋'), children: [block.paragraph('More info')] },]);Synced Blocks
Section titled “Synced Blocks”// Original synced blockblock.syncedBlock({ children: [block.paragraph('Original content')],});
// Reference to synced blockblock.syncedBlock({ syncedFrom: 'source-block-id' });Page Properties
Section titled “Page Properties”These factory functions set page property values. Use them when you create or update pages.
Basic Properties
Section titled “Basic Properties”import { prop, richText } from '@visus-io/notion-sdk-ts';
// Titleprop.title('My Task');
// Rich textprop.richText('Some notes');prop.richText(richText('Important').bold());
// Numberprop.number(95);prop.number(3.14);
// Checkboxprop.checkbox(true);prop.checkbox(false);
// URLprop.url('https://example.com');
// Emailprop.email('user@example.com');
// Phone numberprop.phoneNumber('+1-555-0100');Select Properties
Section titled “Select Properties”// Single selectprop.select('High');prop.select('Option Name');
// Multi-selectprop.multiSelect(['urgent', 'frontend']);prop.multiSelect(['tag1', 'tag2', 'tag3']);
// Statusprop.status('In Progress');Date Properties
Section titled “Date Properties”// Single dateprop.date('2025-03-01');
// Date rangeprop.date('2025-03-01', { end: '2025-03-15' });
// With timeprop.date('2025-03-01T10:00:00');
// Date range with timeprop.date('2025-03-01T10:00:00', { end: '2025-03-01T11:00:00' });
// With timezoneprop.date('2025-03-01T10:00:00', { timeZone: 'America/New_York' });Relation & People
Section titled “Relation & People”// Relation (link to other pages)prop.relation(['page-id-1', 'page-id-2']);prop.relation(['page-id']); // Single relation
// Peopleprop.people(['user-id-1', 'user-id-2']);prop.people(['user-id']); // Single person// Files (external URLs or uploaded files)prop.files([ { name: 'doc.pdf', url: 'https://example.com/doc.pdf' }, { name: 'image.png', url: 'https://example.com/image.png' },]);
// Single fileprop.files([{ name: 'doc.pdf', url: 'https://example.com/doc.pdf' }]);Verification
Section titled “Verification”// Mark verified (optionally with a verification date)prop.verification('verified');prop.verification('verified', { start: '2025-01-15' });prop.verification('verified', { start: '2025-01-15', end: '2025-06-15' });
// Mark unverifiedprop.verification('unverified');Clearing Properties
Section titled “Clearing Properties”Pass null to clear a scalar property value:
prop.number(null); // Clear numberprop.select(null); // Clear selectprop.status(null); // Clear statusprop.date(null); // Clear dateprop.url(null); // Clear URLprop.email(null); // Clear emailprop.phoneNumber(null); // Clear phone numberArray-based properties, such as multiSelect, relation, people, and files, do not
accept null. Pass an empty array to clear them instead:
prop.multiSelect([]); // Clear multi-selectprop.relation([]); // Clear relationprop.people([]); // Clear peopleprop.files([]); // Clear filesFilters
Section titled “Filters”The filter helpers return chainable builders for database queries.
Property Filters
Section titled “Property Filters”import { filter } from '@visus-io/notion-sdk-ts';
// Statusfilter.status('Status').equals('Active');filter.status('Status').doesNotEqual('Archived');
// Selectfilter.select('Priority').equals('High');filter.select('Priority').doesNotEqual('Low');
// Multi-selectfilter.multiSelect('Tags').contains('urgent');filter.multiSelect('Tags').doesNotContain('archived');
// Numberfilter.number('Score').equals(100);filter.number('Score').doesNotEqual(0);filter.number('Score').greaterThan(80);filter.number('Score').greaterThanOrEqualTo(90);filter.number('Score').lessThan(50);filter.number('Score').lessThanOrEqualTo(60);
// Checkboxfilter.checkbox('Done').equals(true);filter.checkbox('Done').equals(false);
// Datefilter.date('Due Date').equals('2025-03-01');filter.date('Due Date').before('2025-06-01');filter.date('Due Date').after('2025-01-01');filter.date('Due Date').onOrBefore('2025-06-01');filter.date('Due Date').onOrAfter('2025-01-01');
// Date relative filtersfilter.date('Due Date').pastWeek();filter.date('Due Date').pastMonth();filter.date('Due Date').pastYear();filter.date('Due Date').nextWeek();filter.date('Due Date').nextMonth();filter.date('Due Date').nextYear();
// Text (title or rich_text properties)filter.text('Description').equals('exact match');filter.text('Description').doesNotEqual('not this');filter.text('Description').contains('keyword');filter.text('Description').doesNotContain('exclude');filter.text('Description').startsWith('prefix');filter.text('Description').endsWith('suffix');
// Titlefilter.title('Name').equals('Task Name');filter.title('Name').contains('important');filter.title('Name').startsWith('Project');
// URL, Email, Phonefilter.url('Website').isNotEmpty();filter.url('Website').isEmpty();filter.email('Contact').isNotEmpty();filter.email('Contact').isEmpty();filter.phoneNumber('Phone').isNotEmpty();
// Peoplefilter.people('Assignee').contains('user-id');filter.people('Assignee').doesNotContain('user-id');filter.people('Assignee').isEmpty();filter.people('Assignee').isNotEmpty();
// Relationfilter.relation('Project').contains('page-id');filter.relation('Project').doesNotContain('page-id');filter.relation('Project').isEmpty();filter.relation('Project').isNotEmpty();
// Filesfilter.files('Attachments').isEmpty();filter.files('Attachments').isNotEmpty();Timestamp Filters
Section titled “Timestamp Filters”Timestamp filters do not require a property name.
// Created timefilter.createdTime().after('2025-01-01');filter.createdTime().before('2025-12-31');filter.createdTime().onOrAfter('2025-01-01');filter.createdTime().pastWeek();
// Last edited timefilter.lastEditedTime().after('2025-02-01');filter.lastEditedTime().pastMonth();Compound Filters
Section titled “Compound Filters”// AND: all conditions must be truefilter.and( filter.status('Status').equals('Active'), filter.number('Score').greaterThan(80), filter.date('Due Date').nextWeek(),);
// OR: at least one condition must be truefilter.or( filter.select('Priority').equals('High'), filter.date('Due Date').before('2025-03-01'), filter.checkbox('Urgent').equals(true),);
// Nested conditionsfilter.and( filter.status('Status').doesNotEqual('Done'), filter.or(filter.select('Priority').equals('High'), filter.date('Due Date').nextWeek()),);Sorting
Section titled “Sorting”Create sort parameters for database queries.
import { sort } from '@visus-io/notion-sdk-ts';
// Property sortsconst sorts = [ sort.property('Priority').ascending(), sort.property('Due Date').descending(), sort.property('Name').ascending(),];
// Timestamp sortsconst timestampSorts = [sort.createdTime().descending(), sort.lastEditedTime().ascending()];
// Use in database queryawait notion.databases.query('database-id', { sorts: [ sort.property('Status').ascending(), sort.property('Priority').descending(), sort.property('Due Date').ascending(), ],});Parent, Icon, Cover, and File
Section titled “Parent, Icon, Cover, and File”These helper functions build parent references, icons, covers, and file sources.
Parent Helpers
Section titled “Parent Helpers”import { parent } from '@visus-io/notion-sdk-ts';
// Page parentparent.page('page-id');
// Data source parent (for creating pages in databases)parent.dataSource('data-source-id', 'database-id');
// Workspace parent (for creating top-level pages/databases)parent.workspace();
// Block parent (for comments on blocks)parent.block('block-id');Icon Helpers
Section titled “Icon Helpers”import { icon } from '@visus-io/notion-sdk-ts';
// Emoji iconicon.emoji('🚀');icon.emoji('📚');
// External image iconicon.external('https://example.com/icon.png');
// Uploaded file iconicon.fileUpload('upload-id');
// Native icon-picker icon (optionally colored)icon.native('star circle');icon.native('star circle', 'blue');
// Custom workspace emoji (see notion.customEmojis.list())icon.customEmoji('custom-emoji-id');Native icon colors: 'gray', 'lightgray', 'brown', 'yellow', 'orange', 'green', 'blue', 'purple', 'pink', 'red'
Cover Helpers
Section titled “Cover Helpers”import { cover } from '@visus-io/notion-sdk-ts';
// External image covercover.external('https://example.com/banner.jpg');
// Uploaded file covercover.fileUpload('upload-id');File Source Helpers
Section titled “File Source Helpers”import { notionFile } from '@visus-io/notion-sdk-ts';
// External filenotionFile.external('https://example.com/doc.pdf');
// Uploaded filenotionFile.upload('upload-id');
// Use in blocksblock.image(notionFile.external('https://example.com/photo.jpg'));block.pdf(notionFile.upload('upload-id'));Webhooks
Section titled “Webhooks”Sign and verify Notion webhook payloads. Notion signs webhook requests with HMAC-SHA256. Notion
keys the signature with the subscription’s verification token. Notion signs the raw JSON request
body and sends the signature in an X-Notion-Signature: sha256=<hex digest> header.
import { webhook } from '@visus-io/notion-sdk-ts';
// Verify an incoming webhook requestconst isValid = webhook.verifySignature( rawBody, req.headers['x-notion-signature'], verificationToken,);
if (!isValid) { return res.status(401).send('Invalid signature');}
// Sign a payload yourself, e.g. to generate test signaturesconst signature = webhook.sign({ event: 'page.updated' }, verificationToken);verifySignature() returns false for any mismatch or malformed input. It never throws an
error. Internally, it uses a constant-time comparison.
rawBodymust be the exact raw request body Notion sent. Do not useJSON.stringify(parsedBody). Re-serializing a parsed object can produce a different byte sequence: a different key order or different whitespace. A different byte sequence silently breaks verification. Use your framework’s raw-body access, for example Express’sexpress.raw()andreq.rawBody. Do not usereq.bodyafter JSON middleware has already parsed the request.
Related Pages
Section titled “Related Pages”- Common Use Cases: practical examples that use helpers.
- Models: details on the returned model objects.
- API Reference: how to use helpers with API endpoints.
- Request Size Limits: size limits enforced by helpers.