Creating pages from templates
Learn how to apply data source templates to pages created in the Notion API.
Overview
Database templates save time when adding a new page to a data source. Instead of building manually from a blank page, templates accelerate your workflows by providing a blueprint for the page's properties and content.
For example, a bug tracking database can have templates for various types of bugs, like "Urgent Production Bug" and "User Interface (UI) Bug".
The Notion app can be used to create and manage templates, and designate one as the "default" template:

To take advantage of templates when creating pages in the API, the three main steps are:
- Identify the template to use. Use the List data source templates endpoint, or manually navigate to the template in the Notion app and get its ID. Skip this step if you want to apply the data source's "default" template.
- Create page with the chosen template. Provide a
template[type]
ofdefault
, or oftemplate_id
alongside atemplate[template_id]
, to the Create a page API to kick off the process of "duplicating" a template into a new page.- Remember to use a
parent[type]
ofdata_source_id
and provide aparent[data_source_id]
when creating a page under a data source. - Store the ID of the newly created page in your app's backend storage systems. This will be necessary in the next step, since the returned page is momentarily blank until the template finishes applying.
- Remember to use a
- Wait for template processing to complete. If your integration needs to perform additional steps once a template has finished applying to a page and it's ready for use, wait for Notion's systems to populate the page content before proceeding.
- Register an handler for integration webhooks that listens to
page.created
andpage.content_updated
events and uses the Retrieve block children API to confirm the page contents are populated.
- Register an handler for integration webhooks that listens to
Step 1: Identify the template to use
For integrations using the Notion API, use the List data source templates endpoint to retrieve a list of template IDs and titles:
curl --request GET \
--url 'https://api.notion.com/v1/data_sources/b55c9c91-384d-452b-81db-d1ef79372b75/templates' \
-H 'Notion-Version: 2025-09-03' \
-H 'Authorization: Bearer '"$NOTION_API_KEY"''
The API response includes a similar set of information as the Notion app displays in the screenshot above:
{
"templates": [
{
"id": "a5da15f6-b853-455d-8827-f906fb52db2b",
"name": "New Generic Task",
"is_default": true
},
{
"id": "9cc74169-8dd7-4104-8b36-ed952ac44bd0",
"name": "New UI Task",
"is_default": false
},
{
"id": "f2d298e3-efeb-4401-bf4f-67e7b194694f",
"name": "New Support Task",
"is_default": false
}
]
}
Aside from this API endpoint, templates are regular pages in Notion, so you can also get the template ID by opening the template, copying the URL, and extracting the ID from it. For example, if the template looks like https://notion.so/notion/New-Hire-Onboarding-a07589e357414b3285a8d02beb8fd9dd
, the template id
is a07589e357414b3285a8d02beb8fd9dd
. Determining the ID of a template will be useful in the next step, where we'll create pages using templates.
Step 2: Create page using a template
By default, adding pages to a data source creates them with only the block children
you provide. In other words, the content has to be built up from scratch manually.
In the Create a page API, this corresponds to the template[type] = "none"
parameter. The two other options for type
allow you to start taking advantage of the power of templates at page creation time:
template[type] | template[template_id] | Behavior |
---|---|---|
none (or omitted) | N/A | No template. Provided children and properties are immediately applied. |
default | N/A | Applies the data source's default template to the newly created page. children cannot be specified in the create page request. |
template_id | (ID of a template) | Use an ID from the response of List data source templates, or copied from a URL, as the template_id . Indicates which exact template to apply to the newly created page. children cannot be specified in the create page request. |
When using a template — either the default
template or a specific template_id
— the Create Page API request returns immediately with a Page object representing a blank page, aside from any initial properties
(for example, the title
) set on it. Store the ID of this page in your backend systems if you need it for Step 3 below.
Afterwards, Notion's systems quickly begin applying the chosen template in the background, replacing the page content and merging in the template's properties. Any placeholder values (e.g. "Current time when duplicating template"), are appropriately populated, the same way they would be when a Notion user applies a template in the app. The key difference is that the API bot user (rather than a person) is set as the "created by" user (i.e. author) of the new page.
Check page and database permissions
The Notion API returns an HTTP 400
validation_error
response in the following scenarios:
- The provided template ID is invalid. Template IDs are UUIDs (v4) and look like page IDs in Notion.
- The integration doesn't have access to the template. Generally, if a bot is connected to the data source's parent database, those permissions apply to all templates for the data source by default, since templates are represented as (special) pages under the data source.
- However, to confirm, check the "Connections" list under the 3-dot overflow menu for a template to ensure your bot appears in the list.
- Attempting to apply the default template when there isn't one. When using
template[type]=default
, ensure theparent
in the Create Page request is pointing to the correctdata_source_id
, and that the data source has a template that's marked as "default".
Step 3: Confirm page contents are ready
After Step 2, Notion's systems asynchronously begin processing a task to populate the page contents and properties based on the template you identified. In most cases, this is visually very prompt when viewing the data source in the Notion app, but for API integrations, you might need an additional step to wait for processing to complete, in cases where your integration needs to take action once the page is ready.
Webhook setup
Go through the Webhooks guide to set up a webhook URL for your integration, and make sure you're using the newest API version in your webhook settings. Also, make sure you have enabled page.created
and page.content_updated
events.
How aggregated events work
Internally, Notion produces a page.content_updated
event once the template duplication is complete, but in the API, such events might be aggregated into the base page.created
event if they take place in a short enough time window, which will generally be the case. As a result, you might not see the page.created
event immediately after Step 2 (the Create a page call). In these cases, the page.created
event will be deferred until the page is ready.
In rare cases, or for complex templates, Notion's processing of the page might take longer. In this case, your integration may receive the page.created
event for the blank page created from Step 2, and subsequently, a page.content_updated
event when the page is ready.
For more information on event aggregation, refer to the detailed event types reference .
Webhook implementation
Putting the above flow together, your webhook handler can implement logic as follows:
- When receiving a
page.created
orpage.content_updated
event with the entity ID matching the page Id created in Step 2 👀:- If the event is
page.content_updated
, you know the template has finished applying, and can proceed to any further steps your integration needs to take ✅. - If the event is
page.created
, call the Retrieve block children API using the page ID to check if the page content is a blank array, or if it includes the content you expect from the template 👀.- If the page contents have been populated, you know the template has finished applying, and can proceed to any further steps your integration needs to take ✅,
- Otherwise, stop processing and wait for a
page.content_updated
event signaling the completion of applying the template ⏳.
- If the event is
Updated 2 minutes ago