dataSources on worker.customBlock(). Two consequences of that shape everything below:
- The key you declared is the key you query by. A block that declares
issuescallsuseDataSource("issues"). - When connected to a host, initialization validates all declared data source bindings before rendering children.
Query rows
useDataSource takes the key you declared and returns the bound data source’s rows.
The
limit option caps how many rows the query returns. It defaults to 20 and is capped at 999. hasMore means the results are incomplete. The hook does not provide cursor pagination. You can increase limit to request a larger result set, up to the cap.
Filters and sorting
Usekey to address a declared property, or propertyId to address a real Notion property ID. The SDK resolves declared keys through the block’s property mappings.
filter accepts one property condition or a shallow and group with up to 25 conditions. Nested groups and or groups are unsupported.
Empty checks require
true. Option filters accept option names, either one string or an array. Date comparisons accept ISO 8601 dates or timestamps. Relative dates and filters on property types absent from the table are unsupported.
People filters accept one explicit reference to a human user or a group. Use { object: "user", id: "..." } or { object: "group", id: "..." }. Group filters match exact group mentions. They do not expand group membership. Using bot or organization bot pointers as filter references is not supported.
Creator filters require an actual Created by column in the bound database. The column can have any name. In this example, the declared property key creator maps to that column:
propertyId instead of key to address the column by its actual property ID. The created_by key selects the filter type. It does not identify the column. The synthetic read entry propertiesById.created_by is available without a column, but propertyId: "created_by" does not address a Created by column.
Creator filters accept one explicit human user reference. Groups, bots, and organization bots are not supported as filter references. does_not_contain also matches rows with non-human or missing creators. Empty checks test whether creator metadata is missing.
sorts accepts property addresses with an ascending or descending direction. Notion accepts up to 10 unique properties and applies sorts in array order. The first sort has the highest priority.
See the property support table for sortable property types.
Query rows without React
Use the framework-neutralcustomBlock.subscribeToDataSource API. Initialize the SDK before you subscribe.
unsubscribe() when the view no longer needs the query:
Keys versus IDs
Every row exposes its values twice:propertiesByKey, keyed by the keys you declared in the manifest, and propertiesById, keyed by the bound data source’s real property IDs. Prefer propertiesByKey — see binding to Notion data for why.
Update a row
Each row carries its ownupdate method, so you do not need the pages API to edit a row in a bound data source.
update resolves to a result object rather than throwing, following the same { status: "success" } or { status: "error", error } pattern as the rest of the SDK.
Updates support title, rich_text, number, url, email, phone_number, checkbox, select, status, multi_select, date, people, relation, files, and place. Computed properties such as formula, rollup, and creation or edit timestamps are read-only. Declaring other property types does not make them writable.
To create rows, or to work with pages outside a bound data source, use the pages API.
Archive and unarchive a row
item.archive() is shorthand for calling item.update({ is_archived: true }).
item.unarchive() is shorthand for calling item.update({ is_archived: false }).
Both methods return an UpdatePageResult.
Use item.update to change archive status and other fields in one request.
Read the manifest at runtime
useManifest() returns the block’s declared manifest, and customBlock.getManifest() does the same outside React. Both require the block to be initialized.
This is useful for rendering against your own declaration — for example, iterating declared properties to build columns — rather than hardcoding the same list in both the worker and the frontend.
The init payload also carries a dataSources array describing each bound data source, including its resolved propertyIdsByKey and propertySchemasById.
Property support
This table shows property support for custom blocks running in Notion.-
Query result shows values in
propertiesByIdandpropertiesByKeyfromuseDataSourceandcustomBlock.subscribeToDataSource. Missing values can beundefined. -
Update row covers writes through
item.update({ properties: ... }). - Filter and Sort cover query options.
- 🟢 Supported: The SDK supports this operation in Notion.
- 🟡 Limited: The SDK supports this operation with the restrictions shown in the cell.
- 🔴 Unavailable: The SDK does not expose this operation.
- ⚫ Not supported in Notion: Notion itself does not support this operation in the stated case.
Notes
- Text values omit formatting, mention tokens, and annotations. A text fallback can be empty and does not preserve the property’s structured value. It does not provide structured formula or rollup results.
- Record pointers contain a table name and a record ID.
- People properties return record pointers with table values of
notion_user,space_permission_group,bot, ororganization_bot. Group IDs use the composite formgroupId|workspaceId. People filters support users and groups. Bot and organization bot filtering is not supported. - Every row includes four built-in properties in
propertiesById:created_time,last_edited_time,created_by, andlast_edited_by. The data source does not need matching schema properties. These values are read-only. Creator filters require an actual Created by schema property even though metadata reads do not. Timestamps useNotionDateTimein UTC. Creator and editor values use arrays of record pointers. - The SDK accepts timestamp sorts, but the current Notion host requires a property ID in the data source’s actual schema. Sort using a configured created-time or last-edited-time property. The synthetic IDs
created_timeandlast_edited_timealone are not sufficient. - You can sort by up to 10 unique properties.
- Date-time filter values may include seconds or milliseconds, but the Notion host currently evaluates them at minute precision. Date filters do not expose relative dates or end-date targeting.
- Status filters accept option names and empty checks, but not status groups.
- Filters accept one condition or an
andgroup of up to 25 conditions. The SDK does not supportoror nested groups. - Select, multi-select, and status query values contain option names. Their schemas provide option IDs and colors separately. Writes set the selected values. They do not edit option definitions or colors.
Writing values
The value you read has a different shape from the value you write. For example, a query returns a status as a string:status is a declared property key:
- Text: Title and rich text writes preserve plain text, but not formatting or mentions.
- Files: Supply external or existing hosted file URLs. The host stores them as links and does not support upload references.
- Relations: Supply the complete replacement list of related pages. The host rejects
has_more: true, which indicates an incomplete list.