CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-notion-client

Robust TypeScript client for the unofficial Notion API.

94

1.06x
Overview
Eval results
Files

blocks-users.mddocs/

Block and User Operations

Low-level operations for fetching individual blocks and user information, useful for granular data access.

Capabilities

Get Blocks

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");
}

Get Users

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);
}

Working with Block Types

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);
});

Block Hierarchy and Navigation

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);

User Information Integration

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}`);
});

Error Handling

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-client

docs

blocks-users.md

collections.md

core-api.md

files-urls.md

index.md

search.md

tile.json