Pages are the building blocks of Notion. Think of them as documents that can live on their own, inside databases, or nested within other pages. This guide shows you how to create, retrieve, and update pages using the SDK.
Before you start
All examples assume you have a client set up:
<?php
use Brd6\NotionSdkPhp\Client;
use Brd6\NotionSdkPhp\ClientOptions;
$options = (new ClientOptions())->setAuth('your_notion_token');
$notion = new Client($options);Retrieve a page
Get any page by its ID:
<?php
$pageId = '4a808e6e-8845-4d49-a447-fb2a4c460f6f';
try {
$page = $notion->pages()->retrieve($pageId);
echo "Page ID: " . $page->getId() . "\n";
echo "Created: " . $page->getCreatedTime()->format('Y-m-d H:i:s') . "\n";
echo "Last edited: " . $page->getLastEditedTime()->format('Y-m-d H:i:s') . "\n";
echo "URL: " . $page->getUrl() . "\n";
echo "Archived: " . ($page->isArchived() ? 'Yes' : 'No') . "\n";
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
}Access page properties
Page properties contain the actual data. Here's how to safely access them:
<?php
$page = $notion->pages()->retrieve($pageId);
$properties = $page->getProperties();
// Get the title property (most pages have this)
if (isset($properties['title'])) {
$titleProperty = $properties['title'];
if ($titleProperty->getType() === 'title') {
$titleTexts = $titleProperty->getTitle();
if (!empty($titleTexts)) {
echo "Page title: " . $titleTexts[0]->getPlainText() . "\n";
}
}
}
// Access other properties by name
foreach ($properties as $name => $property) {
echo "Property '{$name}' is type: " . $property->getType() . "\n";
}Create a page
Create a page in a database
Most pages you'll create will go inside a database. Here's the basic pattern:
<?php
use Brd6\NotionSdkPhp\Resource\Page;
use Brd6\NotionSdkPhp\Resource\Page\Parent\DatabaseIdParent;
use Brd6\NotionSdkPhp\Resource\Page\PropertyValue\TitlePropertyValue;
use Brd6\NotionSdkPhp\Resource\RichText\Text;
$databaseId = 'your-database-id';
// Create the page object
$page = new Page();
// Set which database this page belongs to
$parent = new DatabaseIdParent();
$parent->setDatabaseId($databaseId);
$page->setParent($parent);
// Set the title (required for most databases)
$titleProperty = new TitlePropertyValue();
$titleProperty->setTitle([
Text::fromContent('My new page')
]);
// Add properties
$page->setProperties([
'title' => $titleProperty,
]);
try {
$createdPage = $notion->pages()->create($page);
echo "Created page: " . $createdPage->getId() . "\n";
echo "URL: " . $createdPage->getUrl() . "\n";
} catch (Exception $e) {
echo "Failed to create page: " . $e->getMessage() . "\n";
}Create a page with multiple properties
Real pages usually have more than just a title. Here's how to set different property types:
<?php
use Brd6\NotionSdkPhp\Resource\Page;
use Brd6\NotionSdkPhp\Resource\Page\Parent\DatabaseIdParent;
use Brd6\NotionSdkPhp\Resource\Page\PropertyValue\TitlePropertyValue;
use Brd6\NotionSdkPhp\Resource\Page\PropertyValue\RichTextPropertyValue;
use Brd6\NotionSdkPhp\Resource\Page\PropertyValue\SelectPropertyValue;
use Brd6\NotionSdkPhp\Resource\Page\PropertyValue\CheckboxPropertyValue;
use Brd6\NotionSdkPhp\Resource\Page\PropertyValue\NumberPropertyValue;
use Brd6\NotionSdkPhp\Resource\Property\SelectProperty;
use Brd6\NotionSdkPhp\Resource\RichText\Text;
$page = new Page();
// Set parent database
$parent = new DatabaseIdParent();
$parent->setDatabaseId($databaseId);
$page->setParent($parent);
// Title property
$titleProperty = new TitlePropertyValue();
$titleProperty->setTitle([
Text::fromContent('Project Alpha')
]);
// Description (rich text)
$descriptionProperty = new RichTextPropertyValue();
$descriptionProperty->setRichText([
Text::fromContent('A comprehensive project to improve our API documentation.')
]);
// Status (select)
$statusProperty = new SelectPropertyValue();
$statusSelect = new SelectProperty();
$statusSelect->setName('In Progress');
$statusProperty->setSelect($statusSelect);
// Priority (number)
$priorityProperty = new NumberPropertyValue();
$priorityProperty->setNumber(8);
// Completed (checkbox)
$completedProperty = new CheckboxPropertyValue();
$completedProperty->setCheckbox(false);
// Set all properties
$page->setProperties([
'title' => $titleProperty,
'Description' => $descriptionProperty,
'Status' => $statusProperty,
'Priority' => $priorityProperty,
'Completed' => $completedProperty,
]);
try {
$createdPage = $notion->pages()->create($page);
echo "Created page with multiple properties!\n";
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
}Create a sub-page
Pages can contain other pages. Here's how to create a sub-page:
<?php
use Brd6\NotionSdkPhp\Resource\Page;
use Brd6\NotionSdkPhp\Resource\Page\Parent\PageIdParent;
use Brd6\NotionSdkPhp\Resource\Page\PropertyValue\TitlePropertyValue;
use Brd6\NotionSdkPhp\Resource\RichText\Text;
$parentPageId = 'parent-page-id';
$page = new Page();
// Set the parent page (not a database this time)
$parent = new PageIdParent();
$parent->setPageId($parentPageId);
$page->setParent($parent);
// Sub-pages still need a title
$titleProperty = new TitlePropertyValue();
$titleProperty->setTitle([
Text::fromContent('Meeting Notes - March 15')
]);
$page->setProperties([
'title' => $titleProperty,
]);
try {
$createdPage = $notion->pages()->create($page);
echo "Created sub-page: " . $createdPage->getId() . "\n";
} catch (Exception $e) {
echo "Error creating sub-page: " . $e->getMessage() . "\n";
}Create a page with content
You can add content blocks when creating a page:
<?php
use Brd6\NotionSdkPhp\Resource\Page;
use Brd6\NotionSdkPhp\Resource\Page\Parent\PageIdParent;
use Brd6\NotionSdkPhp\Resource\Page\PropertyValue\TitlePropertyValue;
use Brd6\NotionSdkPhp\Resource\RichText\Text;
use Brd6\NotionSdkPhp\Resource\Block\ParagraphBlock;
use Brd6\NotionSdkPhp\Resource\Block\Heading1Block;
use Brd6\NotionSdkPhp\Resource\Property\ParagraphProperty;
use Brd6\NotionSdkPhp\Resource\Property\Heading1Property;
$page = new Page();
// Set up the page as before
$parent = new PageIdParent();
$parent->setPageId($parentPageId);
$page->setParent($parent);
$titleProperty = new TitlePropertyValue();
$titleProperty->setTitle([
Text::fromContent('Project Overview')
]);
$page->setProperties([
'title' => $titleProperty,
]);
// Create content blocks
$heading = new Heading1Block();
$headingProperty = new Heading1Property();
$headingProperty->setRichText([
Text::fromContent('Introduction')
]);
$heading->setHeading1($headingProperty);
$paragraph = new ParagraphBlock();
$paragraphProperty = new ParagraphProperty();
$paragraphProperty->setRichText([
Text::fromContent('This document outlines the key objectives and milestones for our upcoming project.')
]);
$paragraph->setParagraph($paragraphProperty);
$children = [$heading, $paragraph];
try {
$createdPage = $notion->pages()->create($page, $children);
echo "Created page with content blocks!\n";
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
}Update a page
Update properties
To update a page, retrieve it first, modify what you need, then save:
<?php
try {
// Get the current page
$page = $notion->pages()->retrieve($pageId);
// Update the title
$titleProperty = new TitlePropertyValue();
$titleProperty->setTitle([
Text::fromContent('Updated Project Title')
]);
// Update a status
$statusProperty = new SelectPropertyValue();
$statusSelect = new SelectProperty();
$statusSelect->setName('Completed');
$statusProperty->setSelect($statusSelect);
// Get current properties and update them
$properties = $page->getProperties();
$properties['title'] = $titleProperty;
$properties['Status'] = $statusProperty;
$page->setProperties($properties);
// Save changes
$updatedPage = $notion->pages()->update($page);
echo "Page updated successfully!\n";
} catch (Exception $e) {
echo "Error updating page: " . $e->getMessage() . "\n";
}Update page icon and cover
Make your pages more visual with icons and cover images:
<?php
use Brd6\NotionSdkPhp\Resource\File\Emoji;
use Brd6\NotionSdkPhp\Resource\File\External;
use Brd6\NotionSdkPhp\Resource\Property\ExternalProperty;
try {
$page = $notion->pages()->retrieve($pageId);
// Add an emoji icon
$emoji = new Emoji();
$emoji->setEmoji('๐');
$page->setIcon($emoji);
// Add a cover image
$cover = new External();
$externalProperty = new ExternalProperty();
$externalProperty->setUrl('https://images.unsplash.com/photo-1506905925346-21bda4d32df4');
$cover->setExternal($externalProperty);
$page->setCover($cover);
$updatedPage = $notion->pages()->update($page);
echo "Added icon and cover to page!\n";
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
}Archive a page
Notion doesn't delete pages, it archives them. Archived pages are hidden but can be restored:
<?php
try {
$page = $notion->pages()->retrieve($pageId);
// Archive the page
$page->setArchived(true);
$updatedPage = $notion->pages()->update($page);
echo "Page archived successfully!\n";
} catch (Exception $e) {
echo "Error archiving page: " . $e->getMessage() . "\n";
}Restore an archived page
<?php
try {
$page = $notion->pages()->retrieve($pageId);
if ($page->isArchived()) {
$page->setArchived(false);
$updatedPage = $notion->pages()->update($page);
echo "Page restored!\n";
} else {
echo "Page is not archived.\n";
}
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
}Work with different property types
Here's how to handle the most common property types you'll encounter:
<?php
$page = $notion->pages()->retrieve($pageId);
$properties = $page->getProperties();
foreach ($properties as $name => $property) {
echo "Property: {$name} (type: {$property->getType()})\n";
switch ($property->getType()) {
case 'title':
$titleTexts = $property->getTitle();
if (!empty($titleTexts)) {
echo " Title: " . $titleTexts[0]->getPlainText() . "\n";
}
break;
case 'rich_text':
$richTexts = $property->getRichText();
$text = '';
foreach ($richTexts as $richText) {
$text .= $richText->getPlainText();
}
echo " Text: {$text}\n";
break;
case 'select':
$select = $property->getSelect();
echo " Selected: " . ($select ? $select->getName() : 'None') . "\n";
break;
case 'checkbox':
echo " Checked: " . ($property->getCheckbox() ? 'Yes' : 'No') . "\n";
break;
case 'number':
echo " Number: " . ($property->getNumber() ?? 'Empty') . "\n";
break;
case 'date':
$date = $property->getDate();
if ($date && $date->getStart()) {
echo " Date: " . $date->getStart()->format('Y-m-d') . "\n";
if ($date->getEnd()) {
echo " End date: " . $date->getEnd()->format('Y-m-d') . "\n";
}
}
break;
}
echo "\n";
}