notion-core-workflow-a
'Query, filter, and manage Notion databases and pages.
Allowed Tools
Provided by Plugin
notion-pack
Claude Code skill pack for Notion (30 skills)
Installation
This skill is included in the notion-pack plugin:
/plugin install notion-pack@claude-code-plugins-plus
Click to copy
Instructions
Notion Core Workflow A — Databases & Pages
Overview
Primary workflow for Notion integrations: querying databases with filters/sorts, creating pages with typed properties, updating page properties, and retrieving page content.
Prerequisites
- Completed
notion-install-authsetup - A Notion database shared with your integration
- Understanding of your database's property schema
Authentication
Every call below uses a Client authenticated with an integration token
(process.env.NOTION_TOKEN). Token creation, secret storage, and sharing a
database with the integration are covered end-to-end in the notion-install-auth
skill — complete it first. Never hardcode the token; read it from the environment.
Instructions
The workflow is six steps. Steps 1–2 (schema + filtered query) are the skeleton
you almost always start with, shown here in full. Steps 3–6 (filter syntax by
type, page creation, updates/archive, pagination) live in
the full walkthrough so this file stays scannable.
Step 1: Retrieve Database Schema
Always inspect the schema first — property names and types drive every filter
and write. databases.retrieve returns db.properties keyed by property name.
import { Client } from '@notionhq/client';
const notion = new Client({ auth: process.env.NOTION_TOKEN });
async function getDatabaseSchema(databaseId: string) {
const db = await notion.databases.retrieve({ database_id: databaseId });
for (const [name, prop] of Object.entries(db.properties)) {
console.log(`${name}: ${prop.type}`);
if (prop.type === 'select') {
console.log(' Options:', prop.select.options.map(o => o.name));
}
}
return db.properties;
}
Step 2: Query with Filters
Notion filters use a nested structure keyed by property type, and combine with
and / or. sorts and page_size (max 100) tune the result set.
async function queryWithFilters(databaseId: string) {
const response = await notion.databases.query({
database_id: databaseId,
filter: {
and: [
{ property: 'Status', select: { equals: 'In Progress' } },
{ property: 'Priority', select: { does_not_equal: 'Low' } },
],
},
sorts: [{ property: 'Priority', direction: 'ascending' }],
page_size: 50,
});
return response.results;
}
Steps 3–6: Filter syntax, create, update, paginate
See the full walkthrough for copy-paste code:
- Step 3 — Filter syntax by property type. Every property type (text,
number, select, date, checkbox, people, relation, formula, rollup, timestamp)
has its own filter shape.
- Step 4 — Create a page with all property types. One
pages.createcall
showing the correct payload for each typed property.
- Step 5 — Update & archive.
pages.updateto change properties, or set
archived: true to soft-delete.
- Step 6 — Paginate all results. Loop on
hasmore/nextcursorto pull
a full database beyond the 100-row page limit.
Output
- Database schema retrieved with property types and options
- Filtered and sorted query results
- Pages created with typed properties
- Pages updated and archived
Error Handling
| Error | Cause | Solution |
|---|---|---|
validation_error |
Property name mismatch or wrong type | Use databases.retrieve to check schema |
objectnotfound |
Database not shared with integration | Add integration via Connections |
rate_limited (429) |
>3 requests/second average | Respect Retry-After header |
Empty results |
Filter too restrictive or no data | Test with no filter first |
Examples
Reading queried pages back into plain values requires switching on each
property's type. A reusable getPropertyValue helper plus a full
"flatten a database into an array of objects" example live in
// Excerpt — full helper in references/examples.md
function getPropertyValue(property: any) {
switch (property.type) {
case 'title': return property.title.map((t: any) => t.plain_text).join('');
case 'number': return property.number;
case 'select': return property.select?.name ?? null;
// ...rich_text, multi_select, date, checkbox, url, email, formula
default: return null;
}
}
Resources
- Query a Database
- Filter Database Entries
- Create a Page
- Page Property Values
- Database Object
- Full CRUD walkthrough (Steps 1–6)
- Examples & helpers
- For block-level content operations, see the
notion-core-workflow-bskill.