Getting Started with the Notion API

Getting Started with the Notion API

The Notion API is something that has excited developers all over for a while now. It has been a long time coming and it's finally out in beta!

Notion's UI is an easy way to quickly create any type of content and organize that content with metadata. Fun things you could build with the Notion API:

  • A blog where you write your posts in Notion and publish when you set a select to Published
  • An expenses tracker
  • A team task manager

To get started with the Notion API, we can find the starting portal is here at developers.notion.com.

Notion has put together a great Getting Started with the Notion API Doc.

Let's explore how we can create a Notion page and database, and get that content via the API.

The first thing we need to do is create an integration. This is essentially a Notion app that will give us a Notion Token so that we can securely connect to the API.

Create an integration here: notion.so/my-integrations

Notion Integration Getting a Token

Keep this integration token safe. This token will have access to read and write to some of your Notion databases.

Now that we have an integration, we need to have data to grab. We can create a Notion Database (or use one that you already have). Create a page in Notion and select Table under Database.

Creating a Notion Database

To connect to your Notion database, we'll need to grab its database ID.

Notion desktop app: Click on the Share button once again and select Copy link. Navigate to this link in your browser. You may need to login. The database ID is in the URL.

Notion in a browser: The database ID is the part of the URL after your workspace name and the slash (betterdev) and before the question mark (?).

The ID is 32 characters long, containing numbers and letters. Copy the ID as we'll need it later.

javascript
https://www.notion.so/betterdev/a8aec43384f447ed84390e8e42c2e089?v=...
                                |--------- Database ID --------|

Now that we have a Notion Integration and a Notion Database, we can connect the two and start grabbing data.

We do this because this is how we will have proper credentials to connect to a database. Each integration has a secret token and that token will only get access to the databases you say it can have access to.

The flow goes like this:

Go into the Notion page and click Share in the top right. Click Invite and pick your integration.

Adding a Notion Integration

We'll use Postman (an API explorer tool) to connect to the Notion API and grab data from our new Notion Database.

We can get a database from the Notion API using the Get Database API endpoint.

To query for a database, the API call is:

javascript
Endpoint: GET https://api.notion.com/v1/databases/<YOUR-DATABASE-ID>

Headers:
{
    "Authorization": "Bearer <YOUR-INTEGRATION-TOKEN>",
  "Notion-Version": "2021-05-13"
}

Note: The Notion-Version is required so that Notion knows what version of the API to serve. All calls to the API need this versioning header.

This gives us this result of the information about the database. But it doesn't give us the contents of the database. See the next section for the API call for contents of the Notion database.

Getting a Notion API Database

This endpoint gets the properties/information about the database. It doesn't get the pages in the database.

To get the pages of a Notion API database, we need to use a the Query a Database endpoint.

To query for the contents of a database:

javascript
Endpoint: POST https://api.notion.com/v1/databases/<YOUR-DATABASE-ID>/query

Headers:
{
    "Authorization": "Bearer <YOUR-INTEGRATION-TOKEN>",
  "Notion-Version": "2021-05-13"
}

This will return an array of results.

We can also filter a database by using the Query a Database endpoint.

Let's say we wanted to only get all things in this database that had a Status of Published.

We could use the query endpoint:

https://api.notion.com/v1/databases/9c7e566520fa490f8817781ef24de2a1/query

Here's what the call looks like in JavaScript to only find Published pages.

javascript
fetch(
  "https://api.notion.com/v1/databases/8b818d10777247e9a48438662363637b/query",
  {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.NOTION_TOKEN}`,
      "Notion-Version": "2021-05-13",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      filter: { property: "Status", select: { equals: "Published" } },
    }),
  }
);

You can filter on multiple conditions. Here's how we can find all published articles that have "React" in the title.

javascript
body: JSON.stringify({
  filter: {
    and: [
      { property: "Status", select: { equals: "Published" } },
      { property: "Title", text: { contains: "React" } },
    ]
  }
}),

Read up on the Notion filters you can use.

To get information for a Notion page, we can use the Query a Page API endpoint:

https://api.notion.com/v1/pages/<page_id>

We get the page ID from the previous API call to query the database.

While we can get information about the page here, we can't really see the contents of the page. We can only see the page properties. Just like databases, there's a difference between getting the database properties vs the content in the database.

While we can get the values of a page, in the previous call, we need to get the contents of that page. We need to get all the Notion blocks in the Notion page.

Notion Page Properties vs Page Content

In Notion, the page content of a page contains blocks. This can be any type of content you can insert in Notion.

Notion Blocks

Here is how the Notion API models blocks like a paragraph.

javascript
{
  "object": "block",
  "id": "380c78c0-e0f5-4565-bdbd-c4ccb079050d",
  "type": "paragraph",
  "created_time": "",
  "last_edited_time": "",
  "has_children": false,

  "paragraph": {
    "text": [/* details omitted */]
  }
}

Now that we understand how Notion stores content inside of a page, we can get the blocks of that page.

To get the blocks in a page, we will use the Get Block Children API call. It asks for a block ID. We can use the page's ID since a page is a special kind of block.

javascript
GET https://api.notion.com/v1/blocks/<block_id>/children

The call would look like this:

javascript
fetch("https://api.notion.com/v1/blocks/<page_id_is_the_block_id>/children", {
  headers: {
    Authorization: `Bearer ${process.env.NOTION_TOKEN}`,
    "Notion-Version": "2021-05-13"
  },
});

We will get the blocks back in the results array:

json
{
  "object": "list",
  "results": [
    {
      "object": "block",
      "id": "9bc30ad4-9373-46a5-84ab-0a7845ee52e6",
      "created_time": "2021-03-16T16:31:00.000Z",
      "last_edited_time": "2021-03-16T16:32:00.000Z",
      "has_children": false,
      "type": "heading_2",
      "heading_2": {
        "text": [
          {
            "type": "text",
            "text": {
              "content": "Lacinato kale",
              "link": null
            },
            "annotations": {
              "bold": false,
              "italic": false,
              "strikethrough": false,
              "underline": false,
              "code": false,
              "color": "default"
            },
            "plain_text": "Lacinato kale",
            "href": null
          }
        ]
      }
    },
    {
      "object": "block",
      "id": "7face6fd-3ef4-4b38-b1dc-c5044988eec0",
      "created_time": "2021-03-16T16:34:00.000Z",
      "last_edited_time": "2021-03-16T16:36:00.000Z",
      "has_children": false,
      "type": "paragraph",
      "paragraph": {
        "text": [
          {
            "type": "text",
            "text": {
              "content": "Lacinato kale",
              "link": {
                "url": "https://en.wikipedia.org/wiki/Lacinato_kale"
              }
            },
            "annotations": {
              "bold": false,
              "italic": false,
              "strikethrough": false,
              "underline": false,
              "code": false,
              "color": "default"
            },
            "plain_text": "Lacinato kale",
            "href": "https://en.wikipedia.org/wiki/Lacinato_kale"
          },
          {
            "type": "text",
            "text": {
              "content": " is a variety of kale with a long tradition in Italian cuisine, especially that of Tuscany. It is also known as Tuscan kale, Italian kale, dinosaur kale, kale, flat back kale, palm tree kale, or black Tuscan palm.",
              "link": null
            },
            "annotations": {
              "bold": false,
              "italic": false,
              "strikethrough": false,
              "underline": false,
              "code": false,
              "color": "default"
            },
            "plain_text": " is a variety of kale with a long tradition in Italian cuisine, especially that of Tuscany. It is also known as Tuscan kale, Italian kale, dinosaur kale, kale, flat back kale, palm tree kale, or black Tuscan palm.",
            "href": null
          }
        ]
      }
    },
    {
      "object": "block",
      "id": "7636e2c9-b6c1-4df1-aeae-3ebf0073c5cb",
      "created_time": "2021-03-16T16:35:00.000Z",
      "last_edited_time": "2021-03-16T16:36:00.000Z",
      "has_children": true,
      "type": "toggle",
      "toggle": {
        "text": [
          {
            "type": "text",
            "text": {
              "content": "Recipes",
              "link": null
            },
            "annotations": {
              "bold": true,
              "italic": false,
              "strikethrough": false,
              "underline": false,
              "code": false,
              "color": "default"
            },
            "plain_text": "Recipes",
            "href": null
          }
        ]
      }
    }
  ],
  "next_cursor": null,
  "has_more": false
}

Notion has created a JavaScript SDK that simplifies connecting to the API and getting data. We'll do a full article and video on the SDK, but check it out to see how you can quickly connect.

https://github.com/makenotion/notion-sdk-js

Chris Sev

Chris Sev

Chris Sev is the co-founder of Better Dev. Coding better every day. Previously he created Scotch.io which was acquired.

In this article...

Comments

What did you think of the article? Let us know!
(these comments are powered by GitHub issues and use 0 trackers)