「Notionのワークスペース内におけるページ更新履歴一覧」情報をNotion APIを使ってどこまで取れるか試してみる

2021.07.31

データアナリティクス事業本部 サービスソリューション部 サービス開発チームのしんや です。サービスソリューション部では、現在CSA(カスタマーストーリーアナリティクス)を含めたデータ分析に関わる自社サービス群を開発・展開しています。

最近、データアナリティクス事業本部でもドキュメント管理ツールとして『Notion』の導入・コンテンツのNotionへの移行を進めています。

管理者としての立場で日々ページの作成や整理等を行っているのですが、「ワークスペース全体におけるページの更新履歴情報が欲しいな」とふと思うようになりました。「今現在、どんなページが更新作成されているのか気になるので確認したい」というところからの発案です。

ですが現状、Notionではそのような機能は無さそうでした。(ページ単体での更新履歴については対応している)

一方、最近利用出来るようになったNotion APIではページに関する情報を拾ってくることが出来るようです。当エントリではこのNotion APIを使って、やりたいこと(ワークスペースにおけるページの更新履歴一覧の情報を引っ張ってくる)が出来るかどうか、試してみたいと思います。

目次

 

欲しい情報とイメージ

イメージとしてはこんな感じです。ページの更新履歴が新しい順から一定件数、ページ名称(及びページのURL)が一覧で取れれば要望は満たせる感じですね。

 

Notion API利用のための準備

 

APIトークンの取得

まずはAPIトークンの取得から行います。下記のページにアクセスし、[New Integration]を押下。

設定の名称、対象となるワークスペースを指定して[Submit]を押下。

[Secrets]欄にトークンが発行されているので、ボタン押下でトークン情報を控えておいてください。

 

Notion APIのページアクセスを許可

Notion APIで「ページ情報」を収集・取得出来るようにするには、ワークスペースのページ配下に対して『APIのアクセスを許可する』設定が必要となります。(最初、この手順が必要なことが分からなくて暫く時間を潰してしまいました...)

上記ページの手順『Add integrations to pages』に沿う形でアクセス許可を行っていきます。今回はワークスペース直下にあるページそれぞれに対して、画面右上の[Share]→[Invite]を選択し、

上記手順で追加したAPI連携を指定。

権限を選択(今回のケースに関しては[Can Edit]のみ選択可能となるようです)し、[Invite]を押下。これでNotion APIがページ情報にアクセス出来る様になりました。

 

検証結果

Notion APIにおける「検索」のAPI仕様は以下をご参照ください。

$NOTION_API_KEYの部分を取得したAPIトークンに置き換える形で、ページ情報の検索を行います。

  • timestampで指定出来るのは最終更新日(last_edited_time)だけのようです
  • 降順ソートしたかったので順序(direction)の指定はdescendingとしました
  • APIリファレンスでは検索文字列(query)の指定がありましたが、今回は絞り込みは不要のためこの部分の指定は除去しました
curl -X POST 'https://api.notion.com/v1/search' \
  -H 'Authorization: Bearer '"$NOTION_API_KEY"''
  -H 'Content-Type: application/json' \
  -H "Notion-Version: 2021-05-13" \
  --data '{
    "sort":{
      "direction":"descending",
      "timestamp":"last_edited_time"
    }
  }'

API実行をしてみます。絞り込み・整形無しの結果出力についてはここでは割愛しますが、行数的には100件が上限となっているようです。今回やりたいことも「直近更新があったページの情報」なのでこれでも特に問題ないでしょう。

% curl  -X POST 'https://api.notion.com/v1/search' \
  -H "Notion-Version: 2021-05-13" \
  -H 'Authorization: Bearer '"secret_XXXXxxxxXXXXxxxxXXXXxxxxXXXXxxxxXXXXxxxxXXX"'' \
  -H 'Content-Type: application/json' \
  --data '{
    "sort":{
      "direction":"descending",
      "timestamp":"last_edited_time"
    }
  }' | jq -c '.results[]'  \
  | wc
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 99604    0 99511  100    93  33641     31  0:00:03  0:00:02  0:00:01 33661
     100     570   99413

ちなみに取得結果の加工・整形にはjqを用います。予め導入を済ませておいてください。

% jq --version
jq-1.6

さぁここからは取得した結果をjqでバチーンと良い感じに整形して終わりだ!......と思ったのですが、出力された結果を見てみるとページの種類に拠って今回取得したい部分の情報(主にページタイトル)の場所が異なるらしいということが判明。一旦内容を展開し、どのような種類の情報があるかを見てみることにしました。

 

ワークスペース直下にあるページ(最上位階層ページ)

まずはこちらから。上記手順でも言及したような「ワークスペース直下にあるページ=Notionにおける最上位階層に位置しているページ」を取得する際の設定です。Notion APIでデータを取得した後のjq操作に関する部分でその振り分け・データの抽出を行っています。(以降紹介する内容はこの部分が若干異なる形になっている)

% curl  -X POST 'https://api.notion.com/v1/search' \
  -H "Notion-Version: 2021-05-13" \
  -H 'Authorization: Bearer '"secret_XXXXxxxxXXXXxxxxXXXXxxxxXXXXxxxxXXXXxxxxXXX"'' \
  -H 'Content-Type: application/json' \
  --data '{
    "sort":{
      "direction":"descending",
      "timestamp":"last_edited_time"
    }
  }' | \
jq -c '.results[] | select (.parent.type == "workspace")' | \
jq -c '{ object: .object, last_edited_time: .last_edited_time, id: .id, page_title: .properties.title.title[0].plain_text  } '

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 99638    0 99545  100    93  24670     23  0:00:04  0:00:04 --:--:-- 24693
{"object":"page","last_edited_time":"2021-07-31T09:45:00.000Z","id":"e047c0e6-c535-43fd-b737-xxxxxxxxxxxx","page_title":"XXXXXXXXXX"}
{"object":"page","last_edited_time":"2021-07-31T09:45:00.000Z","id":"edec4593-d73a-4697-bf7b-yyyyyyyyyyyy","page_title":"YYYYYYYYYY"}
{"object":"page","last_edited_time":"2021-07-31T09:45:00.000Z","id":"55ec2daf-d0cc-4f90-b82b-zzzzzzzzzzzz","page_title":"ZZZZZZZZZZ"}
:

 

ワークスペース直下以外の階層にあるページ

次いでこちらもページに関する情報です。最上位階層に位置しているページではないページに関する情報を取得する際の設定です。jqでselect操作を行う時の抽出条件と、その後にデータを整形する際のpage_titleの値を取ってくる際のプロパティ指定値が異なっています。

% curl  -X POST 'https://api.notion.com/v1/search' \
  -H "Notion-Version: 2021-05-13" \
  -H 'Authorization: Bearer '"secret_XXXXxxxxXXXXxxxxXXXXxxxxXXXXxxxxXXXXxxxxXXX"'' \
  -H 'Content-Type: application/json' \
  --data '{
    "sort":{
      "direction":"descending",
      "timestamp":"last_edited_time"
    }
  }' |\
jq -c '.results[] | select (.object == "page" and .parent.type == "page_id")' | \
jq -c '{ object: .object, last_edited_time: .last_edited_time, id: .id, page_title: .properties.title.title[0].plain_text } '
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 99035    0 98942  100    93  33460     31  0:00:03  0:00:02  0:00:01 33480
{"object":"page","last_edited_time":"2021-07-31T12:55:00.000Z","id":"112ef956-6a35-4c50-9e3d-aaaaaaaaaaaa","page_title":"AAAAAAAAAAAAAAA"}
{"object":"page","last_edited_time":"2021-07-31T11:21:00.000Z","id":"7e116be6-e95a-484b-ba72-bbbbbbbbbbbb","page_title":"BBBBBBBBBBBBBBB"}
{"object":"page","last_edited_time":"2021-07-31T11:21:00.000Z","id":"64fce97c-151f-437f-8bed-cccccccccccc","page_title":"CCCCCCCCCCCCCCC"}
:

 

テーブルに関する情報

最後に紹介するのがテーブル情報。ページ配下に/tableコマンドでインラインテーブルを作成したものを引っ張ってくることを想定しています。

% curl  -X POST 'https://api.notion.com/v1/search' \
  -H "Notion-Version: 2021-05-13" \
  -H 'Authorization: Bearer '"secret_XXXXxxxxXXXXxxxxXXXXxxxxXXXXxxxxXXXXxxxxXXX"'' \
  -H 'Content-Type: application/json' \
  --data '{
    "sort":{
      "direction":"descending",
      "timestamp":"last_edited_time"
    }
  }' | \
jq -c '.results[] | select (.object == "database")' | \
jq -c '{ object: .object, last_edited_time: .last_edited_time, id: .id, page_title: .title[0].plain_text } '

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 99035    0 98942  100    93  38083     35  0:00:02  0:00:02 --:--:-- 38105
{"object":"database","last_edited_time":"2021-07-31T12:55:00.000Z","id":"1131ba7c-90fd-44ae-9a82-dddddddddddd","page_title":"DDDDDDDDDDDDDDDDDDDD"}
{"object":"database","last_edited_time":"2021-07-29T05:20:00.000Z","id":"adb15881-484a-4357-ba17-eeeeeeeeeeee","page_title":"EEEEEEEEEEEEEEEEEEEE"}
{"object":"database","last_edited_time":"2021-07-28T08:00:00.000Z","id":"97f8087a-bf42-4e0f-8bb0-ffffffffffff","page_title":"FFFFFFFFFFFFFFFFFFFF"}

ちなみにテーブル関連情報としては下記の条件で抽出出来るものもあったのですが(恐らくはテーブルの1行を意味するデータと思われる)、これに関してはページタイトルに相当する文字情報としてどれを抽出・指定するか悩ましい部分があったので抽出対象外としました。後日何らかの形でうまい策が見つかれば考えてみたいと思います。

 curl  -X POST 'https://api.notion.com/v1/search' \
  -H "Notion-Version: 2021-05-13" \
  -H 'Authorization: Bearer '"secret_XXXXxxxxXXXXxxxxXXXXxxxxXXXXxxxxXXXXxxxxXXX"'' \
  -H 'Content-Type: application/json' \
  --data '{
    "sort":{
      "direction":"descending",
      "timestamp":"last_edited_time"
    }
  }' | \
  jq -c '.results[] | select (.parent.type == "database_id")'

まとめ

という訳で、Notion APIで「ワークスペース全体のページ更新履歴情報を収集する」件でどこまで取れるかを検証してみた内容の紹介でした。

当エントリはここで締めますが、続きとして下記のような手順を踏まえることでより使い勝手の良い情報が生成出来そうです。時間を見つけて対応出来たらこの辺についても追記しておきたいなと思います。

  • 検証した3種のデータをマージ&タイムスタンプでソートして一覧表示させる
  • タイムスタンプ情報のタイムゾーンを日本のものに変換する
  • ページID情報からアクセス可能なURLに変換する(idの情報からハイフンを除き、ドメイン名の後ろに付ける形でアクセス可能なURL形式となる)