Back

Reading and Writing Data Using the Notion API

Jul 17, 20246 minute read

Hey there, fellow JavaScript enthusiasts! Ready to dive into the world of Notion API? Let's get our hands dirty with some data syncing for user-facing integrations. Buckle up!

Setting Up the Notion API

First things first, let's get you set up. Head over to the Notion developers page and snag your API key. Once you've got that, install the Notion client:

npm install @notionhq/client

Now, let's initialize our client:

const { Client } = require('@notionhq/client'); const notion = new Client({ auth: process.env.NOTION_API_KEY });

Reading Data from Notion

Reading data is a breeze. Here's how you can query a database:

async function queryDatabase(databaseId) { try { const response = await notion.databases.query({ database_id: databaseId, }); return response.results; } catch (error) { console.error('Error querying database:', error); } }

Writing Data to Notion

Creating a new page in a database is just as easy:

async function createPage(databaseId, properties) { try { const response = await notion.pages.create({ parent: { database_id: databaseId }, properties: properties, }); return response; } catch (error) { console.error('Error creating page:', error); } }

Implementing Data Sync

Now, let's put it all together with a basic sync function:

async function syncData(localData, databaseId) { const notionData = await queryDatabase(databaseId); for (const item of localData) { const existingItem = notionData.find(n => n.properties.ID.rich_text[0].text.content === item.id); if (existingItem) { // Update existing item await notion.pages.update({ page_id: existingItem.id, properties: { // Map your properties here }, }); } else { // Create new item await createPage(databaseId, { // Map your properties here }); } } }

Error Handling and Edge Cases

Always wrap your API calls in try-catch blocks. Here's a handy wrapper:

async function notionApiCall(apiFunction, ...args) { try { return await apiFunction(...args); } catch (error) { if (error.status === 429) { console.log('Rate limited. Retrying in 5 seconds...'); await new Promise(resolve => setTimeout(resolve, 5000)); return notionApiCall(apiFunction, ...args); } throw error; } }

Optimizing Performance

Batching updates can significantly improve performance:

async function batchUpdate(pages) { const batchSize = 10; for (let i = 0; i < pages.length; i += batchSize) { const batch = pages.slice(i, i + batchSize); await Promise.all(batch.map(page => notion.pages.update(page))); } }

Webhooks for Real-time Updates

Notion webhooks are your friend for real-time updates. Here's a simple Express handler:

app.post('/notion-webhook', (req, res) => { const { type, page } = req.body; if (type === 'page_updated') { // Handle page update console.log('Page updated:', page.id); } res.sendStatus(200); });

Testing and Debugging

Don't forget to test! Here's a simple test case using Jest:

test('createPage creates a new page', async () => { const mockPage = { id: 'test-id', properties: {} }; notion.pages.create = jest.fn().mockResolvedValue(mockPage); const result = await createPage('database-id', {}); expect(result).toEqual(mockPage); expect(notion.pages.create).toHaveBeenCalledWith({ parent: { database_id: 'database-id' }, properties: {}, }); });

Wrapping Up

And there you have it! You're now equipped to read and write data like a Notion API pro. Remember to keep an eye on those rate limits, batch your requests when possible, and always handle your errors gracefully.

Happy coding, and may your data always be in sync! 🚀