### Build the Notionrs Project Source: https://github.com/46ki75/notionrs/blob/main/notionrs/AGENTS.md Use this command to compile the entire project. Ensure you have Rust and Cargo installed. ```bash cargo build ``` -------------------------------- ### Create Notion Database with Basic Properties Source: https://github.com/46ki75/notionrs/blob/main/docs/database/create-database.md Use this method to create a new Notion database. Ensure you have your NOTION_TOKEN and PAGE_ID set as environment variables or replace the placeholders. This example includes an email property. ```rust use std::collections::HashMap; use notionrs::{ database::{DatabaseEmailProperty, DatabaseProperty}, error::Error, Client, RichText, }; #[tokio::main] async fn main() -> Result<(), Error> { let client = Client::new().secret("NOTION_TOKEN"); let title = vec![RichText::from("Database Title")]; let mut properties = HashMap::new(); properties.insert( "email".to_string(), DatabaseProperty::Email(DatabaseEmailProperty::default()), ); let request = client.create_database().page_id("PAGE_ID").title(title); let _response = request.send().await?; Ok(()) } ``` -------------------------------- ### Add tokio Crate for Async Runtime Source: https://github.com/46ki75/notionrs/blob/main/docs/introduction/getting-started.md To use notionrs, which is asynchronous, add the tokio crate with the 'full' feature enabled. This command installs tokio. ```sh cargo add tokio --features full ``` -------------------------------- ### Handle Notion Webhooks with Axum Source: https://github.com/46ki75/notionrs/blob/main/notionrs_webhooks/README.md This example demonstrates how to set up an Axum handler to receive and process Notion webhooks. It includes signature verification and deserialization of the webhook event data. Ensure you have the necessary dependencies like `axum`, `tokio`, and `notionrs-webhooks`. ```rust use axum::{response::IntoResponse, routing::post}; use http::{StatusCode, request::Parts}; use notionrs_webhooks::PageContentUpdated; async fn handler(parts: Parts, body: axum::body::Bytes) -> impl IntoResponse { let verification_token: &'static [u8; 5] = b"token"; let maybe_x_notion_signature = parts.headers.get("x-api-signature"); match maybe_x_notion_signature { None => return StatusCode::UNAUTHORIZED.into_response(), Some(x_notion_signature) => { let is_valid = notionrs_webhooks::verify_signature( verification_token, &body, x_notion_signature.as_bytes(), ); if !is_valid { return StatusCode::FORBIDDEN.into_response(); }; let event = serde_json::from_slice::(&body).unwrap(); return match event.data { notionrs_webhooks::EventData::PageContentUpdated(PageContentUpdated { parent: _, updated_blocks: _, }) => { // Something to do. StatusCode::OK.into_response() } _ => StatusCode::INTERNAL_SERVER_ERROR.into_response(), }; } }; } #[tokio::main] async fn main() { let router = axum::Router::new().route("/", post(handler)); let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap(); axum::serve(listener, router).await.unwrap(); } ``` -------------------------------- ### GET /users Source: https://context7.com/46ki75/notionrs/llms.txt Retrieve a list of all users in the workspace. ```APIDOC ## GET /users ### Description Get all users in the workspace. ### Method GET ### Endpoint /users ``` -------------------------------- ### Create a Notion Page Source: https://github.com/46ki75/notionrs/blob/main/docs/page/create-page.md Use this method to create a new page in Notion. Ensure you have your API key and the target page ID. This example demonstrates setting both a title and multi-select properties for the new page. ```rust use notionrs::{ error::Error, page::{PageMultiSelectProperty, PageProperty, PageTitleProperty}, Client, Select, SelectColor, }; #[tokio::main] async fn main() -> Result<(), Error> { let client = Client::new().secret("API_KEY"); let mut properties = std::collections::HashMap::new(); properties.insert( "Name".to_string(), PageProperty::Title(PageTitleProperty::from("My Page")), ); properties.insert( "Tags".to_string(), PageProperty::MultiSelect(PageMultiSelectProperty { multi_select: vec![ Select { name: "My Tag".to_string(), color: Some(SelectColor::Blue), ..Default::default() }, Select { name: "My Option".to_string(), color: Some(SelectColor::Green), ..Default::default() }, ], ..Default::default() }), ); let request = client .create_page() .page_id("PAGE_ID") .properties(properties); let response = request.send().await?; println!("This block's id is {}", response.id); Ok(()) } ``` -------------------------------- ### Retrieve a Notion Block by ID Source: https://context7.com/46ki75/notionrs/llms.txt Retrieve a single block by its ID. This example demonstrates accessing the block's content and checking its type. ```rust use notionrs::client::Client; use notionrs_types::prelude::*; #[tokio::main] async fn main() -> Result<(), Box> { let client = Client::new(std::env::var("NOTION_TOKEN").unwrap()); let request = client.get_block().block_id("BLOCK_ID"); let response = request.send().await?; println!("This block's id is {}", response.id); if let Block::Paragraph { paragraph } = response.block { let text = paragraph.to_string(); println!("{}", text); } Ok(()) } ``` -------------------------------- ### GET /users/me Source: https://context7.com/46ki75/notionrs/llms.txt Retrieve the bot user associated with the current API token. ```APIDOC ## GET /users/me ### Description Retrieve the bot user associated with the current token. ### Method GET ### Endpoint /users/me ``` -------------------------------- ### Update an Existing Notion Block Source: https://context7.com/46ki75/notionrs/llms.txt Modify the content of an existing block. This example updates a paragraph block with new text and a blue background. ```rust use notionrs::{Client, Error}; use notionrs_types::prelude::*; #[tokio::main] async fn main() -> Result<(), Error> { let client = Client::new(std::env::var("NOTION_TOKEN").unwrap()); let rich_text = RichText::from("Updated paragraph text"); let block = Block::Paragraph { paragraph: ParagraphBlock::default() .rich_text(vec![rich_text.clone()]) .blue_background(), }; let request = client.update_block().block_id("BLOCK_ID").block(block); let response = request.send().await?; println!("{:?}", response); Ok(()) } ``` -------------------------------- ### Comments API - Retrieve Comments Source: https://context7.com/46ki75/notionrs/llms.txt Get all comments on a page. ```APIDOC ## GET /comments ### Description Get all comments on a page. ### Method GET ### Endpoint /comments ### Parameters #### Query Parameters - **page_id** (string) - Required - The ID of the page to retrieve comments from. ### Response #### Success Response (200) - **results** (array) - An array of comment objects. - **next_cursor** (string) - A cursor for fetching the next page of results. - **has_more** (boolean) - Indicates if there are more results to fetch. #### Response Example ```json { "results": [ { "id": "a1b2c3d4-e5f6-7890-1234-567890abcdef", "type": "comment", "created_time": "2023-10-27T10:00:00Z", "created_by": { "object": "user", "id": "user-id" }, "parent": { "type": "page_id", "page_id": "PAGE_ID" }, "discussion_id": "discussion-id", "url": "https://www.notion.so/threads/discussion-id/a1b2c3d4-e5f6-7890-1234-567890abcdef" } ], "next_cursor": null, "has_more": false } ``` ``` -------------------------------- ### GET /users/{user_id} Source: https://context7.com/46ki75/notionrs/llms.txt Retrieve details for a specific user by their unique identifier. ```APIDOC ## GET /users/{user_id} ### Description Retrieve a user by their ID. ### Method GET ### Endpoint /users/{user_id} ### Parameters #### Path Parameters - **user_id** (string) - Required - The unique identifier of the user. ``` -------------------------------- ### Append Block Children to a Parent Block Source: https://context7.com/46ki75/notionrs/llms.txt Add new blocks as children to an existing block or page. This example appends a paragraph with a blue background. ```rust use notionrs::{Client, Error}; use notionrs_types::prelude::*; #[tokio::main] async fn main() -> Result<(), Error> { let client = Client::new(std::env::var("NOTION_TOKEN").unwrap()); let rich_text = RichText::from("This is a new paragraph with blue background"); let block = Block::Paragraph { paragraph: ParagraphBlock::default() .rich_text(vec![rich_text.clone()]) .blue_background(), }; let request = client .append_block_children() .block_id("PARENT_BLOCK_ID") .children(vec![block]); let response = request.send().await?; println!("{:?}", response); Ok(()) } ``` -------------------------------- ### Get Page Property Item Source: https://context7.com/46ki75/notionrs/llms.txt Retrieves a specific property value from a page using its page and property IDs. Requires the NOTION_TOKEN environment variable. ```rust use notionrs::client::Client; use notionrs_types::prelude::*; #[tokio::main] async fn main() -> Result<(), Box> { let client = Client::new(std::env::var("NOTION_TOKEN").unwrap()); let request = client .get_page_property_item() .page_id("PAGE_ID") .property_id("PROPERTY_ID"); let response = request.send().await?; if let PageProperty::Title(title_property) = response { let title = title_property.to_string(); println!("Title: {}", title); } Ok(()) } ``` -------------------------------- ### Update Notion Block with Rust Source: https://github.com/46ki75/notionrs/blob/main/docs/block/update-block.md Use this method to update a block in Notion. Ensure you have your API key and the block ID. The example demonstrates creating a rich text object and a paragraph block. ```rust use notionrs::{error::Error, Client}; #[tokio::main] async fn main() -> Result<(), Error> { let client = Client::new().secret("API_KEY"); let rich_text = notionrs::object::rich_text::RichText::from("rich text"); let block = notionrs::object::block::Block::Paragraph { paragraph: notionrs::object::block::ParagraphBlock::default() .rich_text(vec![rich_text.clone()]) .blue_background(), }; let request = client.update_block().block_id("BLOCK_ID").block(block); let response = request.send().await?; println!("{:?}", response); Ok(()) } ``` -------------------------------- ### Get Specific User in Rust Source: https://github.com/46ki75/notionrs/blob/main/docs/user/get-user.md Use this method to retrieve details of a specific user by their ID. Ensure you have the `notionrs` crate and `tokio` for async operations. ```rust #[tokio::main] async fn main() -> Result<(), notionrs::error::Error> { let client = notionrs::client::Client::new(); let request = client.get_user().user_id("USER_ID"); let response = request.send().await?; let name = match response { notionrs::object::user::User::Bot(bot) => bot.name, notionrs::object::user::User::Person(person) => person.name, }; match name { None => println!("No name found"), Some(name) => println!("{}", name), } Ok(()) } ``` -------------------------------- ### Update Notion Database with Properties Source: https://github.com/46ki75/notionrs/blob/main/docs/database/update-database.md Use this Rust code to update a Notion database. Ensure you have your NOTION_TOKEN and DATABASE_ID set. This example shows how to modify database properties such as 'Tags', 'Rich Text', and 'URL', as well as the database's title, description, icon, and cover. ```Rust use notionrs::{ database::{ DatabaseMultiSelectProperty, DatabaseProperty, DatabaseRichTextProperty, DatabaseUrlProperty, }, error::Error, Client, Emoji, ExternalFile, File, Icon, RichText, Select, SelectColor, }; #[tokio::main] async fn main() -> Result<(), Error> { let client = Client::new().secret("NOTION_TOKEN"); let mut properties = std::collections::HashMap::new(); let options = vec![ Select::default() .color(SelectColor::Blue) .name("IT") .id("id"), Select::default() .color(SelectColor::Red) .name("SoC") .id("id"), Select::default() .color(SelectColor::Green) .name("TPM") .id("id"), ]; properties.insert( "Tags".to_string(), Some(DatabaseProperty::MultiSelect( DatabaseMultiSelectProperty::default().options(options.clone()), )), ); properties.insert( "Rich Text".to_string(), Some(DatabaseProperty::RichText( DatabaseRichTextProperty::default(), )), ); properties.insert( "URL".to_string(), Some(DatabaseProperty::Url(DatabaseUrlProperty::default())), ); let request = client .update_database() .databse_id("DATABASE_ID") .title(vec![RichText::from("Database Title (changed)")]) .description(vec![RichText::from( "Description of the Database (changed)", )]) .properties(properties) .icon(Icon::Emoji(Emoji::from("🚧"))) .cover(File::External(ExternalFile::from( "https://upload.wikimedia.org/wikipedia/commons/6/62/Tuscankale.jpg", ))); let _response = request.send().await?; Ok(()) } ``` -------------------------------- ### Query a Notion Database in Rust Source: https://github.com/46ki75/notionrs/blob/main/docs/database/query-database.md Demonstrates initializing the client, applying filters and sorts, and iterating through the returned page results. ```rs use notionrs::{database::Sort, error::Error, filter::Filter, page::PageProperty, Client}; #[tokio::main] async fn main() -> Result<(), Error> { let client = Client::new().secret("NOTION_TOKEN"); let filter = Filter::timestamp_past_month(); let sort = Sort::desc("Created Time"); let request = client .query_database() .database_id("DATABASE_ID") .filter(filter) .sorts(vec![sort]); let response = request.send().await?; for page in response.results { let title_property = page .properties .get("Name") .ok_or(Error::Custom("Property not found".to_string()))?; if let PageProperty::Title(title) = title_property { println!("Title: {}", title); } } Ok(()) } ``` -------------------------------- ### Initialize Notion Client with API Key Source: https://context7.com/46ki75/notionrs/llms.txt Initialize the Notion client using your API key. Ensure the NOTION_TOKEN environment variable is set. ```rust use notionrs::Client; #[tokio::main] async fn main() -> Result<(), Box> { let notion_api_key = std::env::var("NOTION_TOKEN").unwrap(); let client = Client::new(notion_api_key); // Client is now ready to make API requests Ok(()) } ``` -------------------------------- ### Create a Database Source: https://context7.com/46ki75/notionrs/llms.txt Creates a new database with a defined schema under a specified parent page. Requires the NOTION_TOKEN environment variable. ```rust use std::collections::HashMap; use notionrs::Error; use notionrs_types::prelude::*; #[tokio::main] async fn main() -> Result<(), Error> { let client = notionrs::Client::new(std::env::var("NOTION_TOKEN").unwrap()); let title = vec![RichText::from("My Database")]; let mut properties = HashMap::new(); properties.insert( "email".to_string(), DataSourceProperty::Email(DataSourceEmailProperty::default()), ); let request = client.create_database().page_id("PAGE_ID").title(title); let _response = request.send().await?; Ok(()) } ``` -------------------------------- ### Create a Database View Source: https://context7.com/46ki75/notionrs/llms.txt Initializes a new view for a database, specifying the view type and data source. ```rust use notionrs::{Client, Error}; use notionrs_types::object::view::ViewType; #[tokio::main] async fn main() -> Result<(), Error> { let client = Client::new(std::env::var("NOTION_TOKEN").unwrap()); let request = client .create_view() .data_source_id("DATA_SOURCE_ID") .name("My Table View") .view_type(ViewType::Table) .database_id("DATABASE_ID"); let response = request.send().await?; println!("{:?}", response); Ok(()) } ``` -------------------------------- ### Create a Page with Properties Source: https://context7.com/46ki75/notionrs/llms.txt Use this to create a new page with specified properties in a database or as a child of another page. Ensure the NOTION_TOKEN environment variable is set. ```rust use notionrs::{Client, Error}; use notionrs_types::prelude::*; #[tokio::main] async fn main() -> Result<(), Error> { let client = Client::new(std::env::var("NOTION_TOKEN").unwrap()); let mut properties = std::collections::HashMap::new(); properties.insert( "Name".to_string(), PageProperty::Title(PageTitleProperty::from("My New Page")), ); properties.insert( "Tags".to_string(), PageProperty::MultiSelect(PageMultiSelectProperty { multi_select: vec![ Select { name: "Important".to_string(), color: Some(SelectColor::Blue), ..Default::default() }, Select { name: "Work".to_string(), color: Some(SelectColor::Green), ..Default::default() }, ], ..Default::default() }), ); let request = client .create_page() .page_id("PARENT_PAGE_ID") .properties(properties); let response = request.send().await?; println!("Created page with id: {}", response.id); Ok(()) } ``` -------------------------------- ### Load Notion Token from Environment Variable Source: https://github.com/46ki75/notionrs/blob/main/notionrs/examples/README.md Initialize the Notion client by loading the API key from the NOTION_TOKEN environment variable. Ensure the .env file is set up correctly. ```ini NOTION_TOKEN=secret_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ``` ```rust let notion_api_key = std::env::var("NOTION_TOKEN").unwrap(); let client = Client::new(notion_api_key); ``` -------------------------------- ### Retrieve a Page with notionrs Source: https://github.com/46ki75/notionrs/blob/main/docs/page/get-page.md Demonstrates initializing the client and fetching page properties by ID. Requires a valid Notion API secret and page ID. ```rust use notionrs::{error::Error, Client}; #[tokio::main] async fn main() -> Result<(), Error> { let client = Client::new().secret("API_KEY"); let request = client.create_page().page_id("PAGE_ID"); let response = request.send().await?; println!("This block's id is {}", response.id); let properties = response.properties; let title = properties .get("Name") .ok_or(Error::Custom("`Name` property not found".to_string()))?; println!("Title: {}", title); Ok(()) } ``` -------------------------------- ### Retrieve Database with Properties Source: https://github.com/46ki75/notionrs/blob/main/docs/database/retrieve-database.md Use this method to retrieve a database and iterate through its properties, specifically demonstrating how to access and print 'Tags' if it's a MultiSelect type. Ensure you have your NOTION_TOKEN and DATABASE_ID set. ```rust use notionrs::{error::Error, Client}; #[tokio::main] async fn main() -> Result<(), Error> { let client = Client::new().secret("NOTION_TOKEN"); let request = client.retrieve_database().database_id("DATABASE_ID"); let response = request.send().await?; let properties = response.properties; let tags_property = properties .get("Tags") .ok_or(Error::Custom("Tags property not found".to_string()))?; if let notionrs::object::database::DatabaseProperty::MultiSelect(tags) = tags_property { for tag in tags.multi_select.options.clone() { println!("Tag: {}", tag.name); } } Ok(()) } ``` -------------------------------- ### Retrieve a Page Property Item Source: https://github.com/46ki75/notionrs/blob/main/docs/page/get-page-property-item.md Demonstrates initializing the client and fetching a specific property by page and property ID. Requires a valid Notion API secret and the corresponding IDs. ```rs use notionrs::{error::Error, page::PageProperty, Client}; #[tokio::main] async fn main() -> Result<(), Error> { let client = Client::new().secret("API_KEY"); let request = client .get_page_property_item() .page_id("PAGE_ID") .property_id("PROPERTY_ID"); let response = request.send().await?; if let PageProperty::Title(title_property) = response { let title = title_property.to_string(); println!("Title: {}", title); } else { return Err(Error::Custom("Property is not a title".to_string())); } Ok(()) } ``` -------------------------------- ### Retrieve a Page Source: https://context7.com/46ki75/notionrs/llms.txt Fetches a page by its ID and allows access to its properties. Requires the NOTION_TOKEN environment variable. ```rust use notionrs::client::Client; #[tokio::main] async fn main() -> Result<(), Box> { let client = Client::new(std::env::var("NOTION_TOKEN").unwrap()); let request = client.create_page().page_id("PAGE_ID"); let response = request.send().await?; println!("Page id: {}", response.id); let properties = response.properties; let title = properties .get("Name") .ok_or("`Name` property not found")?; println!("Title: {}", title); Ok(()) } ``` -------------------------------- ### List Users in Notion Workspace (Rust) Source: https://github.com/46ki75/notionrs/blob/main/docs/user/list-users.md Use this Rust code to fetch users from your Notion workspace. It requires the `tokio` runtime and the `notionrs` crate. The code iterates through the results, extracting and printing the name of each user, distinguishing between bot and person accounts. ```rust #[tokio::main] async fn main() -> Result<(), notionrs::error::Error> { let client = notionrs::client::Client::new(); let mut request = client.list_users(); let response = request.send().await?; for user in response.results { let name = match user { notionrs::object::user::User::Bot(bot) => bot.name, notionrs::object::user::User::Person(person) => person.name, }; match name { None => println!("No name found"), Some(name) => println!("{}", name), } } Ok(()) } ``` -------------------------------- ### Retrieve a Database Source: https://context7.com/46ki75/notionrs/llms.txt Fetch metadata and schema information for a specific data source. ```rust use notionrs::client::Client; #[tokio::main] async fn main() -> Result<(), Box> { let client = Client::new(std::env::var("NOTION_TOKEN").unwrap()); let request = client .retrieve_data_source() .data_source_id("DATA_SOURCE_ID"); let response = request.send().await?; println!("{:?}", response); Ok(()) } ``` -------------------------------- ### Add tokio and notionrs to Cargo.toml Source: https://github.com/46ki75/notionrs/blob/main/docs/introduction/getting-started.md Manually add both tokio with the 'full' feature and notionrs to your Cargo.toml file to set up an async environment. ```toml [dependencies] tokio = { version = "1", features = ["full"] } notionrs = "1" ``` -------------------------------- ### Upload a File to Notion Source: https://context7.com/46ki75/notionrs/llms.txt Initiates the file upload process by creating a record for the file in Notion. ```rust use notionrs::Client; #[tokio::main] async fn main() -> Result<(), notionrs::error::Error> { let client = Client::new(std::env::var("NOTION_TOKEN").unwrap()); // Step 1: Create a file upload let create_response = client .create_file_upload() .filename("document.pdf".to_string()) .content_type("application/pdf".to_string()) .send() .await?; println!("File upload created: {:?}", create_response); // Step 2: Send the file content // Step 3: Complete the upload Ok(()) } ``` -------------------------------- ### Query All Pages with Streaming Source: https://context7.com/46ki75/notionrs/llms.txt Fetch all paginated results from a data source using asynchronous streams. ```rust use futures::TryStreamExt; use notionrs::{Client, PaginateExt}; use notionrs_types::prelude::*; #[tokio::main] async fn main() -> Result<(), Box> { let client = Client::new(std::env::var("NOTION_TOKEN").unwrap()); let filter = Filter::timestamp_past_month(); let sort = Sort::desc("Created Time"); let pages = client .query_data_source() .data_source_id("DATA_SOURCE_ID") .filter(filter) .sorts(vec![sort]) .into_stream() .try_collect::>() .await .unwrap(); for page in pages { println!("{:#?}", page.properties); } Ok(()) } ``` -------------------------------- ### Update a Notion page using notionrs Source: https://github.com/46ki75/notionrs/blob/main/docs/page/update-page.md Demonstrates initializing the client and updating page properties. Requires a valid API key and page ID. ```rs use notionrs::{ error::Error, page::{PageProperty, PageTitleProperty}, Client, }; #[tokio::main] async fn main() -> Result<(), Error> { let client = Client::new().secret("API_KEY"); let mut properties = std::collections::HashMap::new(); properties.insert( "Name".to_string(), PageProperty::Title(PageTitleProperty::from("New Page"), ); let request = client .update_page() .page_id("PAGE_ID") .properties(properties); let response = request.send().await?; println!("This block's id is {}", response.id); Ok(()) } ``` -------------------------------- ### Update a Database Source: https://context7.com/46ki75/notionrs/llms.txt Modify database title, description, icon, cover, and schema properties using the update_database builder. ```rust use notionrs::{Client, Error}; use notionrs_types::prelude::*; #[tokio::main] async fn main() -> Result<(), Error> { let client = Client::new(std::env::var("NOTION_TOKEN").unwrap()); let mut properties = std::collections::HashMap::new(); let options = vec![ Select::default().color(SelectColor::Blue).name("IT").id("id"), Select::default().color(SelectColor::Red).name("SoC").id("id"), Select::default().color(SelectColor::Green).name("TPM").id("id"), ]; properties.insert( "Tags".to_string(), Some(DataSourceProperty::MultiSelect( DataSourceMultiSelectProperty::default().options(options.clone()), )), ); properties.insert( "Rich Text".to_string(), Some(DataSourceProperty::RichText(DataSourceRichTextProperty::default())), ); let request = client .update_database() .database_id("DATABASE_ID") .title(vec![RichText::from("Updated Database Title")]) .description(vec![RichText::from("Updated description")]) .icon(EmojiAndIcon::Emoji(Emoji::from("🚧"))) .cover(File::External(ExternalFile::from( "https://example.com/cover.jpg", ))); let _response = request.send().await?; Ok(()) } ``` -------------------------------- ### Run Mutable Integration Tests for Notionrs Source: https://github.com/46ki75/notionrs/blob/main/notionrs/AGENTS.md Execute mutable integration tests. This requires the NOTION_API_KEY_MUTABLE environment variable to be set. These tests modify Notion data. ```bash cargo test --test integration_test_mutable ``` -------------------------------- ### Handle Webhook Events with Axum Source: https://context7.com/46ki75/notionrs/llms.txt Demonstrates how to verify a Notion webhook signature and deserialize the event payload using Axum. ```rust use axum::{response::IntoResponse, routing::post}; use http::{StatusCode, request::Parts}; use notionrs_webhooks::{WebhookEvent, EventData, PageContentUpdated}; async fn handler(parts: Parts, body: axum::body::Bytes) -> impl IntoResponse { let verification_token: &'static [u8; 5] = b"token"; let maybe_x_notion_signature = parts.headers.get("x-api-signature"); match maybe_x_notion_signature { None => return StatusCode::UNAUTHORIZED.into_response(), Some(x_notion_signature) => { let is_valid = notionrs_webhooks::verify_signature( verification_token, &body, x_notion_signature.as_bytes(), ); if !is_valid { return StatusCode::FORBIDDEN.into_response(); }; let event = serde_json::from_slice::(&body).unwrap(); match event.data { EventData::PageCreated(_) => { // Handle page created StatusCode::OK.into_response() } EventData::PageContentUpdated(PageContentUpdated { parent, updated_blocks }) => { // Handle page content updated StatusCode::OK.into_response() } EventData::DatabaseCreated(_) => { // Handle database created StatusCode::OK.into_response() } EventData::CommentCreated(_) => { // Handle comment created StatusCode::OK.into_response() } _ => StatusCode::OK.into_response(), } } } } #[tokio::main] async fn main() { let router = axum::Router::new().route("/", post(handler)); let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap(); axum::serve(listener, router).await.unwrap(); } ``` -------------------------------- ### Retrieve Notion Token from Secret Store Source: https://github.com/46ki75/notionrs/blob/main/notionrs/examples/README.md Initialize the Notion client by retrieving the secret token from a secret store asynchronously. This method is suitable for more secure token management. ```rust let secret = get_notion_token_from_secret_store().await.unwrap(); let client = notionrs::client::Client::new().secret(secret); ``` -------------------------------- ### Search Notion Workspace Source: https://context7.com/46ki75/notionrs/llms.txt Perform searches for pages and databases, with options to filter by type and sort results. ```rust use notionrs::Client; #[tokio::main] async fn main() -> Result<(), notionrs::error::Error> { let client = Client::new(std::env::var("NOTION_TOKEN").unwrap()); let request = client .search() .query("meeting notes") .sort_timestamp_desc() .page_size(10); let response = request.send().await?; for item in response.results { println!("{:?}", item); } Ok(()) } ``` ```rust use notionrs::Client; #[tokio::main] async fn main() -> Result<(), notionrs::error::Error> { let client = Client::new(std::env::var("NOTION_TOKEN").unwrap()); let request = client .search_database() .query("Projects") .sort_timestamp_asc(); let response = request.send().await?; println!("{:?}", response); Ok(()) } ``` ```rust use notionrs::Client; #[tokio::main] async fn main() -> Result<(), notionrs::error::Error> { let client = Client::new(std::env::var("NOTION_TOKEN").unwrap()); let request = client .search_page() .query("Documentation") .page_size(50); let response = request.send().await?; println!("{:?}", response); Ok(()) } ``` -------------------------------- ### Views API - Create a View Source: https://context7.com/46ki75/notionrs/llms.txt Create a new view for a database with filters and sorts. ```APIDOC ## POST /views ### Description Create a new view for a database with filters and sorts. ### Method POST ### Endpoint /views ### Parameters #### Request Body - **data_source_id** (string) - Required - The ID of the data source (database) for the view. - **name** (string) - Required - The name of the view. - **view_type** (string) - Required - The type of the view (e.g., "table", "board", "calendar", "gallery", "list"). - **database_id** (string) - Required - The ID of the database the view belongs to. ### Request Example ```json { "data_source_id": "DATA_SOURCE_ID", "name": "My Table View", "view_type": "table", "database_id": "DATABASE_ID" } ``` ### Response #### Success Response (200) - **id** (string) - The ID of the created view. - **object** (string) - The object type, should be "view". - **type** (string) - The type of the view. - **created_time** (string) - The timestamp when the view was created. - **last_edited_time** (string) - The timestamp when the view was last edited. - **parent** (object) - Information about the parent of the view. - **properties** (object) - The properties of the view, including filters and sorts. #### Response Example ```json { "id": "view-id", "object": "view", "type": "table", "created_time": "2023-10-27T10:00:00Z", "last_edited_time": "2023-10-27T10:00:00Z", "parent": { "type": "database_id", "database_id": "DATABASE_ID" }, "properties": {} } ``` ``` -------------------------------- ### Retrieve Notion Users Source: https://context7.com/46ki75/notionrs/llms.txt Methods for listing all workspace users, fetching the current bot user, or retrieving a specific user by ID. ```rust use notionrs::Client; #[tokio::main] async fn main() -> Result<(), notionrs::error::Error> { let client = Client::new(std::env::var("NOTION_TOKEN").unwrap()); let request = client.list_users(); let response = request.send().await?; for user in response.results { match user.name { Some(name) => println!("{}", name), None => println!("No name found"), } } Ok(()) } ``` ```rust use notionrs::Client; #[tokio::main] async fn main() -> Result<(), notionrs::error::Error> { let client = Client::new(std::env::var("NOTION_TOKEN").unwrap()); let request = client.get_self(); let response = request.send().await?; match response.name { Some(name) => println!("Bot name: {}", name), None => println!("No name found"), } Ok(()) } ``` ```rust use notionrs::Client; #[tokio::main] async fn main() -> Result<(), notionrs::error::Error> { let client = Client::new(std::env::var("NOTION_TOKEN").unwrap()); let request = client.get_user().user_id("USER_ID"); let response = request.send().await?; match response.name { Some(name) => println!("{}", name), None => println!("No name found"), } Ok(()) } ``` -------------------------------- ### Run Readonly Integration Tests for Notionrs Source: https://github.com/46ki75/notionrs/blob/main/notionrs/AGENTS.md Execute read-only integration tests. This requires the NOTION_API_KEY_READONLY environment variable to be set. These tests only read Notion data. ```bash cargo test --test integration_test_readonly ``` -------------------------------- ### Convert Page to Markdown Source: https://context7.com/46ki75/notionrs/llms.txt Converts the content of a Notion page or block into markdown format. ```rust use notionrs::Client; #[tokio::main] async fn main() -> Result<(), notionrs::error::Error> { let client = Client::new(std::env::var("NOTION_TOKEN").unwrap()); let markdown_lines = client.to_markdown("PAGE_OR_BLOCK_ID").await?; for line in markdown_lines { println!("{}", line); } Ok(()) } ``` -------------------------------- ### Webhooks - Verify Webhook Signatures Source: https://context7.com/46ki75/notionrs/llms.txt Verify incoming webhook requests from Notion. ```APIDOC ## POST /webhooks/verify ### Description Verify incoming webhook requests from Notion to ensure their authenticity. ### Method POST ### Endpoint /webhooks/verify ### Parameters #### Request Body - **verification_token** (bytes) - Required - The verification token provided by Notion. - **body** (bytes) - Required - The raw body of the incoming webhook request. - **signature_header** (bytes) - Required - The value of the `Notion-Signature` header from the incoming request. ### Request Example (This is a conceptual example as the actual implementation involves byte arrays and headers) ``` // Assuming you have the raw request body, signature header, and your verification token let is_valid = verify_signature(VERIFICATION_TOKEN, REQUEST_BODY, SIGNATURE_HEADER); ``` ### Response #### Success Response (Boolean) - **true** if the signature is valid, **false** otherwise. #### Response Example ``` true ``` ``` -------------------------------- ### Add Notionrs Dependencies to Cargo.toml Source: https://context7.com/46ki75/notionrs/llms.txt Add the necessary notionrs crates and their dependencies to your project's Cargo.toml file for integration. ```toml [dependencies] notionrs = { version = "0" } notionrs_types = { version = "0" } tokio = { version = "1", features = ["full"] } serde = { version = "1", features = ["derive"] } ``` -------------------------------- ### Move a Page Source: https://context7.com/46ki75/notionrs/llms.txt Relocates a page to a different parent page or data source. Ensure the NOTION_TOKEN is configured. ```rust use notionrs::{Client, Error}; #[tokio::main] async fn main() -> Result<(), Error> { let client = Client::new(std::env::var("NOTION_TOKEN").unwrap()); // Move to another page let request = client .move_page() .source_page_id("SOURCE_PAGE_ID") .destination_page_id("DESTINATION_PAGE_ID"); let response = request.send().await?; println!("Moved page: {}", response.id); Ok(()) } ``` -------------------------------- ### Run Integration Tests with Cargo Source: https://github.com/46ki75/notionrs/blob/main/docs/contribute/integration-test.md Execute only the integration tests by specifying the 'integration_tests' module. This command ensures that only tests designed to interact with the Notion API are run. ```bash cargo test integration_tests ``` -------------------------------- ### Running Unit Tests in Rust Source: https://github.com/46ki75/notionrs/blob/main/docs/contribute/unit-test.md Execute unit tests specifically within `unit_tests` modules using the `cargo test` command with the module name. ```bash cargo test unit_tests ``` -------------------------------- ### Hard-code Notion Token Source: https://github.com/46ki75/notionrs/blob/main/notionrs/examples/README.md Initialize the Notion client by directly providing the secret token using the .secret() method. This is not recommended for production environments. ```rust let client = notionrs::client::Client::new().secret("secret_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); ``` -------------------------------- ### Query a Data Source with Typed Results Source: https://context7.com/46ki75/notionrs/llms.txt Query a database and deserialize the page properties into a custom struct. ```rust use notionrs::Client; use notionrs_types::prelude::*; use serde::{Deserialize, Serialize}; #[tokio::main] async fn main() -> Result<(), Box> { let client = Client::new(std::env::var("NOTION_TOKEN").unwrap()); let filter = Filter::timestamp_past_month(); let sort = Sort::desc("Created Time"); let request = client .query_data_source() .data_source_id("DATA_SOURCE_ID") .filter(filter) .sorts(vec![sort]); #[derive(Debug, Clone, Serialize, Deserialize)] struct MyProperties { #[serde(rename = "My Title")] pub title: PageTitleProperty, } let response = request.send::().await?; for page in response.results { println!("{}", page.properties.title.to_string()); } Ok(()) } ``` -------------------------------- ### Create a Comment in Notion Source: https://context7.com/46ki75/notionrs/llms.txt Adds a comment to a specific page using either rich text or markdown formatting. ```rust use notionrs::{Client, Error}; use notionrs_types::prelude::*; #[tokio::main] async fn main() -> Result<(), Error> { let client = Client::new(std::env::var("NOTION_TOKEN").unwrap()); // Using rich text let request = client .create_comment() .page_id("PAGE_ID") .rich_text(vec![RichText::from("This is a comment")]); let response = request.send().await?; println!("{:?}", response); // Or using markdown let request = client .create_comment() .page_id("PAGE_ID") .markdown("**Bold** and _italic_ comment".to_string()); let response = request.send().await?; println!("{:?}", response); Ok(()) } ``` -------------------------------- ### Update Page Properties Source: https://context7.com/46ki75/notionrs/llms.txt Modifies existing page properties, such as the title or tags. Ensure the NOTION_TOKEN is set. ```rust use notionrs::{Client, Error}; use notionrs_types::prelude::*; #[tokio::main] async fn main() -> Result<(), Error> { let client = Client::new(std::env::var("NOTION_TOKEN").unwrap()); let mut properties = std::collections::HashMap::new(); properties.insert( "Name".to_string(), PageProperty::Title(PageTitleProperty::from("Updated Page Title")), ); let request = client .update_page() .page_id("PAGE_ID") .properties(properties); let response = request.send().await?; println!("Updated page: {}", response.id); Ok(()) } ``` -------------------------------- ### POST /search Source: https://context7.com/46ki75/notionrs/llms.txt Search for pages and databases across the workspace using various filters. ```APIDOC ## POST /search ### Description Search for pages and databases by title across the workspace. ### Method POST ### Endpoint /search ### Request Body - **query** (string) - Optional - The search query string. - **sort** (object) - Optional - Sorting criteria. - **page_size** (integer) - Optional - Number of results to return. ``` -------------------------------- ### Cargo.toml Dependencies for Notion API Source: https://github.com/46ki75/notionrs/blob/main/README.md Declare the necessary dependencies for using the notionrs library and Tokio for asynchronous operations. ```toml notionrs = { version = "0" } notionrs_types = { version = "0" } tokio = { version = "1", features = ["full"] } serde = { version = "1", features = ["derive"] } ``` -------------------------------- ### Convert to Markdown - Convert Page to Markdown Source: https://context7.com/46ki75/notionrs/llms.txt Experimental feature to convert Notion page content to markdown. ```APIDOC ## GET /pages/{id}/to_markdown ### Description Experimental feature to convert Notion page content to markdown. ### Method GET ### Endpoint /pages/{id}/to_markdown ### Parameters #### Path Parameters - **id** (string) - Required - The ID of the Notion page or block to convert. ### Response #### Success Response (200) - **markdown_lines** (array of strings) - An array where each element is a line of markdown. #### Response Example ```json [ "# My Notion Page", "", "This is a paragraph.", "**This is bold text.**" ] ``` ``` -------------------------------- ### Query Notion Data Source with Filters and Sorting Source: https://github.com/46ki75/notionrs/blob/main/README.md An asynchronous Rust function to query a Notion data source. It requires the NOTION_API_KEY environment variable and a valid DATA_SOURCE_ID. The query is filtered for entries from the past month and sorted by creation time in descending order. ```rust use notionrs::Client; use notionrs_types::prelude::*; use serde::{Deserialize, Serialize}; #[tokio::main] async fn main() -> Result<(), Box> { let notion_api_key = std::env::var("NOTION_API_KEY").unwrap(); let client = Client::new(notion_api_key); let filter = Filter::timestamp_past_month(); let sort = Sort::desc("Created Time"); let request = client .query_data_source() .data_source_id("DATA_SOURCE_ID") .filter(filter) .sorts(vec![sort]); #[derive(Debug, Clone, Serialize, Deserialize)] struct MyProperties { #[serde(rename = "My Title")] pub title: PageTitleProperty, } let response = request.send::().await?; for page in response.results { println!("{}", page.properties.title.to_string()); } Ok(()) } ``` -------------------------------- ### File Uploads API - Upload a File Source: https://context7.com/46ki75/notionrs/llms.txt Create and upload a file to Notion. ```APIDOC ## POST /files/upload ### Description Create and upload a file to Notion. This is a multi-step process. ### Method POST ### Endpoint /files/upload ### Parameters #### Request Body (Step 1: Create File Upload) - **filename** (string) - Required - The name of the file to upload. - **content_type** (string) - Required - The MIME type of the file. ### Request Example (Step 1) ```json { "filename": "document.pdf", "content_type": "application/pdf" } ``` ### Response (Step 1) #### Success Response (200) - **id** (string) - The ID of the file upload. - **url** (string) - The URL to which the file content should be uploaded. - **filename** (string) - The name of the file. - **content_type** (string) - The MIME type of the file. #### Response Example (Step 1) ```json { "id": "file-upload-id", "url": "https://upload.notion.so/path/to/upload", "filename": "document.pdf", "content_type": "application/pdf" } ``` **Note:** After creating the file upload, you will need to send the file content to the provided URL using a PUT request, and then potentially complete the upload process through another API call (details depend on the specific library implementation). ``` -------------------------------- ### Configure Notion Token for Integration Tests Source: https://github.com/46ki75/notionrs/blob/main/docs/contribute/integration-test.md Set the NOTION_TOKEN in a .env file in the project root. This token is required for authentication when running integration tests that send actual requests to the Notion API. ```ini NOTION_TOKEN=secret_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ```