go-notion is a minimal Go client library for Notion's v1 API. Check the usage or examples to see how to access Notion's v1 API.
NB: Notion's v1 API is still in beta; this integration will change as they update it.
go get github.com/oyekanmiayo/go-notion/notion/version1
HTTP requests to Notion's API must contain a bearer token in the Authorization
header to be successful. Currently,
Notion allows two types of integrations: Internal and Public. Getting the bearer token is different for each case.
When you create an internal integration on Notion's developer portal, you are given something called an "Internal Integration Token" - this is the bearer token. All you need to do is simply copy it out and store it as an environment variable (preferred) or use it directly in your code.
NB: Internal Integration Token, Bearer Token and Access Token mean the same things here.
import (
notion "github.com/oyekanmiayo/go-notion/notion/version1"
"net/http"
"os"
)
func main() {
accessToken := os.Getenv("NOTION_BEARER_TOKEN")
// Notion Client
client := notion.NewClient(http.DefaultClient, accessToken)
}
This integration receives bearer tokens each time a user completes the OAuth flow. Basically, this is in 3 steps:
- The client requests authorization from a user
- Notion calls a callback url (a.k.a
redirect_uri
) withstate
andcode
as query params - The client exchanges the code for a token
import (
"flag"
"fmt"
"golang.org/x/oauth2"
"log"
"os"
"net/http"
)
func main() {
flags := flag.NewFlagSet("notion-example", flag.ExitOnError)
clientID := flags.String("client-id", "", "Client ID")
redirectURL := flags.String("url", "", "Redirect url")
err := flags.Parse(os.Args[1:])
if err != nil {
log.Fatalf("error: %v", err)
}
c := oauth2.Config{
ClientID: *clientID,
ClientSecret: "",
Endpoint: oauth2.Endpoint{
AuthURL: "https://api.notion.com/v1/oauth/authorize",
TokenURL: "https://api.notion.com/v1/oauth/token",
},
RedirectURL: *redirectURL,
}
client := notion.AuthClient(http.DefaultClient)
// Generate the authorization url
authURL := client.Auth.AuthorizationURL(&c, "")
fmt.Println(authURL)
// The authorization url should be sent back to the client as a redirect
// The user will see an option to give the integration access to their workspace
// If the user approves the request, notion will call the call the callback url (a.k.a `redirect_uri`) with `state` and `code` as query params
// Use the code here to get an access token that can now be used with go-notion's client
resp, _ := client.Auth.AccessToken(&c, *code)
fmt.Println(resp)
client := notion.NewClient(http.DefaultClient, resp.AcessToken)
}
The clientID
and clientSecret
in the snippet above can be found on the developer portal:
Read more about the Database endpoints here.
This retrieves a Notion database based on a specified ID. Read more here.
client := notion.NewClient(http.DefaultClient, *accessToken)
// Retrieve DB
db, _, err := client.Databases.RetrieveDatabase(databaseID)
if err != nil {
fmt.Printf("Err %v\n", err)
}
See full code example here.
This gets a list of Pages contained in a database, filtered and ordered according to the filter conditions and sort criteria provided in the request. Filters can single filters or compound filters. Read more here.
client := notion.NewClient(http.DefaultClient, *accessToken)
// Query DB with SingleFilter
params := ¬ion.QueryDatabaseBodyParams{
Filter: ¬ion.SingleFilter{
Property: "Tags",
MultiSelect: ¬ion.MultiSelectCondition{
Contains: "Tag1",
},
},
}
resp, _, err := client.Databases.QueryDatabase(*databaseID, params)
if err != nil {
fmt.Printf("Err %v\n", err)
}
See full code example here - it also contains a compound filter example :)
More than one database can be shared with a Notion integration. This endpoint lists all the databases shared with an authenticated integration. Read more here.
client := notion.NewClient(http.DefaultClient, *accessToken)
// List all DBs in a workspace
params := ¬ion.ListDatabasesQueryParams{
PageSize: 20,
}
resp, _, err := client.Databases.ListDatabases(params)
if err != nil {
fmt.Printf("Err %v\n", err)
}
See full code example here.
Read more about Page endpoints here.
This retrieves a Notion page based on a specified ID. Read more here.
client := notion.NewClient(http.DefaultClient, *accessToken)
// Retrieve a page using its pageID
db, _, err := client.Pages.RetrievePage(*pageID)
if err != nil {
fmt.Printf("Err %v\n", err)
}
See full code example here.
Pages in Notion can be created within a database or within another page. This endpoint creates a page as a child of the parent (database or page) specified. Read more here.
client := notion.NewClient(http.DefaultClient, *accessToken)
params := ¬ion.CreatePageBodyParams{
Parent: ¬ion.DatabaseParent{
DatabaseID: *databaseID,
},
Properties: map[string]notion.PageProperty{
"Name": {
Title: []notion.RichText{
{
Text: ¬ion.Text{
Content: "Creating Page Sample",
},
},
},
},
"Tags": {
MultiSelect: []notion.MultiSelectPropertyOpts{
{
Name: "Tag1",
},
{
Name: "Tag3",
},
},
},
"Recommended": {
Checkbox: true,
},
},
}
resp, _, err := client.Pages.CreatePage(params)
if err != nil {
fmt.Printf("Err %v\n", err)
}
The example above creates a page within a database. The body of the request is determined by the structure of the database. See full code example here along with an example to create a page within another page.
Updates page property values for the specified page. Properties that are not set via the "properties" parameter will remain unchanged. Read more here.
client := notion.NewClient(http.DefaultClient, *accessToken)
// Update the title of a page
params := ¬ion.UpdatePagePropertiesBodyParams{
// first keys are the names or ids of the properties :)
// id for title is "title"
// See examples here: https://developers.notion.com/reference/page#page-property-value
Properties: map[string]notion.PageProperty{
"Name": {
Title: []notion.RichText{
{
Type: "text",
Text: ¬ion.Text{
Content: "Jamaican Cuisines III",
},
},
},
},
"Recommended": {
Checkbox: true,
},
},
}
resp, _, err := client.Pages.UpdatePageProperties(*pageID, params)
if err != nil {
fmt.Printf("Err %v\n", err)
}
See full code example here.
A block object represents content within Notion. Blocks can be text, lists, media, and more. A page is a type of block, too! Read more about Block endpoints here.
Returns a paginated array of child block objects contained in the block using the ID specified. In order to receive a complete representation of a block, you may need to recursively retrieve the block children of child blocks. Read more here.
client := notion.NewClient(http.DefaultClient, *accessToken)
// Retrieve the block children for a block
params := ¬ion.RetrieveBlockChildrenParams{}
db, _, err := client.Blocks.RetrieveBlockChildren(*blockID, params)
if err != nil {
fmt.Printf("Err %v\n", err)
}
See full code example here.
Creates and appends new children blocks to the block using the ID specified. Returns the Block object which contains the new children. Read more here.
client := notion.NewClient(http.DefaultClient, *accessToken)
// Append block children (Header Two & Paragraph) to a block
params := ¬ion.AppendBlockChildrenBodyParams{
Children: []notion.Block{
{
Object: "block",
Type: "heading_2",
HeadingTwo: ¬ion.HeadingTwo{
Text: []notion.RichText{
{
Type: "text",
Text: ¬ion.Text{
Content: "Header Two Test",
},
},
},
},
},
{
Object: "block",
Type: "paragraph",
Paragraph: ¬ion.Paragraph{
Text: []notion.RichText{
{
Type: "text",
Text: ¬ion.Text{
Content: "Paragraph Test",
},
},
},
},
},
},
}
db, _, err := client.Blocks.AppendBlockChildren(*blockID, params)
if err != nil {
fmt.Printf("Err %v\n", err)
}
See full code example here.
The User object represents a user in a Notion workspace. Users include guests, full workspace members, and bots. Read more about User endpoints here.
This retrieves a Notion user based on a specified ID. Read more here.
client := notion.NewClient(http.DefaultClient, *accessToken)
// Retrieve a user by userID
db, _, err := client.Users.RetrieveUser(*userID)
if err != nil {
fmt.Printf("Err %v\n", err)
}
See full code example here.
Returns a paginated list of users for the workspace. Read more here.
client := notion.NewClient(http.DefaultClient, *accessToken)
// List all users in workspace
params := ¬ion.ListUsersQueryParams{
PageSize: 20,
}
db, _, err := client.Users.ListUsers(params)
if err != nil {
fmt.Printf("Err %v\n", err)
}
See full code example here.
Searches all pages and child pages that are shared with the integration and returns a list of databases and pages which
have titles that contain the query
parameter. Other parameters like sort
and filter
also affect the output. Read
more about it here.
client := notion.NewClient(http.DefaultClient, *accessToken)
// Search the workspace and return pages that have titles containing "Yurts"
// The result should be sorted in descending order of "last_edited_time"
params := ¬ion.SearchBodyParams{
Query: "Yurts",
Sort: ¬ion.Sort{
Direction: "descending",
Timestamp: "last_edited_time",
},
Filter: ¬ion.SearchFilter{
Value: "page",
Property: "object",
},
}
db, _, err := client.Search.Search(params)
if err != nil {
fmt.Printf("Err %v\n", err)
}
See full code example here.
- Code Contributions won't be accepted until Notion's v1 API is out of beta
- Open an issue if you find a bug or missing integration