Pages

Create, retrieve, and update Notion pages.

6 min read

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";
}

Did this answer your question?