こんにちは。3年目のアドベントカレンダー参戦になります。株式会社ピー・アール・オーです。
これまでに引き続き、今年も各自が興味のある分野について各々に書く方針で進めさせていただきます。
これまでと同様に、とりとめのない内容になるとは思いますが、ご査収いただければ幸いです。
Notion APIが使えるようになりました(半年前に)
昨年のアドベントカレンダーでNotionに関する記事をいくつか挙げたんですが、その際にはまだ公式のAPIがなくて、Notionに可能性を感じながらも利用にあたってはやや遠回りをせざるを得ないのが残念に感じていました。
ですが、2021/5/11にかねてからその開発が噂されていたAPIがPublic Betaとして公開されました。日本語の情報としてもこのころにAPI試してみた系の記事が多く登場していましたので、Notion使いの方たちはきっと目にされていたことと思います。
本記事執筆時点でもまだPublic Betaのままのようですが、後述するようにNotion APIは日々機能追加が行われており、公開当初に書かれた内容とは状況が異なっているものや新たに追加された機能が散見されましたので、あらためて現時点のAPIの状況について私の視点から試してまとめてみたというのが本記事の趣旨となります。
はじめてみる
integrationの作成
利用開始の手順については公開当初と大きくは変わっていないようです。まずはNotionにログインした状態で、https://www.notion.so/my-integrationsにアクセスします。
New Integrationを選択して情報を入力します。
IntegrationはPublicを選ぶとOAuth2.0ベースのアクセストークンを利用したアクセスとなるようです。
今回はお試しなのでInternalで。
submitするとSecretsが表示されます。これは後程APIを叩く際に必要なのでコピっておきましょう。
Notionアプリ側の設定
Integrationが追加されると、NotionのSetting & Members > Integrationsにも作成したものが表示されるようになります。
あとは、実際にAPIを利用したいPageでShare⇒Inviteを選び、作成したIntegrationを選択すれば準備完了です。
Inviteした結果。他のユーザーに対してShareするのと同じような感じですね。
APIを叩いてみる
page
ではさっそくCurlで叩いてみましょう。叩くにあたって必要な情報はBarer TokenとPageIDになります。
Barer TokenはIntegration設定時に表示されたSecretsになります。PageIDはページの「share」から表示されるウインドウで、Copy linkすることで得ることができます。
実際に得られるURLは↓のような感じですが、PageIDは末端のハッシュ値が相当するようです。
ちなみに下のハッシュ値は改ざんしています。本記事内の他のハッシュ値も値変えていますので実際の値と異なります。
curl 'https://api.notion.com/v1/blocks/{PageID}/children?page_size=100' \
-H 'Authorization: Bearer '"{Secret}"'' \
-H "Notion-Version: 2021-08-16"
Notion-VersionというのはAPIのリリース日で管理されているようですね。最新はここで確認できるようです。
https://developers.notion.com/reference/versioning
取得結果は以下のようになります。
{
"object": "list",
"results": [
{
"object": "block",
"id": "96a12436-676f-4ec0-a3ba-8de4g4hbdb4a",
"created_time": "2020-10-17T05:36:00.000Z",
"last_edited_time": "2020-10-17T05:36:00.000Z",
"has_children": false,
"archived": false,
"type": "paragraph",
"paragraph": {
"text": [
{
"type": "text",
"text": {
"content": "👋 Welcome to Notion!",
"link": null
},
"annotations": {
"bold": false,
"italic": false,
"strikethrough": false,
"underline": false,
"code": false,
"color": "default"
},
"plain_text": "👋 Welcome to Notion!",
"href": null
}
]
}
},
{
"object": "block",
"id": "8ef56ed9-1ad0-424d-a887-b3674cb6a506",
"created_time": "2020-10-17T05:36:00.000Z",
"last_edited_time": "2020-10-17T05:36:00.000Z",
"has_children": false,
"archived": false,
"type": "paragraph",
"paragraph": {
"text": []
}
},
(以下省略)
blockってのはNotionのページ内における行を表しているようです。上のJSONに対応するのはこの部分ですね。
画像やCodeブロックなどはどうでしょうか?いくつかのAPI試してみた系の記事では取得ができないという話だったので気になっていましたが・・・
最新のAPIではどちらも問題なく取得できるようになったようです。
database
さて、普通のPageについてはblocksで返されるJSONは大変納得がいくものでしたが、notionの売りであるDatabaseに対して実施するとどうなるのでしょう?
Notionで管理しているDatabaseとして、私のお弁当レシピリストがありました。
極めてプライベートな情報のため気恥ずかしいですが、ためしにそれを対象にしてみましょう。
上記Pageに対してまずはblockを取得してみます。
{
"object": "list",
"results": [
{
"object": "block",
"id": "a98e0e05-d915-406a-a987-bdf775a8be24",
"created_time": "2021-10-22T09:58:00.000Z",
"last_edited_time": "2021-11-25T03:39:00.000Z",
"has_children": false,
"archived": false,
"type": "child_database",
"child_database": {
"title": ""
}
},
{
"object": "block",
"id": "bb126f57-3078-4d80-ac10-b9edd0bb6134",
"created_time": "2021-10-22T10:00:00.000Z",
"last_edited_time": "2021-10-22T10:00:00.000Z",
"has_children": false,
"archived": false,
"type": "paragraph",
"paragraph": {
"text": []
}
}
],
"next_cursor": null,
"has_more": false
}
まあ案の定ですが、DatabaseはPage内コンテンツ(block)とは管理が別なんですね。
しかもdatabaseを配置しているPage内情報からはそのDatabaseのIDが引けないようです。仕方ないのでPageと同様にDatabaseからCopy libkでIDを取得します。
GETメソッドのdatabasesを叩いてみます。
curl 'https://api.notion.com/v1/databases/{databaseID}' \
-H 'Authorization: Bearer '"{secret}"'' \
-H "Notion-Version: 2021-08-16"
あれ?意外に簡素な内容しか取れないですね・・・
{
"object": "database",
"id": "a98e3e05-d913-305a-a951-bdf867a8fg35",
"cover": null,
"icon": null,
"created_time": "2021-10-22T09:58:00.000Z",
"last_edited_time": "2021-11-25T03:39:00.000Z",
"title": [],
"properties": {
"Date": {
"id": "sN_~",
"name": "Date",
"type": "date",
"date": {}
},
"Name": {
"id": "title",
"name": "Name",
"type": "title",
"title": {}
}
},
"parent": {
"type": "page_id",
"page_id": "cbb47508-34da-48ca-a0d2-fd496013109a"
},
"url": "https://www.notion.so/a99e5e05d915406ab875bdf775a8be24"
}
どうやらdatabaseの中身を参照したいときには単なるGETではだめで、POSTメソッドであるqueryで検索条件を渡さないとダメみたいですね。
https://developers.notion.com/reference/post-database-query
と、いうわけで改めて・・・
curl -X POST 'https://api.notion.com/v1/databases/{databaseID}/query' \
-H 'Authorization: Bearer '"{secret}"'' \
-H 'Notion-Version: 2021-08-16' \
-H "Content-Type: application/json" \
--data '{
"filter": {
"or": [
{
"property": "Date",
"date": {
"after": "2021-11-01"
}
}
]
},
"sorts": [
{
"property": "Date",
"direction": "ascending"
}
]
}'
おお、取得できました!
{
"object": "list",
"results": [
{
"object": "page",
"id": "666f2743-08a5-4e03-7966-145b6cbcd0c1",
"created_time": "2021-11-05T07:30:00.000Z",
"last_edited_time": "2021-11-05T23:58:00.000Z",
"cover": null,
"icon": null,
"parent": {
"type": "database_id",
"database_id": "a98e1e05-d914-405a-a951-bdf886a8fg25"
},
"archived": false,
"properties": {
"Date": {
"id": "sN_~",
"type": "date",
"date": {
"start": "2021-11-08",
"end": null
}
},
"Name": {
"id": "title",
"type": "title",
"title": [
{
"type": "text",
"text": {
"content": "紅しょうがと大葉の豚こま天ぷらと卵の天ぷら",
"link": null
},
"annotations": {
"bold": false,
"italic": false,
"strikethrough": false,
"underline": false,
"code": false,
"color": "default"
},
"plain_text": "紅しょうがと大葉の豚こま天ぷらと卵の天ぷら",
"href": null
}
]
}
},
"url": "https://www.notion.so/666f274408a74e058293234b6aabf9c1"
},
{
"object": "page",
"id": "2db12d01-447d-47fd-83bc-23793bc4ad90",
"created_time": "2021-11-05T22:34:00.000Z",
"last_edited_time": "2021-11-09T00:50:00.000Z",
"cover": null,
"icon": null,
"parent": {
"type": "database_id",
"database_id": "a98e1e05-d914-405a-a951-bdf886a8fg25"
},
"archived": false,
"properties": {
"Date": {
"id": "sN_~",
"type": "date",
"date": {
"start": "2021-11-09",
"end": null
}
},
"Name": {
"id": "title",
"type": "title",
"title": [
{
"type": "text",
"text": {
"content": "昆布だし塩サバ",
"link": null
},
"annotations": {
"bold": false,
"italic": false,
"strikethrough": false,
"underline": false,
"code": false,
"color": "default"
},
"plain_text": "昆布だし塩サバ",
"href": null
}
]
}
},
"url": "https://www.notion.so/2db13d01556556fe82bc14243bc3ad90"
},
(省略)
ちなみに、dateはISO8601書式が使えるようです。したがって日本時間で検索したいときには、
curl -X POST 'https://api.notion.com/v1/databases/a98e0e05d915406aa951bdf775a8be24/query' \
-H 'Authorization: Bearer '"secret_4P4vCb0DLbqXbrbQWDhH3RC14fuR5xXP2014vNssfsK"'' \
-H 'Notion-Version: 2021-08-16' \
-H "Content-Type: application/json" \
--data '{
"filter": {
"or": [
{
"property": "Date",
"date": {
"after": "2021-11-01T00:00:00+09:00"
}
}
]
},
"sorts": [
{
"property": "Date",
"direction": "ascending"
}
]
}'
こんな感じの指定ができるってわけですね。この機能はつい最近(先月?)追加されたようで、Notion APIは今ももりもり開発されているようです。
計算式を含むDatabase
もう少し複雑なdatabaseに対してやってみます。
notionは簡単な数式を設定できるのですが、数式を設定したもう少し複雑なパターンはどうでしょうか?
↓こんなDatabseを対象にしてみます。
実行結果
"object": "list",
"results": [
{
"object": "page",
"id": "d2e6af07-df0e-43e3-a1f6-320542f1d321",
"created_time": "2021-11-25T10:07:00.000Z",
"last_edited_time": "2021-11-25T10:07:00.000Z",
"cover": null,
"icon": {
"type": "emoji",
"emoji": "📃"
},
"parent": {
"type": "database_id",
"database_id": "9e0e27f8-e435-4c32-76e5-c75173b0ec08"
},
"archived": false,
"properties": {
"Type": {
"id": "R%3DsB",
"type": "multi_select",
"multi_select": [
{
"id": "4c816f99-0e87-508a-8cb1-89d28577c8fa",
"name": "Task",
"color": "green"
}
]
},
"Related to サブタスク (Column)": {
"id": "UYws",
"type": "relation",
"relation": [
{
"id": "f126c964-de6e-48cc-b972-c16b569a3b31"
},
{
"id": "e756b1b9-96ef-45e8-a765-2698b0a08466"
},
{
"id": "fa54136a-fa45-3189-beb1-53d51c84bd45"
},
{
"id": "5ec97606-954f-3654-8850-1ceebb2c688e"
}
]
},
"進捗バー": {
"id": "buAP",
"type": "formula",
"formula": {
"type": "string",
"string": "▓▓▓▓▓▓▓▓▓▓ 100%"
}
},
"Assign": {
"id": "e_VQ",
"type": "people",
"people": [
{
"object": "user",
"id": "7a87b8fc-e99f-4c19-9cb3-26f6c61109b",
"name": "matuzaki",
"avatar_url": "https://lh3.googleusercontent.com/-7W9F5KJAcnI/AAAAAAAAAAI/AAAAAAAAAAA/AMZvvbmSP7V82UpKTlMeDQ2IhEHx5KOe0Q/photo.jpg",
"type": "person",
"person": {
"email": "xxxxxxxxxx"
}
}
]
},
"各タスク状況": {
"id": "lwBb",
"type": "rollup",
"rollup": {
"type": "number",
"number": 1,
"function": "percent_checked"
}
},
"Date": {
"id": "zANe",
"type": "date",
"date": {
"start": "2021-11-05",
"end": "2021-11-09"
}
},
"Status": {
"id": "zHyE",
"type": "select",
"select": {
"id": "0ee89e54-1ae4-3987-ae3b-a975073d4439",
"name": "Pending",
"color": "blue"
}
},
"Name": {
"id": "title",
"type": "title",
"title": [
{
"type": "text",
"text": {
"content": "設計書フォーマット整理",
"link": null
},
"annotations": {
"bold": false,
"italic": false,
"strikethrough": false,
"underline": false,
"code": false,
"color": "default"
},
"plain_text": "設計書フォーマット整理",
"href": null
}
]
}
},
"url": "https://www.notion.so/d2e6af07df0e31c3a1e7320542f1d253"
},
(省略)
プロパティで、数式にしている個所は演算結果のみ取得できるようですね。
サンプルで進捗バーはformulaで定義しているんですが、結果のバーのみが取得できました。
その他はおおむね情報としては取得できてそうな感じです。
利用できるAPI一覧
notion公式に上がってるAPIは執筆時点で以下となります。
まだ必要最低限といった感じですが、一通りのCRUD操作的なものは出来そうです。
ちなみに、Retrieve~ってのはGETなので取得メソッドですね。
Category | API | Method |
---|---|---|
Database object | Query a database | POST |
Create a database | POST | |
Update database | PATCH | |
Retreive a database | GET | |
List database(deprecated) | GET | |
Page object | Retrieve a page | GET |
Create a page | POST | |
Update page | PATCH | |
Archive a Page(delated) | ||
Retrieve a page property item | GET | |
Block object | Retrieve a block | GET |
Update a block | PATCH | |
Retrieve block children | GET | |
Append block children | PATCH | |
Delete a block | DELETE | |
User object | Retrieve a user | GET |
List all users | GET | |
Retrieve your token's bot user | GET | |
Search | Search |
所感
notion API、まだまだ発展途上ながら、APIが出た当初に比べてかなり拡充されきていると言えそうです。
まだまだ開発も続いているようなので、まだ機能がもの足りないというようなときはchange logをみてみるといいかもしれません。
1week程度の周期で結構新機能がリリースされてたりします。
本記事が皆様のnotion活用に寄与できれば幸いです。