Working with databases

Learn about database schemas, querying databases, and more.

Overview

Databases allow users to create and manipulate structured data in Notion. Integrations can help users sync databases with external systems or build workflows around Notion databases.

📘

Databases vs. linked databases

Notion offers linked databases as a way of showing databases in multiple places. You can identify them by a ↗ next to the database title which, when clicked, takes you to the source database.

The Notion API does not work with linked databases. When sharing a database with your integration, make sure it's the source one!

In this guide, you'll learn about how databases are represented in the API, how to add items to a database, and how to find items within them. You'll also learn how to update page properties.

Structure

Database objects describe a part of what a user sees in Notion when they open a database. The most important part is the database's schema, defined in the properties collection.

{
  "object": "database",
  
  "id": "2f26ee68-df30-4251-aad4-8ddc420cba3d",
  "created_time": "2020-03-17T19:10:04.968Z",
  "last_edited_time": "2020-03-17T21:49:37.913Z",
  "title": [/* details omitted */],
  
  "properties": {/* a collection of property objects */},
}

Properties

Let's assume you're viewing a database as a table. Property objects store a description of a column, including a type for of all the values in a column. You might recognize a few of the common types: text, numbers, dates, people, and more. For each type, additional configuration may also be available. Let's take a look at the properties section of an example database object.

{
  "object": "database",
    
  "properties": {
    "Grocery item": {
      "id": "fy:{",
      "type": "title",
      "title": {}
    },
    "Price": {
      "id": "dia[",
      "type": "number",
      "number": {
        "format": "dollar"
      }
    },
    "Last ordered": {
      "id": "]\\R[",
      "type": "date",
      "date": {}
    },
  }
  
  // remaining details omitted
}

In this database object, there are three properties defined. Each key is the property name and each value is a property object. Here are some key takeaways:

  • The "title" type is special. Every database has exactly one property with the "title" type. Properties of this type refer to the page title for each item in the database. In this example, the Grocery item property has this type.
  • The value of type corresponds to another key in the property object. Each property object has a nested property named the same as it's type value. For example, Last ordered has the type "date", and it also has a date property. This pattern is used throughout the Notion API on many objects and we call it type-specific data.
  • Certain property object types have additional configuration. In this example, Price has the type "number". Number property objects have additional configuration inside the number property. In this example, the format configuration is set to "dollar" to control the appearance of page property values in this column.

Adding pages to a database

Pages are used as items inside a database, and each page's properties must conform to it's parent database's schema. In other words, if you're viewing a database as a table, a page's properties define all the values in a single row.

Pages are added to a database using the create a page API endpoint. Let's try to add a page to the example database above. The endpoint has two required parameters: parent and properties.

When adding a page to a database, the parent parameter must be a database parent. We can build this object for the example database above:

{
  "type": "database_id",
  "database_id": "2f26ee68-df30-4251-aad4-8ddc420cba3d"
}

🚧

Permissions

Before an integration can add a page to a database, a user must share that database with the integration. Users can share a database using the Share menu inside Notion on the database, or on any parent page of the database.

📘

Where can I find my database's ID?

Here's a quick procedure to find the database ID for a specific database in Notion:

Open the database as a full page in Notion. Use the Share menu to Copy link. Now paste the link in your text editor so you can take a closer look. The URL uses the following format:

https://www.notion.so/{workspace_name}/{database_id}?v={view_id}

Find the part that corresponds to {database_id} in the URL you pasted. It is a 36 character long string. This value is your database ID.
Note that when you receive the database ID from the API, e.g. the search endpoint, it will contain hyphens in the UUIDv4 format. You may use either the hyphenated or un-hyphenated ID when calling the API.

The properties parameter is an object which uses property names or IDs as keys, and property value objects as values. In order to create this parameter correctly, you refer to the
property objects in the database's schema. We can build this object for the example database above too:

{
  "Grocery item": {
    "type": "title",
    "title": [{ "type": "text", "text": { "content": "Tomatoes" } }]
  },
  "Price": {
    "type": "number",
    "number": 1.49
  },
  "Last ordered": {
    "type": "date",
    "date": { "start": "2021-05-11" }
  }
}

📘

Building a property value object in code

Building the property value object manually, as described in this guide, is only helpful when you're working with one specific database that you know about ahead of time. In order to build an integration that works with any database a user picks, and to remain flexible as the user's chosen database inevitably changes in the future, use the retrieve a database endpoint. Your integration can call this endpoint to get a current database schema, and then create the properties parameter in code based on that schema.

Using both the parent and properties parameters, we create a page by sending a request to the endpoint.

curl -X POST https://api.notion.com/v1/pages \
  -H 'Authorization: Bearer '"$NOTION_API_KEY"'' \
  -H "Content-Type: application/json" \
  -H "Notion-Version: 2021-05-13" \
  --data '{
      "parent": { "type": "database_id", "database_id": "2f26ee68-df30-4251-aad4-8ddc420cba3d" },
      "properties": {
      "Grocery item": {
        "type": "title",
        "title": [{ "type": "text", "text": { "content": "Tomatoes" } }]
      },
      "Price": {
        "type": "number",
        "number": 1.49
      },
      "Last ordered": {
        "type": "date",
        "date": { "start": "2021-05-11" }
      }
    }
  }'
const { Client } = require('@notionhq/client');

const notion = new Client({ auth: process.env.NOTION_API_KEY });

(async () => {
  const response = await notion.pages.create({
    parent: {
      database_id: '2f26ee68-df30-4251-aad4-8ddc420cba3d',
    },
    properties: {
      'Grocery item': {
        type: 'title',
        title: [
          {
            type: 'text',
            text: {
              content: 'Tomatoes',
            },
          },
        ],
      },
      Price: {
        type: 'number',
        number: 1.49,
      },
      'Last ordered': {
        type: 'date',
        date: {
          start: '2021-05-11',
        },
      },
    },
  });
  console.log(response);
})();

Once the page is added, you'll receive a response containing the new page object. An important property in the response is the page ID (id). If you're connecting Notion to an external system, it's a good idea to store the page ID. If you want to update the page properties later, you can use the ID with the update page properties endpoint.

Finding pages in a database

Pages can be read from a database using the query a database endpoint. This endpoint allows you to find pages based on criteria such as "where the Last ordered date is in the past week". Some databases are very large and this endpoint also allows you to get the results in a specific order, and get the results in smaller batches.

📘

Getting a specific page

If you're looking for one specific page and already have it's page ID, you don't need to query a database to find it. Instead, use the retrieve a page endpoint.

The criteria used to find pages are called filters. Filters can describe simple conditions (i.e. "Tag includes Urgent") or more complex conditions (i.e. "Tag includes Urgent AND Due date is within the next week AND Assignee equals Cassandra Vasquez"). These complex conditions are called compound filters because they use "and" or "or" to join multiple single property conditions together.

📘

Finding all pages in a database

In order to find all the pages in a database, send a request to the query a database without a filter parameter.

In this guide, let's focus on a single property condition using the example database above. Looking at the database schema, we know the Last ordered property uses the type "date". This means we can build a filter for the Last ordered property using any condition for the "date" type. The following filter object which matches pages where the Last ordered date is in the past week:

{
  "property": "Last ordered",
  "date": {
    "past_week": {}
  }
}

Using this filter, we can find all the pages in the example database which pages the condition.

curl -X POST https://api.notion.com/v1/databases/2f26ee68df304251aad48ddc420cba3d/query \
  -H 'Authorization: Bearer '"$NOTION_API_KEY"''
  -H "Content-Type: application/json" \
    --data '{
      "filter": {
      "property": "Last ordered",
      "date": {
        "past_week": {}
      }
        }
    }'
const { Client } = require('@notionhq/client');

const notion = new Client({ auth: process.env.NOTION_API_KEY });

(async () => {
  const databaseId = '2f26ee68df304251aad48ddc420cba3d';
  const response = await notion.databases.retrieve({
    database_id: databaseId,
    filter: {
      property: 'Last ordered',
      date: {
        past_week: {},
      },
    }
  });
  console.log(response);
})();

You'll receive a response that contains a list of matching page objects.

{
  "object": "list",
  "results": [
    {
      "object": "page",
      /* details omitted */
    }
  ],
  "has_more": false,
  "next_cursor": null
}

This is a paginated response. Paginated responses are used throughout the Notion API when returning a potentially large list of objects. The maximum number of results in one paginated response is 100. The pagination reference explains how to use the "start_cursor" and "page_size" parameters to get more than 100 results.

In this case, the individual pages we requested are in the "results" array. What if our integration (or its users) cared most about pages that were created recently? It would be helpful if the results were ordered so that the most recently created page was first, especially if the results didn't fit into one paginated response.

The sort parameter is used to order results by individual properties or by timestamps. This parameter can be assigned an array of sort object.

The time which a page was created is not a page property (properties that conform to the database schema). Instead, it's a property that every page has, and it's one of two kinds of timestamps. It is called the "created_time" timestamp. Let's build a sort object that orders results so the most recently created page is first:

{
  "timestamp": "created_time",
  "direction": "descending"
}

Finally, let's update the request we made earlier to order the page results using this sort object:

curl -X POST https://api.notion.com/v1/databases/2f26ee68df304251aad48ddc420cba3d/query \
  -H 'Authorization: Bearer '"$NOTION_API_KEY"''
  -H "Content-Type: application/json" \
    --data '{
      "filter": {
      "property": "Last ordered",
      "date": {
        "past_week": {}
      }
        },
    "sorts": [{ "timestamp": "created_time", "direction": "descending" }]
    }'
const { Client } = require('@notionhq/client');

const notion = new Client({ auth: process.env.NOTION_API_KEY });

(async () => {
  const databaseId = '2f26ee68df304251aad48ddc420cba3d';
  const response = await notion.databases.retrieve({
    database_id: databaseId,
    filter: {
      property: 'Last ordered',
      date: {
        past_week: {},
      },
    },
    sorts: [
      {
        timestamp: 'created_time',
        direction: 'descending',
      },
    ]
  });
  console.log(response);
})();

Conclusion

Understanding database schemas, made from a collection of database properties, is key to working with Notion databases. This enables you to add pages to a database and also get find items in a database.

You're ready to help users take advantage of Notion's flexible and extensible database interface to work with more kinds of data. There's more to learn and do with databases in the resources below.

Next steps

Updated about a month ago


Working with databases


Learn about database schemas, querying databases, and more.

Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.