Robust TypeScript client for the unofficial Notion API.
94
Low-level operations for fetching individual blocks and user information, useful for granular data access.
Fetches block data for specific block IDs. Useful for loading individual blocks or missing blocks that weren't fetched with the initial page load.
/**
* Fetches block data for given block IDs
* @param blockIds - Array of block IDs to fetch
* @param kyOptions - HTTP client options
* @returns Promise resolving to page chunk containing block data
*/
async getBlocks(blockIds: string[], kyOptions?: KyOptions): Promise<PageChunk>;
interface PageChunk {
recordMap: RecordMap;
cursor?: Cursor;
}
interface RecordMap {
block: Record<string, BlockRecord>;
collection?: Record<string, CollectionRecord>;
collection_view?: Record<string, CollectionViewRecord>;
notion_user?: Record<string, UserRecord>;
}Usage Examples:
import { NotionAPI } from "notion-client";
const api = new NotionAPI();
// Fetch specific blocks by ID
const blockIds = [
"067dd719-a912-471e-a9a3-ac10710e7fdf",
"123e4567-e89b-12d3-a456-426614174000",
"789abcde-f012-3456-7890-abcdef123456"
];
const blocksData = await api.getBlocks(blockIds);
// Access individual blocks
Object.keys(blocksData.recordMap.block).forEach(blockId => {
const block = blocksData.recordMap.block[blockId];
console.log(`Block ${blockId}:`, block.value.type);
console.log("Properties:", block.value.properties);
});
// Check if specific block was fetched
const targetBlockId = "067dd719-a912-471e-a9a3-ac10710e7fdf";
const targetBlock = blocksData.recordMap.block[targetBlockId];
if (targetBlock) {
console.log("Block found:", targetBlock.value);
} else {
console.log("Block not found or not accessible");
}Fetches user information for specific user IDs. Useful for getting user details, names, and avatars for display purposes.
/**
* Fetches user information for given user IDs
* @param userIds - Array of user IDs to fetch
* @param kyOptions - HTTP client options
* @returns Promise resolving to user records
*/
async getUsers(userIds: string[], kyOptions?: KyOptions): Promise<RecordValues<User>>;
interface RecordValues<T> {
results: T[];
}
interface User {
id: string;
version: number;
email: string;
given_name: string;
family_name: string;
profile_photo: string;
onboarding_completed: boolean;
mobile_onboarding_completed: boolean;
}Usage Examples:
import { NotionAPI } from "notion-client";
const api = new NotionAPI({ authToken: "your-token" });
// Fetch specific users
const userIds = [
"user-uuid-1",
"user-uuid-2",
"user-uuid-3"
];
const usersData = await api.getUsers(userIds);
// Process user data
usersData.results.forEach(user => {
console.log(`User: ${user.given_name} ${user.family_name}`);
console.log(`Email: ${user.email}`);
console.log(`Profile photo: ${user.profile_photo}`);
console.log(`Onboarding completed: ${user.onboarding_completed}`);
});
// Get user from page data and fetch details
const page = await api.getPage("page-id");
const creatorId = Object.values(page.block)[0]?.value?.created_by_id;
if (creatorId) {
const creatorData = await api.getUsers([creatorId]);
const creator = creatorData.results[0];
console.log("Page creator:", creator?.given_name, creator?.family_name);
}Different block types have different properties and structures:
Usage Examples:
const blocksData = await api.getBlocks(blockIds);
Object.values(blocksData.recordMap.block).forEach(blockRecord => {
const block = blockRecord.value;
switch (block.type) {
case "text":
console.log("Text block:", block.properties?.title);
break;
case "header":
console.log("Header block:", block.properties?.title);
break;
case "image":
console.log("Image block:", block.properties?.source);
console.log("Caption:", block.properties?.caption);
break;
case "page":
console.log("Page block:", block.properties?.title);
console.log("Child blocks:", block.content);
break;
case "collection_view":
console.log("Collection view:", block.collection_id);
console.log("View IDs:", block.view_ids);
break;
default:
console.log(`Unknown block type: ${block.type}`);
}
// Common properties for all blocks
console.log("Created:", new Date(block.created_time));
console.log("Last edited:", new Date(block.last_edited_time));
console.log("Parent:", block.parent_id);
});Blocks form a hierarchy that can be navigated:
Usage Examples:
const page = await api.getPage("root-page-id");
// Find all child blocks of a specific block
const parentBlockId = "parent-block-id";
const parentBlock = page.block[parentBlockId]?.value;
if (parentBlock?.content) {
// Fetch child blocks
const childBlocks = await api.getBlocks(parentBlock.content);
childBlocks.recordMap.block.forEach((childRecord, childId) => {
const child = childRecord.value;
console.log(`Child ${childId}: ${child.type}`);
});
}
// Find blocks by type
const imageBlocks = Object.entries(page.block)
.filter(([_, record]) => record.value.type === "image")
.map(([blockId, record]) => ({ id: blockId, block: record.value }));
console.log("Found image blocks:", imageBlocks.length);Combine user data with block information:
Usage Examples:
const page = await api.getPage("page-id");
// Collect all unique user IDs from blocks
const userIds = new Set<string>();
Object.values(page.block).forEach(record => {
const block = record.value;
if (block.created_by_id) userIds.add(block.created_by_id);
if (block.last_edited_by_id) userIds.add(block.last_edited_by_id);
});
// Fetch all user data at once
const usersData = await api.getUsers(Array.from(userIds));
const usersMap = new Map();
usersData.results.forEach(user => {
usersMap.set(user.id, user);
});
// Enrich blocks with user information
Object.entries(page.block).forEach(([blockId, record]) => {
const block = record.value;
const creator = usersMap.get(block.created_by_id);
const editor = usersMap.get(block.last_edited_by_id);
console.log(`Block ${blockId}:`);
console.log(` Created by: ${creator?.given_name} ${creator?.family_name}`);
console.log(` Last edited by: ${editor?.given_name} ${editor?.family_name}`);
});Handle cases where blocks or users cannot be fetched:
Usage Examples:
try {
const blocksData = await api.getBlocks(["invalid-block-id"]);
// Check if any blocks were actually returned
const blockCount = Object.keys(blocksData.recordMap.block).length;
if (blockCount === 0) {
console.log("No blocks found or accessible");
}
} catch (error) {
console.error("Failed to fetch blocks:", error.message);
}
try {
const usersData = await api.getUsers(["invalid-user-id"]);
// Check results
if (usersData.results.length === 0) {
console.log("No users found");
}
} catch (error) {
console.error("Failed to fetch users:", error.message);
}Install with Tessl CLI
npx tessl i tessl/npm-notion-clientevals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10