@visus-io/notion-sdk-ts 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +66 -921
- package/dist/api/base.api.d.ts +161 -0
- package/dist/api/base.api.js +228 -0
- package/dist/api/blocks.api.d.ts +3867 -4
- package/dist/api/blocks.api.js +16 -47
- package/dist/api/comments.api.d.ts +259 -4
- package/dist/api/comments.api.js +11 -29
- package/dist/api/dataSources.api.d.ts +788 -4
- package/dist/api/dataSources.api.js +14 -28
- package/dist/api/databases.api.d.ts +491 -4
- package/dist/api/databases.api.js +20 -45
- package/dist/api/fileUploads.api.d.ts +25 -3
- package/dist/api/fileUploads.api.js +7 -2
- package/dist/api/index.d.ts +0 -1
- package/dist/api/index.js +0 -1
- package/dist/api/pages.api.d.ts +864 -3
- package/dist/api/pages.api.js +14 -28
- package/dist/api/search.api.d.ts +0 -1
- package/dist/api/search.api.js +5 -11
- package/dist/api/users.api.d.ts +40 -4
- package/dist/api/users.api.js +12 -35
- package/dist/client.d.ts +0 -1
- package/dist/client.js +0 -1
- package/dist/errors.d.ts +0 -1
- package/dist/errors.js +0 -1
- package/dist/helpers/block.helpers.d.ts +4 -1
- package/dist/helpers/block.helpers.js +11 -1
- package/dist/helpers/file.helpers.d.ts +0 -1
- package/dist/helpers/file.helpers.js +0 -1
- package/dist/helpers/filter.helpers.d.ts +0 -1
- package/dist/helpers/filter.helpers.js +0 -1
- package/dist/helpers/index.d.ts +0 -1
- package/dist/helpers/index.js +0 -1
- package/dist/helpers/pagination.helpers.d.ts +0 -1
- package/dist/helpers/pagination.helpers.js +0 -1
- package/dist/helpers/parent.helpers.d.ts +0 -1
- package/dist/helpers/parent.helpers.js +0 -1
- package/dist/helpers/property.helpers.d.ts +0 -1
- package/dist/helpers/property.helpers.js +0 -1
- package/dist/helpers/richText.helpers.d.ts +0 -1
- package/dist/helpers/richText.helpers.js +0 -1
- package/dist/helpers/sort.helpers.d.ts +0 -1
- package/dist/helpers/sort.helpers.js +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/models/base.model.d.ts +2 -3
- package/dist/models/base.model.js +0 -1
- package/dist/models/block.model.d.ts +0 -1
- package/dist/models/block.model.js +0 -1
- package/dist/models/comment.model.d.ts +0 -1
- package/dist/models/comment.model.js +0 -1
- package/dist/models/dataSource.model.d.ts +0 -1
- package/dist/models/dataSource.model.js +0 -1
- package/dist/models/database.model.d.ts +0 -1
- package/dist/models/database.model.js +0 -1
- package/dist/models/fileUpload.model.d.ts +0 -1
- package/dist/models/fileUpload.model.js +0 -1
- package/dist/models/index.d.ts +0 -1
- package/dist/models/index.js +0 -1
- package/dist/models/page.model.d.ts +0 -1
- package/dist/models/page.model.js +0 -1
- package/dist/models/richText.model.d.ts +0 -1
- package/dist/models/richText.model.js +0 -1
- package/dist/models/user.model.d.ts +0 -1
- package/dist/models/user.model.js +0 -1
- package/dist/notion.d.ts +0 -1
- package/dist/notion.js +0 -1
- package/dist/schemas/block.schema.d.ts +261 -82
- package/dist/schemas/block.schema.js +157 -82
- package/dist/schemas/codeLanguages.d.ts +0 -1
- package/dist/schemas/codeLanguages.js +0 -1
- package/dist/schemas/colors.d.ts +0 -1
- package/dist/schemas/colors.js +0 -1
- package/dist/schemas/comment.schema.d.ts +9 -10
- package/dist/schemas/comment.schema.js +54 -21
- package/dist/schemas/dataSource.schema.d.ts +13 -14
- package/dist/schemas/dataSource.schema.js +46 -13
- package/dist/schemas/database.schema.d.ts +13 -14
- package/dist/schemas/database.schema.js +51 -18
- package/dist/schemas/emoji.schema.d.ts +1 -2
- package/dist/schemas/emoji.schema.js +37 -5
- package/dist/schemas/file.schema.d.ts +3 -4
- package/dist/schemas/file.schema.js +49 -16
- package/dist/schemas/fileUpload.schema.d.ts +3 -4
- package/dist/schemas/fileUpload.schema.js +47 -14
- package/dist/schemas/index.d.ts +1 -1
- package/dist/schemas/index.js +1 -1
- package/dist/schemas/page.schema.d.ts +30 -31
- package/dist/schemas/page.schema.js +47 -14
- package/dist/schemas/pageProperties.schema.d.ts +47 -48
- package/dist/schemas/pageProperties.schema.js +162 -129
- package/dist/schemas/pagination.schema.d.ts +1 -2
- package/dist/schemas/pagination.schema.js +40 -8
- package/dist/schemas/parent.schema.d.ts +1 -2
- package/dist/schemas/parent.schema.js +51 -19
- package/dist/schemas/propertyObjects.schema.d.ts +1 -2
- package/dist/schemas/propertyObjects.schema.js +194 -162
- package/dist/schemas/richText.schema.d.ts +7 -8
- package/dist/schemas/richText.schema.js +95 -57
- package/dist/schemas/shared.schema.d.ts +15 -0
- package/dist/schemas/shared.schema.js +54 -0
- package/dist/schemas/user.schema.d.ts +3 -4
- package/dist/schemas/user.schema.js +63 -31
- package/dist/validation.d.ts +0 -1
- package/dist/validation.js +0 -1
- package/package.json +3 -1
- package/dist/api/blocks.api.d.ts.map +0 -1
- package/dist/api/blocks.api.js.map +0 -1
- package/dist/api/comments.api.d.ts.map +0 -1
- package/dist/api/comments.api.js.map +0 -1
- package/dist/api/dataSources.api.d.ts.map +0 -1
- package/dist/api/dataSources.api.js.map +0 -1
- package/dist/api/databases.api.d.ts.map +0 -1
- package/dist/api/databases.api.js.map +0 -1
- package/dist/api/fileUploads.api.d.ts.map +0 -1
- package/dist/api/fileUploads.api.js.map +0 -1
- package/dist/api/index.d.ts.map +0 -1
- package/dist/api/index.js.map +0 -1
- package/dist/api/pages.api.d.ts.map +0 -1
- package/dist/api/pages.api.js.map +0 -1
- package/dist/api/search.api.d.ts.map +0 -1
- package/dist/api/search.api.js.map +0 -1
- package/dist/api/users.api.d.ts.map +0 -1
- package/dist/api/users.api.js.map +0 -1
- package/dist/client.d.ts.map +0 -1
- package/dist/client.js.map +0 -1
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js.map +0 -1
- package/dist/helpers/block.helpers.d.ts.map +0 -1
- package/dist/helpers/block.helpers.js.map +0 -1
- package/dist/helpers/file.helpers.d.ts.map +0 -1
- package/dist/helpers/file.helpers.js.map +0 -1
- package/dist/helpers/filter.helpers.d.ts.map +0 -1
- package/dist/helpers/filter.helpers.js.map +0 -1
- package/dist/helpers/index.d.ts.map +0 -1
- package/dist/helpers/index.js.map +0 -1
- package/dist/helpers/pagination.helpers.d.ts.map +0 -1
- package/dist/helpers/pagination.helpers.js.map +0 -1
- package/dist/helpers/parent.helpers.d.ts.map +0 -1
- package/dist/helpers/parent.helpers.js.map +0 -1
- package/dist/helpers/property.helpers.d.ts.map +0 -1
- package/dist/helpers/property.helpers.js.map +0 -1
- package/dist/helpers/richText.helpers.d.ts.map +0 -1
- package/dist/helpers/richText.helpers.js.map +0 -1
- package/dist/helpers/sort.helpers.d.ts.map +0 -1
- package/dist/helpers/sort.helpers.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/models/base.model.d.ts.map +0 -1
- package/dist/models/base.model.js.map +0 -1
- package/dist/models/block.model.d.ts.map +0 -1
- package/dist/models/block.model.js.map +0 -1
- package/dist/models/comment.model.d.ts.map +0 -1
- package/dist/models/comment.model.js.map +0 -1
- package/dist/models/dataSource.model.d.ts.map +0 -1
- package/dist/models/dataSource.model.js.map +0 -1
- package/dist/models/database.model.d.ts.map +0 -1
- package/dist/models/database.model.js.map +0 -1
- package/dist/models/fileUpload.model.d.ts.map +0 -1
- package/dist/models/fileUpload.model.js.map +0 -1
- package/dist/models/index.d.ts.map +0 -1
- package/dist/models/index.js.map +0 -1
- package/dist/models/page.model.d.ts.map +0 -1
- package/dist/models/page.model.js.map +0 -1
- package/dist/models/richText.model.d.ts.map +0 -1
- package/dist/models/richText.model.js.map +0 -1
- package/dist/models/user.model.d.ts.map +0 -1
- package/dist/models/user.model.js.map +0 -1
- package/dist/notion.d.ts.map +0 -1
- package/dist/notion.js.map +0 -1
- package/dist/schemas/block.schema.d.ts.map +0 -1
- package/dist/schemas/block.schema.js.map +0 -1
- package/dist/schemas/codeLanguages.d.ts.map +0 -1
- package/dist/schemas/codeLanguages.js.map +0 -1
- package/dist/schemas/colors.d.ts.map +0 -1
- package/dist/schemas/colors.js.map +0 -1
- package/dist/schemas/comment.schema.d.ts.map +0 -1
- package/dist/schemas/comment.schema.js.map +0 -1
- package/dist/schemas/dataSource.schema.d.ts.map +0 -1
- package/dist/schemas/dataSource.schema.js.map +0 -1
- package/dist/schemas/database.schema.d.ts.map +0 -1
- package/dist/schemas/database.schema.js.map +0 -1
- package/dist/schemas/emoji.schema.d.ts.map +0 -1
- package/dist/schemas/emoji.schema.js.map +0 -1
- package/dist/schemas/file.schema.d.ts.map +0 -1
- package/dist/schemas/file.schema.js.map +0 -1
- package/dist/schemas/fileUpload.schema.d.ts.map +0 -1
- package/dist/schemas/fileUpload.schema.js.map +0 -1
- package/dist/schemas/index.d.ts.map +0 -1
- package/dist/schemas/index.js.map +0 -1
- package/dist/schemas/page.schema.d.ts.map +0 -1
- package/dist/schemas/page.schema.js.map +0 -1
- package/dist/schemas/pageProperties.schema.d.ts.map +0 -1
- package/dist/schemas/pageProperties.schema.js.map +0 -1
- package/dist/schemas/pagination.schema.d.ts.map +0 -1
- package/dist/schemas/pagination.schema.js.map +0 -1
- package/dist/schemas/parent.schema.d.ts.map +0 -1
- package/dist/schemas/parent.schema.js.map +0 -1
- package/dist/schemas/propertyObjects.schema.d.ts.map +0 -1
- package/dist/schemas/propertyObjects.schema.js.map +0 -1
- package/dist/schemas/richText.schema.d.ts.map +0 -1
- package/dist/schemas/richText.schema.js.map +0 -1
- package/dist/schemas/user.schema.d.ts.map +0 -1
- package/dist/schemas/user.schema.js.map +0 -1
- package/dist/validation.d.ts.map +0 -1
- package/dist/validation.js.map +0 -1
package/README.md
CHANGED
|
@@ -5,43 +5,12 @@
|
|
|
5
5
|
[](https://sonarcloud.io/summary/overall?id=visus%3Anotion-sdk-ts)
|
|
6
6
|
[](https://sonarcloud.io/summary/overall?id=visus%3Anotion-sdk-ts)
|
|
7
7
|
|
|
8
|
-

|
|
8
|
+
[](https://www.npmjs.com/package/@visus-io/notion-sdk-ts)
|
|
9
9
|

|
|
10
10
|

|
|
11
11
|
|
|
12
12
|
A type-safe TypeScript SDK for the Notion API with Zod validation, OOP models, and ergonomic helpers.
|
|
13
13
|
|
|
14
|
-
## Table of Contents
|
|
15
|
-
|
|
16
|
-
- [Features](#features)
|
|
17
|
-
- [Installation](#installation)
|
|
18
|
-
- [Migration to API Version 2025-09-03](#migration-to-api-version-2025-09-03)
|
|
19
|
-
- [Quick Start](#quick-start)
|
|
20
|
-
- [Helpers](#helpers)
|
|
21
|
-
- [Rich Text](#rich-text)
|
|
22
|
-
- [Block Builder](#block-builder)
|
|
23
|
-
- [Page Properties](#page-properties)
|
|
24
|
-
- [Filters](#filters)
|
|
25
|
-
- [Sorting](#sorting)
|
|
26
|
-
- [Parent, Icon, Cover & File](#parent-icon-cover--file)
|
|
27
|
-
- [Models](#models)
|
|
28
|
-
- [Error Handling](#error-handling)
|
|
29
|
-
- [Request Size Limits](#request-size-limits)
|
|
30
|
-
- [Pagination](#pagination)
|
|
31
|
-
- [Configuration](#configuration)
|
|
32
|
-
- [API Reference](#api-reference)
|
|
33
|
-
- [Pages](#pages-api)
|
|
34
|
-
- [Blocks](#blocks-api)
|
|
35
|
-
- [Databases](#databases-api)
|
|
36
|
-
- [Data Sources](#data-sources-api)
|
|
37
|
-
- [Comments](#comments-api)
|
|
38
|
-
- [Search](#search-api)
|
|
39
|
-
- [Users](#users-api)
|
|
40
|
-
- [File Uploads](#file-uploads-api)
|
|
41
|
-
- [TypeScript Support](#typescript-support)
|
|
42
|
-
- [Development](#development)
|
|
43
|
-
- [Project Structure](#project-structure)
|
|
44
|
-
|
|
45
14
|
## Features
|
|
46
15
|
|
|
47
16
|
- **Type-safe** Zod v4 runtime validation on every API response; full TypeScript declarations
|
|
@@ -57,159 +26,16 @@ A type-safe TypeScript SDK for the Notion API with Zod validation, OOP models, a
|
|
|
57
26
|
|
|
58
27
|
```bash
|
|
59
28
|
npm install @visus-io/notion-sdk-ts
|
|
29
|
+
# or
|
|
30
|
+
bun add @visus-io/notion-sdk-ts
|
|
60
31
|
```
|
|
61
32
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
**This SDK now defaults to Notion API version `2025-09-03`** (previously `2022-06-28`). This version introduces breaking changes to support multi-source databases.
|
|
65
|
-
|
|
66
|
-
### What Changed
|
|
67
|
-
|
|
68
|
-
**Database Creation**
|
|
69
|
-
|
|
70
|
-
- Properties are now specified under `initial_data_source.properties` instead of top-level `properties`
|
|
71
|
-
- Parent can be `{ page_id: string }` or `{ workspace: true }` (data source parents removed)
|
|
72
|
-
|
|
73
|
-
```typescript
|
|
74
|
-
// ❌ Old (2022-06-28)
|
|
75
|
-
await notion.databases.create({
|
|
76
|
-
parent: { page_id: 'page-id' },
|
|
77
|
-
properties: {
|
|
78
|
-
Name: { title: {} },
|
|
79
|
-
Status: {
|
|
80
|
-
select: {
|
|
81
|
-
options: [
|
|
82
|
-
/* ... */
|
|
83
|
-
],
|
|
84
|
-
},
|
|
85
|
-
},
|
|
86
|
-
},
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
// ✅ New (2025-09-03)
|
|
90
|
-
await notion.databases.create({
|
|
91
|
-
parent: { page_id: 'page-id' },
|
|
92
|
-
initial_data_source: {
|
|
93
|
-
properties: {
|
|
94
|
-
Name: { title: {} },
|
|
95
|
-
Status: {
|
|
96
|
-
select: {
|
|
97
|
-
options: [
|
|
98
|
-
/* ... */
|
|
99
|
-
],
|
|
100
|
-
},
|
|
101
|
-
},
|
|
102
|
-
},
|
|
103
|
-
},
|
|
104
|
-
});
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
**Database Updates**
|
|
108
|
-
|
|
109
|
-
- `properties` field removed from update options (use Data Sources API instead)
|
|
110
|
-
- Added `is_inline` and `parent` fields for moving/configuring databases
|
|
111
|
-
|
|
112
|
-
```typescript
|
|
113
|
-
// ❌ Old (2022-06-28) - properties updated on database
|
|
114
|
-
await notion.databases.update('db-id', {
|
|
115
|
-
properties: { NewField: { number: {} } },
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
// ✅ New (2025-09-03) - properties updated on data source
|
|
119
|
-
const db = await notion.databases.retrieve('db-id');
|
|
120
|
-
const dataSourceId = db.dataSources[0].id;
|
|
121
|
-
await notion.dataSources.update(dataSourceId, {
|
|
122
|
-
properties: { NewField: { number: {} } },
|
|
123
|
-
});
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
**Search API**
|
|
127
|
-
|
|
128
|
-
- Search now returns `DataSource` objects instead of `Database` objects
|
|
129
|
-
- Filter value changed from `'database'` to `'data_source'`
|
|
130
|
-
|
|
131
|
-
```typescript
|
|
132
|
-
// ❌ Old (2022-06-28)
|
|
133
|
-
const results = await notion.search.query({
|
|
134
|
-
filter: { property: 'object', value: 'database' },
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
// ✅ New (2025-09-03)
|
|
138
|
-
const results = await notion.search.query({
|
|
139
|
-
filter: { property: 'object', value: 'data_source' },
|
|
140
|
-
});
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
**Page Creation with Database Parent**
|
|
144
|
-
|
|
145
|
-
- Use `parent.dataSource(dataSourceId, databaseId)` instead of `parent.database(id)` for creating pages
|
|
146
|
-
- Both data source ID and database ID are required
|
|
147
|
-
|
|
148
|
-
```typescript
|
|
149
|
-
// ❌ Old (2022-06-28)
|
|
150
|
-
await notion.pages.create({
|
|
151
|
-
parent: parent.database('database-id'),
|
|
152
|
-
properties: {
|
|
153
|
-
/* ... */
|
|
154
|
-
},
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
// ✅ New (2025-09-03) - recommended
|
|
158
|
-
const db = await notion.databases.retrieve('database-id');
|
|
159
|
-
const dataSourceId = db.dataSources[0].id;
|
|
160
|
-
await notion.pages.create({
|
|
161
|
-
parent: parent.dataSource(dataSourceId, db.id),
|
|
162
|
-
properties: {
|
|
163
|
-
/* ... */
|
|
164
|
-
},
|
|
165
|
-
});
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
### How to Get Data Source IDs
|
|
169
|
-
|
|
170
|
-
```typescript
|
|
171
|
-
// Retrieve database to get its data sources
|
|
172
|
-
const database = await notion.databases.retrieve('database-id');
|
|
173
|
-
|
|
174
|
-
// Get the first (and usually only) data source
|
|
175
|
-
const dataSourceId = database.dataSources[0].id;
|
|
176
|
-
|
|
177
|
-
// Or iterate through all data sources
|
|
178
|
-
database.dataSources.forEach((ds) => {
|
|
179
|
-
console.log(`Data Source: ${ds.name} (${ds.id})`);
|
|
180
|
-
});
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
### Reverting to Old Version
|
|
184
|
-
|
|
185
|
-
If you need to stay on the old API version temporarily:
|
|
186
|
-
|
|
187
|
-
```typescript
|
|
188
|
-
const notion = new Notion({
|
|
189
|
-
auth: process.env.NOTION_TOKEN,
|
|
190
|
-
notionVersion: '2022-06-28', // Use old version
|
|
191
|
-
});
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
**Note:** The old version may not work correctly with databases that have multiple data sources. We recommend migrating to `2025-09-03` as soon as possible.
|
|
195
|
-
|
|
196
|
-
### More Information
|
|
197
|
-
|
|
198
|
-
For complete details, see the [official Notion API upgrade guide](https://developers.notion.com/guides/get-started/upgrade-guide-2025-09-03).
|
|
33
|
+
**Requirements:** Node.js 18+ or Bun 1.3.10+ (uses native `fetch`)
|
|
199
34
|
|
|
200
35
|
## Quick Start
|
|
201
36
|
|
|
202
37
|
```typescript
|
|
203
|
-
import {
|
|
204
|
-
Notion,
|
|
205
|
-
block,
|
|
206
|
-
richText,
|
|
207
|
-
filter,
|
|
208
|
-
sort,
|
|
209
|
-
prop,
|
|
210
|
-
parent,
|
|
211
|
-
paginate,
|
|
212
|
-
} from '@visus-io/notion-sdk-ts';
|
|
38
|
+
import { Notion, block, richText, filter, sort, prop, parent } from '@visus-io/notion-sdk-ts';
|
|
213
39
|
|
|
214
40
|
const notion = new Notion({ auth: process.env.NOTION_TOKEN });
|
|
215
41
|
|
|
@@ -217,7 +43,7 @@ const notion = new Notion({ auth: process.env.NOTION_TOKEN });
|
|
|
217
43
|
const page = await notion.pages.retrieve('page-id');
|
|
218
44
|
console.log(page.getTitle());
|
|
219
45
|
|
|
220
|
-
// Create a page in a database
|
|
46
|
+
// Create a page in a database
|
|
221
47
|
const database = await notion.databases.retrieve('database-id');
|
|
222
48
|
const dataSourceId = database.dataSources[0].id;
|
|
223
49
|
|
|
@@ -227,7 +53,6 @@ await notion.pages.create({
|
|
|
227
53
|
Name: prop.title('New Task'),
|
|
228
54
|
Status: prop.status('In Progress'),
|
|
229
55
|
Priority: prop.select('High'),
|
|
230
|
-
'Due Date': prop.date('2025-03-01'),
|
|
231
56
|
},
|
|
232
57
|
});
|
|
233
58
|
|
|
@@ -236,14 +61,11 @@ await notion.blocks.children.append('page-id', {
|
|
|
236
61
|
children: [
|
|
237
62
|
block.heading2('Meeting Notes'),
|
|
238
63
|
block.paragraph('Discussed the roadmap for Q2.'),
|
|
239
|
-
block.paragraph(richText('Action item: ').build().concat(richText('ship v2').bold().build())),
|
|
240
64
|
block.toDo('Follow up with design', { checked: false }),
|
|
241
|
-
block.divider(),
|
|
242
|
-
block.code('console.log("hello")', 'typescript'),
|
|
243
65
|
],
|
|
244
66
|
});
|
|
245
67
|
|
|
246
|
-
// Query a database with
|
|
68
|
+
// Query a database with filters
|
|
247
69
|
const results = await notion.databases.query('database-id', {
|
|
248
70
|
filter: filter.and(
|
|
249
71
|
filter.status('Status').equals('In Progress'),
|
|
@@ -251,780 +73,103 @@ const results = await notion.databases.query('database-id', {
|
|
|
251
73
|
),
|
|
252
74
|
sorts: [sort.property('Due Date').ascending()],
|
|
253
75
|
});
|
|
254
|
-
|
|
255
|
-
for (const page of results.results) {
|
|
256
|
-
console.log(page.getTitle(), page.url);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
// Search across workspace
|
|
260
|
-
const search = await notion.search.query({
|
|
261
|
-
query: 'project planning',
|
|
262
|
-
filter: { property: 'object', value: 'page' },
|
|
263
|
-
});
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
## Helpers
|
|
267
|
-
|
|
268
|
-
The SDK provides namespace objects that eliminate the verbose JSON the Notion API requires. All text-accepting helpers accept a `string`, a `RichTextBuilder`, or a raw `NotionRichText` array.
|
|
269
|
-
|
|
270
|
-
### Rich Text
|
|
271
|
-
|
|
272
|
-
Build formatted rich text with a chainable API:
|
|
273
|
-
|
|
274
|
-
```typescript
|
|
275
|
-
import { richText } from '@visus-io/notion-sdk-ts';
|
|
276
|
-
|
|
277
|
-
// Plain text
|
|
278
|
-
richText('Hello world').build();
|
|
279
|
-
|
|
280
|
-
// Chained formatting
|
|
281
|
-
richText('Important').bold().italic().color('red').build();
|
|
282
|
-
|
|
283
|
-
// Link
|
|
284
|
-
richText('Notion').link('https://notion.so').build();
|
|
285
|
-
|
|
286
|
-
// Combine multiple segments
|
|
287
|
-
richText.join(
|
|
288
|
-
richText('Normal '),
|
|
289
|
-
richText('bold').bold(),
|
|
290
|
-
richText(' and '),
|
|
291
|
-
richText('italic').italic(),
|
|
292
|
-
);
|
|
293
|
-
|
|
294
|
-
// Mentions
|
|
295
|
-
richText.mentionPage('page-id').build();
|
|
296
|
-
richText.mentionDatabase('db-id').build();
|
|
297
|
-
richText.mentionUser({ object: 'user', id: 'user-id' }).build();
|
|
298
|
-
richText.mentionDate('2025-03-01').build();
|
|
299
|
-
richText.mentionLinkPreview('https://example.com').build();
|
|
300
|
-
|
|
301
|
-
// Inline equation
|
|
302
|
-
richText.equation('E=mc^2').build();
|
|
303
76
|
```
|
|
304
77
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
Factory functions for all 31 block types. Returns plain objects ready for `blocks.children.append()` or `pages.create()`:
|
|
78
|
+
## Documentation
|
|
308
79
|
|
|
309
|
-
|
|
310
|
-
import { block, richText } from '@visus-io/notion-sdk-ts';
|
|
80
|
+
Comprehensive documentation is available in the [**GitHub Wiki**](https://github.com/visus-io/notion-sdk-ts/wiki):
|
|
311
81
|
|
|
312
|
-
|
|
313
|
-
// Text blocks (accept string, RichTextBuilder, or NotionRichText)
|
|
314
|
-
block.heading1('Title'),
|
|
315
|
-
block.heading2('Subtitle', { isToggleable: true }),
|
|
316
|
-
block.paragraph('Plain text'),
|
|
317
|
-
block.paragraph(richText('Styled text').bold().color('blue')),
|
|
318
|
-
block.bulletedListItem('First item'),
|
|
319
|
-
block.numberedListItem('Step one'),
|
|
320
|
-
block.toDo('Task', { checked: true }),
|
|
321
|
-
block.toggle('Click to expand', { children: [block.paragraph('Hidden content')] }),
|
|
322
|
-
block.quote('A wise saying'),
|
|
323
|
-
block.callout('Heads up!', { icon: { type: 'emoji', emoji: '⚠️' } }),
|
|
82
|
+
### Getting Started
|
|
324
83
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
84
|
+
- [**Getting Started**](https://github.com/visus-io/notion-sdk-ts/wiki/Getting-Started) - Installation, quick start, and basic configuration
|
|
85
|
+
- [**Migration Guide**](https://github.com/visus-io/notion-sdk-ts/wiki/Migration-Guide) - Migrating to API version 2025-09-03
|
|
86
|
+
- [**Common Use Cases**](https://github.com/visus-io/notion-sdk-ts/wiki/Common-Use-Cases) - Practical examples and workflows
|
|
328
87
|
|
|
329
|
-
|
|
330
|
-
block.image('https://example.com/photo.png', { caption: 'Photo' }),
|
|
331
|
-
block.video('https://example.com/video.mp4'),
|
|
332
|
-
block.audio('https://example.com/song.mp3'),
|
|
333
|
-
block.file('https://example.com/doc.pdf'),
|
|
334
|
-
block.pdf('https://example.com/doc.pdf'),
|
|
88
|
+
### Core Concepts
|
|
335
89
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
block.linkPreview('https://github.com/example/repo'),
|
|
90
|
+
- [**Helpers**](https://github.com/visus-io/notion-sdk-ts/wiki/Helpers) - Rich Text, Block Builder, Properties, Filters, Sorting
|
|
91
|
+
- [**Models**](https://github.com/visus-io/notion-sdk-ts/wiki/Models) - Page, Block, Database, DataSource, User, Comment, FileUpload
|
|
92
|
+
- [**API Reference**](https://github.com/visus-io/notion-sdk-ts/wiki/API-Reference) - Complete API endpoint documentation
|
|
340
93
|
|
|
341
|
-
|
|
342
|
-
block.divider(),
|
|
343
|
-
block.breadcrumb(),
|
|
344
|
-
block.tableOfContents(),
|
|
345
|
-
block.table(3, {
|
|
346
|
-
hasColumnHeader: true,
|
|
347
|
-
children: [
|
|
348
|
-
block.tableRow(['Name', 'Role', 'Status']),
|
|
349
|
-
block.tableRow(['Alice', 'Engineer', 'Active']),
|
|
350
|
-
],
|
|
351
|
-
}),
|
|
352
|
-
block.columnList([[block.paragraph('Column 1')], [block.paragraph('Column 2')]]),
|
|
94
|
+
### Configuration & Advanced Topics
|
|
353
95
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
]
|
|
358
|
-
```
|
|
96
|
+
- [**Configuration & Features**](https://github.com/visus-io/notion-sdk-ts/wiki/Configuration) - Client options, rate limiting, retries
|
|
97
|
+
- [**Error Handling**](https://github.com/visus-io/notion-sdk-ts/wiki/Error-Handling) - Error types, codes, and handling patterns
|
|
98
|
+
- [**Pagination**](https://github.com/visus-io/notion-sdk-ts/wiki/Pagination) - Automatic pagination helpers
|
|
99
|
+
- [**Request Size Limits**](https://github.com/visus-io/notion-sdk-ts/wiki/Request-Size-Limits) - Notion API size limits
|
|
359
100
|
|
|
360
|
-
###
|
|
101
|
+
### Development
|
|
361
102
|
|
|
362
|
-
|
|
103
|
+
- [**TypeScript Support**](https://github.com/visus-io/notion-sdk-ts/wiki/TypeScript-Support) - Types, schemas, and type safety
|
|
104
|
+
- [**Development & Contributing**](https://github.com/visus-io/notion-sdk-ts/wiki/Development) - Project structure and architecture
|
|
363
105
|
|
|
364
|
-
|
|
365
|
-
import { prop, richText } from '@visus-io/notion-sdk-ts';
|
|
106
|
+
## Migration Notice
|
|
366
107
|
|
|
367
|
-
|
|
368
|
-
Name: prop.title('My Task'),
|
|
369
|
-
Description: prop.richText('Some notes'),
|
|
370
|
-
Notes: prop.richText(richText('Important').bold()),
|
|
371
|
-
Score: prop.number(95),
|
|
372
|
-
Done: prop.checkbox(true),
|
|
373
|
-
Priority: prop.select('High'),
|
|
374
|
-
Tags: prop.multiSelect(['urgent', 'frontend']),
|
|
375
|
-
Status: prop.status('In Progress'),
|
|
376
|
-
'Due Date': prop.date('2025-03-01'),
|
|
377
|
-
'Date Range': prop.date('2025-03-01', { end: '2025-03-15' }),
|
|
378
|
-
Website: prop.url('https://example.com'),
|
|
379
|
-
Contact: prop.email('user@example.com'),
|
|
380
|
-
Phone: prop.phoneNumber('+1-555-0100'),
|
|
381
|
-
Related: prop.relation(['page-id-1', 'page-id-2']),
|
|
382
|
-
Assignee: prop.people(['user-id']),
|
|
383
|
-
Attachments: prop.files([{ name: 'doc.pdf', url: 'https://example.com/doc.pdf' }]),
|
|
384
|
-
};
|
|
108
|
+
**This SDK now defaults to Notion API version `2025-09-03`** (previously `2022-06-28`). This version introduces breaking changes for multi-source database support.
|
|
385
109
|
|
|
386
|
-
|
|
387
|
-
prop.select(null);
|
|
388
|
-
prop.date(null);
|
|
389
|
-
prop.url(null);
|
|
390
|
-
```
|
|
110
|
+
### Key Changes
|
|
391
111
|
|
|
392
|
-
|
|
112
|
+
- **Database creation:** Properties moved to `initial_data_source.properties`
|
|
113
|
+
- **Database updates:** Use Data Sources API for property changes
|
|
114
|
+
- **Page creation:** Requires both data source ID and database ID
|
|
115
|
+
- **Search API:** Returns `DataSource` objects instead of `Database`
|
|
393
116
|
|
|
394
|
-
|
|
117
|
+
### Quick Migration Example
|
|
395
118
|
|
|
396
119
|
```typescript
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
filter.select('Priority').doesNotEqual('Low');
|
|
402
|
-
filter.number('Score').greaterThan(80);
|
|
403
|
-
filter.checkbox('Done').equals(false);
|
|
404
|
-
filter.date('Due Date').before('2025-06-01');
|
|
405
|
-
filter.date('Due Date').pastWeek();
|
|
406
|
-
filter.text('Description').contains('important');
|
|
407
|
-
filter.title('Name').startsWith('Project');
|
|
408
|
-
filter.url('Website').isNotEmpty();
|
|
409
|
-
filter.email('Contact').isNotEmpty();
|
|
410
|
-
filter.multiSelect('Tags').contains('urgent');
|
|
411
|
-
filter.people('Assignee').contains('user-id');
|
|
412
|
-
filter.relation('Project').contains('page-id');
|
|
413
|
-
filter.files('Attachments').isNotEmpty();
|
|
414
|
-
|
|
415
|
-
// Timestamp filters (no property name needed)
|
|
416
|
-
filter.createdTime().after('2025-01-01');
|
|
417
|
-
filter.lastEditedTime().pastMonth();
|
|
418
|
-
|
|
419
|
-
// Compound filters
|
|
420
|
-
filter.and(
|
|
421
|
-
filter.status('Status').equals('Active'),
|
|
422
|
-
filter.number('Score').greaterThan(80),
|
|
423
|
-
filter.or(filter.date('Due Date').before('2025-06-01'), filter.date('Due Date').isEmpty()),
|
|
424
|
-
);
|
|
425
|
-
```
|
|
426
|
-
|
|
427
|
-
### Sorting
|
|
428
|
-
|
|
429
|
-
```typescript
|
|
430
|
-
import { sort } from '@visus-io/notion-sdk-ts';
|
|
431
|
-
|
|
432
|
-
const sorts = [
|
|
433
|
-
sort.property('Priority').ascending(),
|
|
434
|
-
sort.property('Due Date').descending(),
|
|
435
|
-
sort.createdTime().descending(),
|
|
436
|
-
sort.lastEditedTime().ascending(),
|
|
437
|
-
];
|
|
438
|
-
```
|
|
439
|
-
|
|
440
|
-
### Parent, Icon, Cover & File
|
|
441
|
-
|
|
442
|
-
```typescript
|
|
443
|
-
import { parent, icon, cover, notionFile } from '@visus-io/notion-sdk-ts';
|
|
444
|
-
|
|
445
|
-
// Parent objects
|
|
446
|
-
parent.page('page-id');
|
|
447
|
-
parent.dataSource('data-source-id', 'database-id'); // Note: both IDs required in 2025-09-03
|
|
448
|
-
parent.workspace();
|
|
449
|
-
parent.block('block-id'); // For comments on blocks
|
|
450
|
-
|
|
451
|
-
// Icons
|
|
452
|
-
icon.emoji('🚀');
|
|
453
|
-
icon.external('https://example.com/icon.png');
|
|
454
|
-
icon.fileUpload('upload-id');
|
|
455
|
-
|
|
456
|
-
// Covers
|
|
457
|
-
cover.external('https://example.com/banner.jpg');
|
|
458
|
-
cover.fileUpload('upload-id');
|
|
459
|
-
|
|
460
|
-
// File references
|
|
461
|
-
notionFile.external('https://example.com/doc.pdf');
|
|
462
|
-
notionFile.upload('upload-id');
|
|
463
|
-
```
|
|
464
|
-
|
|
465
|
-
## Models
|
|
466
|
-
|
|
467
|
-
All API methods return model instances with typed properties and helper methods. Every model validates raw API data through its Zod schema on construction.
|
|
468
|
-
|
|
469
|
-
### Page
|
|
470
|
-
|
|
471
|
-
```typescript
|
|
472
|
-
const page = await notion.pages.retrieve('page-id');
|
|
473
|
-
|
|
474
|
-
page.id; // UUID
|
|
475
|
-
page.url; // Notion URL
|
|
476
|
-
page.publicUrl; // Public URL (if shared)
|
|
477
|
-
page.createdTime; // Date
|
|
478
|
-
page.lastEditedTime; // Date
|
|
479
|
-
page.archived; // boolean
|
|
480
|
-
page.inTrash; // boolean
|
|
481
|
-
page.properties; // Record of property values
|
|
482
|
-
|
|
483
|
-
page.getTitle(); // Plain text title
|
|
484
|
-
page.getProperty('Name'); // Specific property value
|
|
485
|
-
page.isInDatabase(); // true if parent is a database
|
|
486
|
-
page.isSubpage(); // true if parent is a page
|
|
487
|
-
page.toJSON(); // Raw validated data
|
|
488
|
-
```
|
|
489
|
-
|
|
490
|
-
### Block
|
|
491
|
-
|
|
492
|
-
```typescript
|
|
493
|
-
const block = await notion.blocks.retrieve('block-id');
|
|
494
|
-
|
|
495
|
-
block.id; // UUID
|
|
496
|
-
block.type; // 'paragraph' | 'heading_1' | ...
|
|
497
|
-
block.hasChildren; // boolean
|
|
498
|
-
|
|
499
|
-
block.isTextBlock(); // paragraph, heading, list item, etc.
|
|
500
|
-
block.isHeading(); // heading_1, heading_2, heading_3
|
|
501
|
-
block.canHaveChildren(); // toggle, column, synced_block, etc.
|
|
502
|
-
block.getPlainText(); // Extracted text content
|
|
503
|
-
block.toJSON();
|
|
504
|
-
```
|
|
505
|
-
|
|
506
|
-
### Database
|
|
507
|
-
|
|
508
|
-
```typescript
|
|
509
|
-
const db = await notion.databases.retrieve('database-id');
|
|
510
|
-
|
|
511
|
-
db.id; // UUID
|
|
512
|
-
db.title; // NotionRichText
|
|
513
|
-
db.description; // NotionRichText
|
|
514
|
-
db.dataSources; // DataSourceRef[]
|
|
515
|
-
db.url; // Notion URL
|
|
516
|
-
db.isInline; // boolean
|
|
517
|
-
|
|
518
|
-
db.getTitle(); // Plain text title
|
|
519
|
-
db.getDescription(); // Plain text description
|
|
520
|
-
db.isFullPage(); // true if not inline
|
|
521
|
-
db.hasPageParent();
|
|
522
|
-
db.hasWorkspaceParent();
|
|
523
|
-
db.toJSON();
|
|
524
|
-
```
|
|
525
|
-
|
|
526
|
-
### DataSource
|
|
527
|
-
|
|
528
|
-
```typescript
|
|
529
|
-
const ds = await notion.dataSources.retrieve('data-source-id');
|
|
530
|
-
|
|
531
|
-
ds.id; // UUID
|
|
532
|
-
ds.properties; // Property configurations
|
|
533
|
-
|
|
534
|
-
ds.getTitle();
|
|
535
|
-
ds.getDescription();
|
|
536
|
-
ds.getParentDatabaseId();
|
|
537
|
-
ds.getProperty('Name'); // Specific property config
|
|
538
|
-
ds.getPropertyNames(); // All property names
|
|
539
|
-
ds.hasProperty('Status');
|
|
540
|
-
ds.toJSON();
|
|
541
|
-
```
|
|
542
|
-
|
|
543
|
-
### User
|
|
544
|
-
|
|
545
|
-
```typescript
|
|
546
|
-
const user = await notion.users.retrieve('user-id');
|
|
547
|
-
|
|
548
|
-
user.id; // UUID
|
|
549
|
-
user.type; // 'person' | 'bot' | undefined
|
|
550
|
-
user.name; // string | undefined
|
|
551
|
-
user.avatarUrl; // string | undefined
|
|
552
|
-
|
|
553
|
-
user.isPerson(); // Type guard
|
|
554
|
-
user.isBot(); // Type guard
|
|
555
|
-
user.getEmail(); // Person users only
|
|
556
|
-
user.getBotInfo(); // Bot users only
|
|
557
|
-
user.toJSON();
|
|
558
|
-
```
|
|
559
|
-
|
|
560
|
-
### Comment
|
|
561
|
-
|
|
562
|
-
```typescript
|
|
563
|
-
const comments = await notion.comments.list('page-id');
|
|
564
|
-
const comment = comments.results[0];
|
|
565
|
-
|
|
566
|
-
comment.id;
|
|
567
|
-
comment.discussionId;
|
|
568
|
-
comment.richText; // NotionRichText
|
|
569
|
-
comment.createdTime; // Date
|
|
570
|
-
comment.attachments;
|
|
571
|
-
comment.displayName;
|
|
572
|
-
|
|
573
|
-
comment.getPlainText();
|
|
574
|
-
comment.hasAttachments();
|
|
575
|
-
comment.hasCustomDisplayName();
|
|
576
|
-
comment.getDisplayName(); // Resolved display name string
|
|
577
|
-
comment.hasPageParent();
|
|
578
|
-
comment.hasBlockParent();
|
|
579
|
-
comment.toJSON();
|
|
580
|
-
```
|
|
581
|
-
|
|
582
|
-
### FileUpload
|
|
583
|
-
|
|
584
|
-
```typescript
|
|
585
|
-
const upload = await notion.fileUploads.retrieve('upload-id');
|
|
586
|
-
|
|
587
|
-
upload.id;
|
|
588
|
-
upload.status; // 'pending' | 'uploaded' | 'expired' | 'failed'
|
|
589
|
-
upload.filename;
|
|
590
|
-
upload.contentType;
|
|
591
|
-
upload.contentLength;
|
|
592
|
-
upload.uploadUrl;
|
|
593
|
-
upload.completeUrl;
|
|
594
|
-
|
|
595
|
-
upload.isPending();
|
|
596
|
-
upload.isUploaded();
|
|
597
|
-
upload.isExpired();
|
|
598
|
-
upload.isFailed();
|
|
599
|
-
upload.toJSON();
|
|
600
|
-
```
|
|
601
|
-
|
|
602
|
-
### RichText Utility
|
|
603
|
-
|
|
604
|
-
Parse and convert Notion rich text to other formats:
|
|
605
|
-
|
|
606
|
-
```typescript
|
|
607
|
-
import { RichText } from '@visus-io/notion-sdk-ts';
|
|
608
|
-
|
|
609
|
-
const rt = new RichText(page.properties.Name.title);
|
|
610
|
-
|
|
611
|
-
rt.toPlainText(); // "Project Documentation"
|
|
612
|
-
rt.toMarkdown(); // "**Project** Documentation"
|
|
613
|
-
rt.toHTML(); // "<strong>Project</strong> Documentation"
|
|
614
|
-
rt.hasLinks(); // boolean
|
|
615
|
-
rt.getLinks(); // string[]
|
|
616
|
-
rt.toJSON(); // Raw NotionRichText
|
|
617
|
-
```
|
|
618
|
-
|
|
619
|
-
**Supported conversions:**
|
|
620
|
-
|
|
621
|
-
| Format | Bold | Italic | Strikethrough | Underline | Code | Link |
|
|
622
|
-
| -------- | ---------- | -------- | ------------- | --------- | ------------ | ------------- |
|
|
623
|
-
| Markdown | `**text**` | `*text*` | `~~text~~` | -- | `` `text` `` | `[text](url)` |
|
|
624
|
-
| HTML | `<strong>` | `<em>` | `<s>` | `<u>` | `<code>` | `<a href="">` |
|
|
625
|
-
|
|
626
|
-
## Error Handling
|
|
627
|
-
|
|
628
|
-
Four error classes cover all failure modes:
|
|
629
|
-
|
|
630
|
-
```typescript
|
|
631
|
-
import {
|
|
632
|
-
NotionAPIError,
|
|
633
|
-
NotionNetworkError,
|
|
634
|
-
NotionRequestTimeoutError,
|
|
635
|
-
NotionValidationError,
|
|
636
|
-
} from '@visus-io/notion-sdk-ts';
|
|
637
|
-
|
|
638
|
-
try {
|
|
639
|
-
await notion.pages.retrieve('page-id');
|
|
640
|
-
} catch (error) {
|
|
641
|
-
if (error instanceof NotionValidationError) {
|
|
642
|
-
// Client-side size limit exceeded (thrown before the request is sent)
|
|
643
|
-
console.error(error.message);
|
|
644
|
-
} else if (error instanceof NotionAPIError) {
|
|
645
|
-
// Structured API error with status code and error code
|
|
646
|
-
console.error(error.status, error.code, error.message);
|
|
647
|
-
|
|
648
|
-
error.isNotFound(); // 404
|
|
649
|
-
error.isUnauthorized(); // 401
|
|
650
|
-
error.isValidationError(); // 400
|
|
651
|
-
error.isRateLimited(); // 429 (auto-retried by default)
|
|
652
|
-
error.isServerError(); // 5xx
|
|
653
|
-
error.isRetryable(); // rate limited OR server error
|
|
654
|
-
} else if (error instanceof NotionNetworkError) {
|
|
655
|
-
// DNS failure, connection refused, etc.
|
|
656
|
-
console.error(error.message, error.cause);
|
|
657
|
-
} else if (error instanceof NotionRequestTimeoutError) {
|
|
658
|
-
// Request exceeded configured timeout
|
|
659
|
-
console.error(error.message);
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
```
|
|
663
|
-
|
|
664
|
-
**Error codes:** `invalid_json`, `invalid_request_url`, `invalid_request`, `validation_error`, `missing_version`, `unauthorized`, `restricted_resource`, `object_not_found`, `conflict_error`, `rate_limited`, `internal_server_error`, `service_unavailable`, `database_connection_unavailable`, `gateway_timeout`
|
|
665
|
-
|
|
666
|
-
## Request Size Limits
|
|
667
|
-
|
|
668
|
-
The SDK enforces [Notion API size limits](https://developers.notion.com/reference/request-limits#size-limits) client-side, throwing `NotionValidationError` before the request is sent. This applies at both layers: helpers validate when constructing objects, and API methods validate before sending.
|
|
669
|
-
|
|
670
|
-
| Limit | Value | Where enforced |
|
|
671
|
-
| ---------------------------- | ------------ | ----------------------------------------------------------------------------------------------- |
|
|
672
|
-
| `text.content` length | 2,000 chars | `richText()`, `block.*()`, `prop.title()`, `prop.richText()` |
|
|
673
|
-
| `text.link.url` length | 2,000 chars | `richText().link()` |
|
|
674
|
-
| `equation.expression` length | 1,000 chars | `richText.equation()`, `block.equation()` |
|
|
675
|
-
| Any URL property | 2,000 chars | `prop.url()`, `block.embed()`, `block.bookmark()`, `block.linkPreview()`, `block.image()`, etc. |
|
|
676
|
-
| Email property | 200 chars | `prop.email()` |
|
|
677
|
-
| Phone number property | 200 chars | `prop.phoneNumber()` |
|
|
678
|
-
| Block/rich-text arrays | 100 elements | `blocks.children.append()`, `pages.create()`, `comments.create()`, `databases.create/update()` |
|
|
679
|
-
| Multi-select options | 100 options | `prop.multiSelect()` |
|
|
680
|
-
| Relation pages | 100 pages | `prop.relation()` |
|
|
681
|
-
| People users | 100 users | `prop.people()` |
|
|
682
|
-
| Comment attachments | 3 files | `comments.create()` |
|
|
683
|
-
| `filter_properties` | 100 items | `pages.retrieve()`, `databases.retrieve/query()`, `dataSources.retrieve/query()` |
|
|
684
|
-
|
|
685
|
-
All limit constants are exported as `LIMITS` for reference:
|
|
686
|
-
|
|
687
|
-
```typescript
|
|
688
|
-
import { LIMITS } from '@visus-io/notion-sdk-ts';
|
|
689
|
-
|
|
690
|
-
console.log(LIMITS.RICH_TEXT_CONTENT); // 2000
|
|
691
|
-
console.log(LIMITS.URL); // 2000
|
|
692
|
-
console.log(LIMITS.EMAIL); // 200
|
|
693
|
-
console.log(LIMITS.ARRAY_ELEMENTS); // 100
|
|
694
|
-
```
|
|
695
|
-
|
|
696
|
-
## Pagination
|
|
697
|
-
|
|
698
|
-
All list endpoints return `PaginatedList<T>` with cursor-based pagination:
|
|
699
|
-
|
|
700
|
-
```typescript
|
|
701
|
-
interface PaginatedList<T> {
|
|
702
|
-
results: T[];
|
|
703
|
-
next_cursor: string | null;
|
|
704
|
-
has_more: boolean;
|
|
705
|
-
}
|
|
706
|
-
```
|
|
707
|
-
|
|
708
|
-
The SDK provides helper utilities to automatically collect all results:
|
|
709
|
-
|
|
710
|
-
### `paginate()` - Collect all results
|
|
711
|
-
|
|
712
|
-
Automatically fetches all pages and returns a single array:
|
|
713
|
-
|
|
714
|
-
```typescript
|
|
715
|
-
import { paginate } from '@visus-io/notion-sdk-ts';
|
|
716
|
-
|
|
717
|
-
// All blocks from a page
|
|
718
|
-
const blocks = await paginate((cursor) =>
|
|
719
|
-
notion.blocks.children.list('page-id', { start_cursor: cursor, page_size: 100 }),
|
|
720
|
-
);
|
|
721
|
-
|
|
722
|
-
// All pages from a database query
|
|
723
|
-
const pages = await paginate((cursor) =>
|
|
724
|
-
notion.databases.query('database-id', {
|
|
725
|
-
start_cursor: cursor,
|
|
726
|
-
page_size: 100,
|
|
727
|
-
filter: filter.status('Status').equals('Active'),
|
|
728
|
-
}),
|
|
729
|
-
);
|
|
730
|
-
|
|
731
|
-
// All comments on a page
|
|
732
|
-
const comments = await paginate((cursor) =>
|
|
733
|
-
notion.comments.list('page-id', { start_cursor: cursor }),
|
|
734
|
-
);
|
|
735
|
-
|
|
736
|
-
// All users in workspace
|
|
737
|
-
const users = await paginate((cursor) => notion.users.list({ start_cursor: cursor }));
|
|
738
|
-
|
|
739
|
-
// All search results
|
|
740
|
-
const searchResults = await paginate((cursor) =>
|
|
741
|
-
notion.search.query({
|
|
742
|
-
query: 'project',
|
|
743
|
-
filter: { property: 'object', value: 'page' },
|
|
744
|
-
start_cursor: cursor,
|
|
745
|
-
}),
|
|
746
|
-
);
|
|
747
|
-
```
|
|
748
|
-
|
|
749
|
-
### `paginateIterator()` - Memory-efficient iteration
|
|
750
|
-
|
|
751
|
-
Process results one at a time without loading everything into memory:
|
|
752
|
-
|
|
753
|
-
```typescript
|
|
754
|
-
import { paginateIterator } from '@visus-io/notion-sdk-ts';
|
|
755
|
-
|
|
756
|
-
// Process blocks one at a time
|
|
757
|
-
for await (const block of paginateIterator((cursor) =>
|
|
758
|
-
notion.blocks.children.list('page-id', { start_cursor: cursor }),
|
|
759
|
-
)) {
|
|
760
|
-
console.log(block.type, block.id);
|
|
761
|
-
if (block.isTextBlock()) {
|
|
762
|
-
console.log(block.getPlainText());
|
|
763
|
-
}
|
|
764
|
-
}
|
|
765
|
-
|
|
766
|
-
// Process database pages one at a time
|
|
767
|
-
for await (const page of paginateIterator((cursor) =>
|
|
768
|
-
notion.databases.query('database-id', {
|
|
769
|
-
start_cursor: cursor,
|
|
770
|
-
filter: filter.status('Status').equals('Active'),
|
|
771
|
-
}),
|
|
772
|
-
)) {
|
|
773
|
-
console.log(page.getTitle());
|
|
774
|
-
// Process without loading all pages into memory
|
|
775
|
-
}
|
|
776
|
-
```
|
|
777
|
-
|
|
778
|
-
### `paginateWithMetadata()` - Get results with pagination stats
|
|
779
|
-
|
|
780
|
-
Useful for tracking API usage and performance:
|
|
781
|
-
|
|
782
|
-
```typescript
|
|
783
|
-
import { paginateWithMetadata } from '@visus-io/notion-sdk-ts';
|
|
784
|
-
|
|
785
|
-
const { items, pageCount, totalCount } = await paginateWithMetadata((cursor) =>
|
|
786
|
-
notion.blocks.children.list('page-id', { start_cursor: cursor }),
|
|
787
|
-
);
|
|
788
|
-
|
|
789
|
-
console.log(`Fetched ${totalCount} blocks across ${pageCount} API calls`);
|
|
790
|
-
```
|
|
791
|
-
|
|
792
|
-
**Paginated endpoints:** `blocks.children.list()`, `comments.list()`, `databases.query()`, `dataSources.query()`, `search.query()`, `users.list()`
|
|
793
|
-
|
|
794
|
-
## Configuration
|
|
795
|
-
|
|
796
|
-
```typescript
|
|
797
|
-
const notion = new Notion({
|
|
798
|
-
auth: process.env.NOTION_TOKEN, // Required
|
|
799
|
-
|
|
800
|
-
// All optional:
|
|
801
|
-
baseUrl: 'https://api.notion.com', // Default
|
|
802
|
-
notionVersion: '2025-09-03', // Default (use '2022-06-28' for old version)
|
|
803
|
-
timeoutMs: 60_000, // Default: 60s
|
|
804
|
-
retryOnRateLimit: true, // Default: true
|
|
805
|
-
maxRetries: 3, // Default: 3
|
|
806
|
-
fetch: customFetch, // Custom fetch implementation
|
|
120
|
+
// OLD (2022-06-28)
|
|
121
|
+
await notion.pages.create({
|
|
122
|
+
parent: parent.database('database-id'),
|
|
123
|
+
properties: { Name: prop.title('Task') },
|
|
807
124
|
});
|
|
808
|
-
```
|
|
809
|
-
|
|
810
|
-
**Rate limiting:** The SDK automatically retries 429 responses using the server's `Retry-After` header when present, falling back to exponential backoff (1s, 2s, 4s, 8s... capped at 60s) otherwise. Disable with `retryOnRateLimit: false` or adjust with `maxRetries`.
|
|
811
|
-
|
|
812
|
-
## API Reference
|
|
813
|
-
|
|
814
|
-
### Pages API
|
|
815
|
-
|
|
816
|
-
| Method | Description |
|
|
817
|
-
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------ |
|
|
818
|
-
| `pages.retrieve(id, options?)` | Get a page. Options: `filter_properties` (max 100) |
|
|
819
|
-
| `pages.create(options)` | Create a page. Requires `parent` + `properties`. Optional: `icon`, `cover`, `children` (max 100), `template`, `position` |
|
|
820
|
-
| `pages.update(id, options)` | Update properties, icon, cover, lock status, or archive state. Supports `erase_content` |
|
|
821
|
-
| `pages.archive(id)` | Archive a page |
|
|
822
|
-
| `pages.restore(id)` | Restore an archived page |
|
|
823
|
-
|
|
824
|
-
### Blocks API
|
|
825
125
|
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
| `blocks.update(id, options)` | Update block content |
|
|
830
|
-
| `blocks.delete(id)` | Delete (archive) a block |
|
|
831
|
-
| `blocks.children.list(id, params?)` | List child blocks (paginated) |
|
|
832
|
-
| `blocks.children.append(id, options)` | Append child blocks (max 100). Optional: `after` block ID |
|
|
833
|
-
|
|
834
|
-
### Databases API
|
|
835
|
-
|
|
836
|
-
| Method | Description |
|
|
837
|
-
| ---------------------------------- | ----------------------------------------------------------------------- |
|
|
838
|
-
| `databases.retrieve(id, options?)` | Get a database |
|
|
839
|
-
| `databases.query(id, options?)` | Query with `filter`, `sorts`, pagination. Returns `PaginatedList<Page>` |
|
|
840
|
-
| `databases.create(options)` | Create a database. Requires `parent` + `properties` |
|
|
841
|
-
| `databases.update(id, options)` | Update title, description, properties, icon, cover |
|
|
842
|
-
| `databases.archive(id)` | Archive a database |
|
|
843
|
-
| `databases.restore(id)` | Restore a database |
|
|
844
|
-
|
|
845
|
-
### Data Sources API
|
|
846
|
-
|
|
847
|
-
Data sources represent individual tables under databases (API version 2025-09-03).
|
|
848
|
-
|
|
849
|
-
| Method | Description |
|
|
850
|
-
| ----------------------------------------- | -------------------------------------------------------------------- |
|
|
851
|
-
| `dataSources.retrieve(id, options?)` | Get a data source |
|
|
852
|
-
| `dataSources.query(id, options?)` | Query with filters/sorts. `result_type`: `'page'` or `'data_source'` |
|
|
853
|
-
| `dataSources.create(options)` | Create a data source under a database |
|
|
854
|
-
| `dataSources.update(id, options)` | Update a data source |
|
|
855
|
-
| `dataSources.archive(id)` / `restore(id)` | Archive/restore |
|
|
856
|
-
| `dataSources.trash(id)` / `untrash(id)` | Move to/from trash |
|
|
857
|
-
|
|
858
|
-
### Comments API
|
|
859
|
-
|
|
860
|
-
| Method | Description |
|
|
861
|
-
| ---------------------------------- | -------------------------------------------------------------------------------------------------------- |
|
|
862
|
-
| `comments.list(parentId, params?)` | List comments on a page/block (paginated) |
|
|
863
|
-
| `comments.create(options)` | Create a comment. Options: `parent`, `rich_text`, `discussion_id`, `attachments` (max 3), `display_name` |
|
|
864
|
-
|
|
865
|
-
### Search API
|
|
866
|
-
|
|
867
|
-
| Method | Description |
|
|
868
|
-
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------- |
|
|
869
|
-
| `search.query(options?)` | Search workspace. Filter by `'page'` or `'database'`. Sort by `last_edited_time`. Returns `PaginatedList<Page \| Database>` |
|
|
870
|
-
|
|
871
|
-
### Users API
|
|
872
|
-
|
|
873
|
-
| Method | Description |
|
|
874
|
-
| --------------------- | -------------------------------------- |
|
|
875
|
-
| `users.list(params?)` | List all workspace users (paginated) |
|
|
876
|
-
| `users.retrieve(id)` | Get a user by ID |
|
|
877
|
-
| `users.me()` | Get the bot user for the current token |
|
|
878
|
-
|
|
879
|
-
### File Uploads API
|
|
880
|
-
|
|
881
|
-
| Method | Description |
|
|
882
|
-
| ----------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
|
|
883
|
-
| `fileUploads.uploadFile(filename, data, contentType)` | Upload a file in one call (handles initiate + upload + complete). `data`: `Buffer \| ArrayBuffer \| Blob` |
|
|
884
|
-
| `fileUploads.initiate(options)` | Step 1: Initiate upload |
|
|
885
|
-
| `fileUploads.upload(url, data, contentType)` | Step 2: Upload file data |
|
|
886
|
-
| `fileUploads.complete(url)` | Step 3: Mark upload complete |
|
|
887
|
-
| `fileUploads.retrieve(id)` | Check upload status |
|
|
888
|
-
|
|
889
|
-
**Full example:**
|
|
890
|
-
|
|
891
|
-
```typescript
|
|
892
|
-
import { readFileSync } from 'fs';
|
|
893
|
-
|
|
894
|
-
// One-step upload
|
|
895
|
-
const upload = await notion.fileUploads.uploadFile(
|
|
896
|
-
'document.pdf',
|
|
897
|
-
readFileSync('./document.pdf'),
|
|
898
|
-
'application/pdf',
|
|
899
|
-
);
|
|
900
|
-
|
|
901
|
-
console.log(upload.status); // 'uploaded'
|
|
126
|
+
// NEW (2025-09-03)
|
|
127
|
+
const db = await notion.databases.retrieve('database-id');
|
|
128
|
+
const dataSourceId = db.dataSources[0].id;
|
|
902
129
|
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
content_type: 'application/pdf',
|
|
130
|
+
await notion.pages.create({
|
|
131
|
+
parent: parent.dataSource(dataSourceId, db.id),
|
|
132
|
+
properties: { Name: prop.title('Task') },
|
|
907
133
|
});
|
|
908
|
-
await notion.fileUploads.upload(init.uploadUrl, fileData, 'application/pdf');
|
|
909
|
-
const completed = await notion.fileUploads.complete(init.completeUrl);
|
|
910
134
|
```
|
|
911
135
|
|
|
912
|
-
|
|
136
|
+
See the [**Migration Guide**](https://github.com/visus-io/notion-sdk-ts/wiki/Migration-Guide) for complete details.
|
|
913
137
|
|
|
914
|
-
|
|
138
|
+
## Development
|
|
915
139
|
|
|
916
|
-
|
|
917
|
-
import type {
|
|
918
|
-
NotionPage,
|
|
919
|
-
NotionBlock,
|
|
920
|
-
NotionDatabase,
|
|
921
|
-
NotionUser,
|
|
922
|
-
NotionComment,
|
|
923
|
-
NotionDataSource,
|
|
924
|
-
NotionFileUpload,
|
|
925
|
-
NotionRichText,
|
|
926
|
-
NotionParent,
|
|
927
|
-
NotionFile,
|
|
928
|
-
NotionColor,
|
|
929
|
-
PaginatedList,
|
|
930
|
-
} from '@visus-io/notion-sdk-ts';
|
|
140
|
+
This project uses [Bun](https://bun.sh) as its package manager for faster dependency installation and script execution.
|
|
931
141
|
|
|
932
|
-
|
|
933
|
-
import type {
|
|
934
|
-
Page,
|
|
935
|
-
Block,
|
|
936
|
-
Database,
|
|
937
|
-
User,
|
|
938
|
-
Comment,
|
|
939
|
-
DataSource,
|
|
940
|
-
FileUpload,
|
|
941
|
-
} from '@visus-io/notion-sdk-ts';
|
|
142
|
+
### Prerequisites
|
|
942
143
|
|
|
943
|
-
|
|
944
|
-
import { pageSchema, blockSchema, databaseSchema, userSchema } from '@visus-io/notion-sdk-ts';
|
|
144
|
+
Install Bun if you haven't already:
|
|
945
145
|
|
|
946
|
-
|
|
146
|
+
```bash
|
|
147
|
+
curl -fsSL https://bun.sh/install | bash
|
|
947
148
|
```
|
|
948
149
|
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
**Supported property types (21):** title, rich_text, number, checkbox, date, url, email, phone_number, select, multi_select, status, relation, rollup, people, created_by, last_edited_by, created_time, last_edited_time, files, formula, unique_id, verification
|
|
952
|
-
|
|
953
|
-
## Development
|
|
150
|
+
### Development Commands
|
|
954
151
|
|
|
955
152
|
```bash
|
|
956
|
-
|
|
957
|
-
|
|
153
|
+
bun install # Install dependencies
|
|
154
|
+
bun run build # Compile TypeScript
|
|
958
155
|
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
156
|
+
bun run test # Run tests
|
|
157
|
+
bun run test:watch # Watch mode
|
|
158
|
+
bun run test:coverage # Coverage report
|
|
962
159
|
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
npm run format:check # Check formatting
|
|
160
|
+
bun run lint # ESLint
|
|
161
|
+
bun run lint:fix # Auto-fix
|
|
162
|
+
bun run format # Prettier
|
|
967
163
|
```
|
|
968
164
|
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
```
|
|
972
|
-
src/
|
|
973
|
-
├── index.ts # Entry point — re-exports everything
|
|
974
|
-
├── notion.ts # Notion class (main SDK entry)
|
|
975
|
-
├── client.ts # HTTP client with retry logic
|
|
976
|
-
├── errors.ts # NotionAPIError, NotionNetworkError, NotionRequestTimeoutError
|
|
977
|
-
├── validation.ts # NotionValidationError, LIMITS, size-limit validators
|
|
978
|
-
├── api/
|
|
979
|
-
│ ├── blocks.api.ts # Blocks API
|
|
980
|
-
│ ├── comments.api.ts # Comments API
|
|
981
|
-
│ ├── databases.api.ts # Databases API
|
|
982
|
-
│ ├── dataSources.api.ts # Data Sources API
|
|
983
|
-
│ ├── fileUploads.api.ts # File Uploads API
|
|
984
|
-
│ ├── pages.api.ts # Pages API
|
|
985
|
-
│ ├── search.api.ts # Search API
|
|
986
|
-
│ └── users.api.ts # Users API
|
|
987
|
-
├── helpers/
|
|
988
|
-
│ ├── block.helpers.ts # block.paragraph(), block.heading1(), etc.
|
|
989
|
-
│ ├── richText.helpers.ts # richText(), RichTextBuilder
|
|
990
|
-
│ ├── filter.helpers.ts # filter.status(), filter.and(), etc.
|
|
991
|
-
│ ├── sort.helpers.ts # sort.property(), sort.createdTime()
|
|
992
|
-
│ ├── property.helpers.ts # prop.title(), prop.select(), etc.
|
|
993
|
-
│ ├── parent.helpers.ts # parent.dataSource(), parent.page(), parent.workspace()
|
|
994
|
-
│ └── file.helpers.ts # icon, cover, notionFile
|
|
995
|
-
├── models/
|
|
996
|
-
│ ├── base.model.ts # Abstract BaseModel<T> with Zod validation
|
|
997
|
-
│ ├── page.model.ts # Page
|
|
998
|
-
│ ├── block.model.ts # Block
|
|
999
|
-
│ ├── database.model.ts # Database
|
|
1000
|
-
│ ├── dataSource.model.ts # DataSource
|
|
1001
|
-
│ ├── comment.model.ts # Comment
|
|
1002
|
-
│ ├── user.model.ts # User
|
|
1003
|
-
│ ├── fileUpload.model.ts # FileUpload
|
|
1004
|
-
│ └── richText.model.ts # RichText (toPlainText/toMarkdown/toHTML)
|
|
1005
|
-
└── schemas/
|
|
1006
|
-
├── page.schema.ts # pageSchema + NotionPage
|
|
1007
|
-
├── block.schema.ts # blockSchema + NotionBlock (31 types)
|
|
1008
|
-
├── database.schema.ts # databaseSchema + NotionDatabase
|
|
1009
|
-
├── dataSource.schema.ts # dataSourceSchema + NotionDataSource
|
|
1010
|
-
├── comment.schema.ts # commentSchema + NotionComment
|
|
1011
|
-
├── user.schema.ts # userSchema + NotionUser
|
|
1012
|
-
├── fileUpload.schema.ts # fileUploadSchema + NotionFileUpload
|
|
1013
|
-
├── pageProperties.schema.ts # 21 page property value types
|
|
1014
|
-
├── propertyObjects.schema.ts# 21 database property config types
|
|
1015
|
-
├── richText.schema.ts # richTextSchema + 3 types + 6 mention types
|
|
1016
|
-
├── pagination.schema.ts # PaginatedList<T>, PaginationParameters
|
|
1017
|
-
├── parent.schema.ts # 5 parent types
|
|
1018
|
-
├── file.schema.ts # 3 file variants
|
|
1019
|
-
├── emoji.schema.ts # NotionEmoji
|
|
1020
|
-
├── colors.ts # NOTION_COLORS (19 colors)
|
|
1021
|
-
└── codeLanguages.ts # CODE_BLOCK_LANGUAGES (75 languages)
|
|
1022
|
-
```
|
|
165
|
+
> **Note:** While this project uses Bun for development, the published package works with both Node.js 18+ and Bun 1.3.10+.
|
|
1023
166
|
|
|
1024
|
-
**
|
|
167
|
+
See [**Development & Contributing**](https://github.com/visus-io/notion-sdk-ts/wiki/Development) for more details.
|
|
1025
168
|
|
|
1026
169
|
## Links
|
|
1027
170
|
|
|
1028
|
-
- [
|
|
1029
|
-
- [
|
|
1030
|
-
- [
|
|
171
|
+
- [**Documentation Wiki**](https://github.com/visus-io/notion-sdk-ts/wiki)
|
|
172
|
+
- [**GitHub Repository**](https://github.com/visus-io/notion-sdk-ts)
|
|
173
|
+
- [**npm Package**](https://www.npmjs.com/package/@visus-io/notion-sdk-ts)
|
|
174
|
+
- [**Notion API Documentation**](https://developers.notion.com/reference/intro)
|
|
175
|
+
- [**Notion API Changelog**](https://developers.notion.com/page/changelog)
|