notion-client-0.3.1.0: notion-client-example/Main.hs
-- |
-- Notion API Client Example (API version 2026-03-11)
--
-- This example demonstrates using the Notion API client to interact with Notion:
-- - Retrieving users and user information
-- - Retrieving databases and their data sources
-- - Updating data source schema (adding properties)
-- - Creating pages under data sources with properties and content
-- - Creating pages with markdown content (instead of block JSON)
-- - Editing page content via markdown search-and-replace
-- - Moving pages between parents
-- - Listing data source templates and creating pages with templates
-- - Creating, retrieving, updating, listing, and deleting database views
-- - Listing custom emojis
-- - Adding different types of blocks to pages
-- - Creating comments on pages and on specific blocks
-- - Listing and inspecting comments (with attachments and displayName)
-- - Querying and searching content
--
-- To run this example:
--
-- 1. Get a Notion API token from https://www.notion.so/my-integrations
-- 2. Set the NOTION_TOKEN environment variable with your token
-- 3. (Optional) Set NOTION_TEST_DATABASE_ID with a database ID to test database operations
-- 4. (Optional) Set NOTION_TEST_PAGE_ID with a page ID to test page operations
-- 5. Run with: cabal run notion-client-example
--
-- Note: Your integration must have access to the specified database and page.
module Main where
import Console (logError, printHeader, runTest)
import Control.Monad (when)
import CustomEmojiDemo (runCustomEmojiDemo)
import Data.Maybe (isNothing)
import Data.Text qualified as Text
import Data.Vector qualified as Vector
import DatabaseDemo (runDatabaseDemo)
import MarkdownDemo (runMarkdownDemo)
import Notion.V1 (Methods (..), getClientEnv, makeMethods)
import Notion.V1.Search (SearchRequest (..), SearchResult (..), SearchSort (..), SearchSortDirection (..), dataSourceFilter, pageFilter, parseSearchResults)
import PageDemo (runPageDemo)
import System.Environment qualified as Environment
import TemplateDemo (runTemplateDemo)
import UserDemo (runUserDemo)
import ViewDemo (runViewDemo)
main :: IO ()
main = do
putStrLn "Notion API Client Example"
putStrLn "========================="
-- Get environment variables with error handling
token <- do
mToken <- Environment.lookupEnv "NOTION_TOKEN"
case mToken of
Just t -> pure (Text.pack t)
Nothing -> logError (Text.pack "NOTION_TOKEN environment variable is required")
databaseIdEnv <- Environment.lookupEnv "NOTION_TEST_DATABASE_ID"
pageIdEnv <- Environment.lookupEnv "NOTION_TEST_PAGE_ID"
when (isNothing databaseIdEnv && isNothing pageIdEnv) $
putStrLn "WARNING: Neither NOTION_TEST_DATABASE_ID nor NOTION_TEST_PAGE_ID are set.\n Only basic user API functionality will be demonstrated."
printHeader (Text.pack "Client Initialization")
clientEnv <- getClientEnv (Text.pack "https://api.notion.com/v1")
putStrLn "Client initialized"
let methods = makeMethods clientEnv token
-- User API demo
runUserDemo methods
-- Custom Emojis demo (no setup needed)
runCustomEmojiDemo methods
-- Optional Page tests
case pageIdEnv of
Just pageIdStr -> do
runPageDemo methods pageIdStr
runMarkdownDemo methods pageIdStr
Nothing ->
putStrLn "Skipping page/markdown tests (set NOTION_TEST_PAGE_ID to enable)"
-- Optional Database tests
case databaseIdEnv of
Just databaseIdStr -> do
runDatabaseDemo methods databaseIdStr
runViewDemo methods databaseIdStr
runTemplateDemo methods databaseIdStr
Nothing ->
putStrLn "Skipping database/view/template tests (set NOTION_TEST_DATABASE_ID to enable)"
-- Search API
printHeader (Text.pack "Search API")
-- General search
let searchParams =
SearchRequest
{ query = Nothing,
sort = Just (SearchSort {direction = Descending, timestamp = Text.pack "last_edited_time"}),
filter = Nothing,
startCursor = Nothing,
pageSize = Just 5
}
rawResults <-
runTest (Text.pack "Searching (all objects, sorted by last_edited_time)") $
search methods searchParams
let typedResults = parseSearchResults rawResults
putStrLn $ " Found " <> show (Vector.length typedResults) <> " typed results"
Vector.forM_ typedResults $ \result ->
case result of
PageResult _ -> putStrLn " - page"
DataSourceResult _ -> putStrLn " - data_source"
-- Search filtered to pages only
let pageSearchParams =
SearchRequest
{ query = Nothing,
sort = Nothing,
filter = Just pageFilter,
startCursor = Nothing,
pageSize = Just 3
}
pageResults <-
runTest (Text.pack "Searching (pages only)") $
search methods pageSearchParams
let typedPageResults = parseSearchResults pageResults
putStrLn $ " Found " <> show (Vector.length typedPageResults) <> " pages"
-- Search filtered to data sources only
let dsSearchParams =
SearchRequest
{ query = Nothing,
sort = Nothing,
filter = Just dataSourceFilter,
startCursor = Nothing,
pageSize = Just 3
}
dsResults <-
runTest (Text.pack "Searching (data sources only)") $
search methods dsSearchParams
let typedDsResults = parseSearchResults dsResults
putStrLn $ " Found " <> show (Vector.length typedDsResults) <> " data sources"
-- All done
printHeader (Text.pack "Test complete")
putStrLn "All tests completed successfully!"