その際に知ったことを書きます。APIは、2021/5/14にパブリックベータとして公開されました。https://developers.notion.com/ベータなので色々微妙だったりもするのですが、個人的には思ったよりも使えるなと思いました。ドキュメントもまだ情報量は少ないですが、ツボはおさえてる感じです。僕は公式ドキュメント見ながら進めましたが、途中で詰むことはありませんでした。Referenceの2ページはめちゃくちゃ見ました。苦言を呈するなら、今提供しているAPIの全体像とか、利用サンプルとかの説明は弱いかなと感じました。非公式API(読み飛ばし可)Notionは長らくAPI公開をしてくれませんでしたが、そうはいってもAPIでNotionのデータを取得したい需要は根強くありました。以前notion-blogの紹介記事も書きましたが、https://zenn.dev/st43/articles/9a714916c50b80こちらで使っているのが非公式APIです。いうエンドポイントを叩いています。https://github.com/ijjk/notion-blog/blob/main/src/lib/notion/server-constants.js↑notion-blogのこの部分ですね。ブラウザの開発者コンソールで内部APIの挙動を推測して叩いてた、という事情のようです。APIが完成したら、外部からのアクセスを封じる方向に動くのではないかと思います。APIに加えて、この非公式APIの内容も紹介できたらと思います。APIでは取れないけど、非公式APIだと取れる要素がいくつか存在します。要件次第では、敢えて非公式APIを使うという選択肢もあるのかなと思います。APIの設定https://www.notion.so/my-integrations↑ここにNotionアカウントを使ってログインします。「Integration」というのが、Notion上のあるDBをAPIから操作可能にする単位になるので、新規作成します。Intergrationで追加します。ここでアクセス権与えるところはなんか変な感じがしますが、面白いなとも思いました。Notionユーザーに権限与えるのと同じように、APIからのアクセスも管理するんだなーと。以上、2つの作業が終わったら、APIが叩ける状態になります。Integrationsからシークレットキーが見られるので、curlコマンド使って色々叩いてみましょう。手順の詳細は公式ドキュメントをご確認ください。https://developers.notion.com/docs認証まわり僕自身はNotionを個人で使っており、チームで使ったことがないので読み飛ばしていましたが、最近はNotionを会社で使っているところもあると聞きます。publicなIntegrationをつくると、OAuthで外部からのアクセスを受け入れることもできるようです。僕は試していないところなので、もしご興味があれば下記を参照してください。僕はAPIを個人ブログのために使おうと思っていたので、まずAPIでNotionのページに書いてある文章をとりあえず取ってみたい、と思いました。初見だと、そこまでたどり着くのがちょっと大変でした。手書きで恐縮ですが、あるアカウントのNotionのデータ構造はざっくり下記のようになっています。この図が示しているのは、典型的なNotionの利用例です。データベースがあって、そこに複数のページが紐づいています。1つのページはヘッダー部とコンテンツ部にわかれていて、コンテンツはブロックの配列として管理されています。僕の場合、「Blog」みたいな名前のデータベースをつくって、その要素として「記事A」「記事B」みたいにページをつくりました。ルート要素としてつくったページは、親となるデータベースは持ちません。親子関係は柔軟に作成できるので、データベースの子要素としてデータベースもつくれますし、そこら辺に制約はありません。上記の構成なので、APIもデータベース・ページ・ブロックでそれぞれわかれています。pageは、ブロックを返してくれません。Notionのドキュメントでは、GETのことをRetrieveと書いています。childrenを使いましょう。ブロックを取得するサンプルAPIから返却されるデータのイメージをつかために、curlコマンド叩いたときのレスポンスを載せます。Notionのページに「test」とだけ書いて、そのページに対してブロックの取得を試みました。2021-05-13"リファレンスを見ると、block_idを指定しろと書かれていて面食らいましたが、ページIDでいいみたいです。false}なんかたかが一単語に対して、ずいぶん大袈裟にネストしているように見えますが、これはNotionのブロックがプレインテキストだけでなく、テキストの書式を持っていたり、Markdownチックな要素情報を持っていたり、場合によってはURLリンクだったりNotion内の別ページへのリンクだったり、様々なフォーマットを持っているためです。今回は一ブロックのページに対してAPI叩きましたが、実際のページだとブロック数分来ます。開発者側で上手いこと扱えば、現状でもとりあえずテキストベースなら(後述)なんとか使えると思いますが、ブログのコンテンツホスティングとして使うユースケースなら、Markdown形式でまるっと返してくれる、とかが欲しいなと思ってしまいました。APIでできること一覧2021/07/13現在の情報です。(最新のチェンジログ)APIが提供している機能をまず書きます。検索結果をfilter/sortした結果を取得するデータベースIDを確認するだいたいのAPIの操作は、認証のためのNOTION_API_KEY、そして操作対象のIDを指定することになります。NOTION_API_KEYというのは、NotionのIntegrationページから取得する、secret_xxxというキーです。データベースIDは、なんとURLを見て取得することになります。API.https://developers.notion.com/docs/working-with-databases#adding-pages-to-a-databaseこれなんかすごいワイルドですよね。ちなみにIDは「2f26ee68-df30-4251-aad4-8ddc420cba3d」みたいな形式で来ますが、ハイフンがあってもなくてもイケました。ページIDを確認するページIDもURLから取得できます。ルートページでなければ、ページの親となるデータベースの要素の中にIDが入っているので、そっちを使うことになると思います。https://developers.notion.com/docs/working-with-page-content#creating-a-page-with-contentドキュメントでは、「お試しでURLからページID取るのはいいけど、本番環境でユーザーに聞いたりするのはどうかと思うよ」と書かれています。ブロックIDブロックにもそれぞれIDが振られています。ブロックIDはさすがにAPI経由じゃないと取得できませんが、ブロック操作のAPIにはブロックIDが必須となります。ブロック操作のAPIはページIDでも叩けます。任意のページのブロック要素を取得したい際は、ページIDを使うことになります。ページIDになってるのかな?」と最初思ったんですが、ブロックIDはブロックIDで別に振られていました。ドキュメントを読んだ限りでは、ページはブロックでもあるみたいです。禅問答みたいですが、どうもそういう設計思想のようです。触ったときはちょっと戸惑うと思います。APIのSDKJavaScriptでSDKが提供されています。他の言語はありません。試すならcurlコマンド、SDK使うならJSの二択のみです。https://github.com/makenotion/notion-sdk-jsJSのSDKはOSSとして公開されています。process.env.NOTION_TOKEN,})こんな感じで入れましょう。Referenceの右列にサンプルコードが載っているので、それが一番わかりいいと思います。以下、制約を書いていきます。更新系の処理ができないできること一覧の中で、ページの新規追加/更新とブロック要素の追加と書きましたが、逆に言うとこれ以外の更新系の処理はできません。基本的にCRUD操作の中の、CREATE/UPDATEがほとんどできない状況ですね。データベースは新規作成できないので、Notionアプリからやる必要があります。ページについてはそこそこCRUD操作がそろっている印象です。ブロック操作ができないので、ページのプロパティだけいじれても......って感じはありますよね。ブロックは新規要素を追加(append)することはできるんですが、既存のブロックを更新することはできません。今のままだと使い道は限られるかなーという感じです。テキスト以外のブロックが取れないこの制約が一番キツいですね。"unsupported"で返ってきます。サポートされてるタイプは下記の通りです。"paragraph""heading_1""heading_2""heading_3""bulleted_list_item""numbered_list_item""to_do""toggle""child_page"画像、コードブロックなどがunsupportedで返ってくるので、辛いですね。テキストの書式は取れるので、Notion上でつけていたリッチテキストの装飾の情報は取得できます。(個人的にはあんまりリッチテキスト使わないタイプなので、要らない情報ですが)レートに秒間3回までの制限があるこちらでリクエスト制限について議論がありました。https://zenn.dev/catnose99/articles/ab3afcb4338cbe現在は秒間3リクエストで制限があるみたいです。これはあくまでベータ版なので、正式公開のときは料金プランに応じて制限をかける予定とのこと。429エラーが返ってくるそうです。planshttps://developers.notion.com/reference/errors#rate-limits(2021/10/20追記)「そんなにヘビーに連打しないんで食らわないだろう」と本音では思ってたんですが、食いました。こんなエラーが返ってきます。'/articles'}ブロックにサイズ制限があるそんなに引っかからないと思うんですが、ブロックのサイズ制限があります。https://developers.notion.com/reference/errors#size-limits2,000字/blockなので、よほどギチギチに詰めない限り引っかからないかな、と思います。URLも1,000字/blockなので、長めに感じます。Retrieveは100要素までの上限があるデータベース/ページ/ブロックのGET、ユーザー一覧やクエリ検索のAPI全部なんですが、一度のAPIリクエストで返す要素は100までです。「え、じゃあ100超えたらどうすんの?」と思いましたが、has_moreというフラグがあるので、これがtrueだったら、next_cursorに指定されたidをstart_cursorに詰めて叩いてください、という仕様になっています。https://developers.notion.com/reference/paginationこっちの要素は普通に使っていればそのうちどこかで超えると思うので、ページネーションを実装する必要があります。ブロック要素は超えやすいと思います。僕の場合、昔書いたブログ記事をNotionに50個持ってきたんですが、そのうち3つで100ブロック以上の記事がありました。データベースの要素は基本的にcreated_time順で返るNotionアプリ上でブログ記事のデータベースがあるんですが、アプリ上で順番を入れかえても、APIからのレスポンスの順番は変わりません。API叩いたところ、どうもcreated_timeが新しい順に返しているようです。最新の要素が最初に返ってくる、という仕様です。Notionは仕様として、created_timeをユーザーが編集する機能がありません。https://twitter.com/NotionHQ/status/1116453128428118016?s=20したがって、ブログ記事のデータベースをきちんと運用すれば問題はありませんが、たとえば2015年に書いた記事を突然個人ブログにインポートしたくなったときに困ります。本当の意味での作成日は2015年ですが、Notion上のcreated_timeは2021年になってしまいます。https://developers.notion.com/reference/post-database-query#post-database-query-sortデータベースのAPIでsort条件が指定できるので、こちらでやるのがいいんだと思います。created_time順で受けるだけ受けて、クライアントサイドでsortする方法もあります。time」を入れるようにしています。APIの説明は終わりなんですが、現状だと、非公式APIを使うともっと情報が取れます。https://www.notion.so/api/v3/loadUserContentトークンを取る手段は昔書いた記事を見ていただければと思います。このAPI叩くと、ユーザーアカウントに紐づく情報が一覧で返ってきます。整形してコピペしようと思いましたが、長すぎるのでやめました。Notionアプリを開いたときのトップページで表示してるデータがたぶん全部取得できてるんだと思います。お気に入りに入れてるページ/DBのリストや、ルートにあるページ/DBのリストも入っています。ページ/DBのプロパティ情報も入っています。ここからIDを参照するか、URLを見るとページIDが取れるので、下記のエンドポイントを叩きます。https://www.notion.so/api/v3/loadPageChunkこれのレスポンスが、こんなデータ構造になっております。}}色々調べると、非公式APIも上限100要素制限ができてるらしく、ページネーションが必要っぽいのは同じようです。APIのブロック要素がテキスト関連しか返せないのに対して、非公式APIは全種類(たぶん)返せます。https://github.com/ijjk/notion-blog/blob/106d82ca3fe479e773fe8d6caa558c920e45915b/src/pages/blog/[slug].tsx非公式APIなので、もちろんドキュメントはないのですが、notion-blogの実装を参考にしてブロックのtypeを察するに、pagedividertextimagevideoembedheadersub_headersub_sub_headerbookmarkcodequotecallouttweetequationがとれるはずです。(H3要素がsub_sub_headerになってるのはベンチャー特有の雑な感じして好きです)画像の置き場とかどうするんだろうなと思ってましたが、たぶん非公式APIはurlごともらってるみたいですねまとめまとめます。Developerバッジを贈って著者を応援しようバッジを受け取った著者にはZennから現金やAmazonギフト券が還元されます。APIで画像がサポートされたり、ページの削除が可能になったりなどの変化がありました。2021/11/16すごく興味深い内容でした。notionってurlのクエリパラメーターなどの値をページ内で展開して、ユーザーごとの個人ページを表示するようなことはできないのでしょうか?上記の内容はこれらのAPIでも実現できないような気がしていて気になりました。2021/11/16notionってurlのクエリパラメーターなどの値をページ内で展開して、ユーザーごとの個人ページを表示するようなことはできないのでしょうか?クエリ受けるのはムリだと思います。作成した個人ページをユーザーに返すみたいな流れで実現するしかないですかね。2021/11/16いやーやはりそうなりますよね。API叩いてユーザーごとに新規ページ作る方法。ユーザーが増えるとそれに比例してページ数も増えてしまうのが難点ですね。APIのSDK更新系の処理ができないテキスト以外のブロックが取れないレートに秒間3回までの制限があるブロックにサイズ制限があるRetrieveは100要素までの上限があるデータベースの要素は基本的にcreated_time順で返る非公式APIのレスポンス(読み飛ばし可)まとめZennエンジニアのための情報共有コミュニティAboutZennについて運営会社お知らせ・リリースGuides使い方Publicationよくある質問LinksTwitterGitHubメディアキットLegal利用規約プライバシーポリシ。