Site cover image

Site icon imageおかしんワークス

ビジネステクノロジーエンジニア @okash1n のブログです

Postmanのススメ Notion APIを添えて

皆さん、PowerAutomateやらGASやらでWebAPIを使って自動化したりしますよね?その際に各サービスのAPIドキュメントを見ながらcURLコマンドを使って返ってくるJSONをjqで整形したりするのでは無いでしょうか?

例えばこんなかんじ

$ curl "https://api.open-meteo.com/v1/forecast?latitude=34.40&longitude=132.45&daily=weathercode&timezone=Asia%2FTokyo" | jq .

{
  "latitude": 34.4,
  "longitude": 132.4375,
  "generationtime_ms": 0.21600723266601562,
  "utc_offset_seconds": 32400,
  "timezone": "Asia/Tokyo",
  "timezone_abbreviation": "JST",
  "elevation": 8,
  "daily_units": {
    "time": "iso8601",
    "weathercode": "wmo code"
  },
  "daily": {
    "time": [
      "2023-04-22",
      "2023-04-23",
      "2023-04-24",
      "2023-04-25",
      "2023-04-26",
      "2023-04-27",
      "2023-04-28"
    ],
    "weathercode": [
      0,
      1,
      2,
      63,
      61,
      3,
      61
    ]
  }
}

これはOpen-Meteoという無料のお天気APIを叩いているのですが、ここから込み入った処理を行うためにはAPIのドキュメントを読んで、繰り返し叩いては整形して、そこからやっとコードに落とし込むことになると思います。

ましてや、我々が日常業務で使うWebAPIにはTokenによる認証が必要である場合がほとんどで、cURLのリクエストを作るのも一苦労です。

そういった作業を便利にしてくれるPostmanというサービスを紹介します

Notion APIを素で叩いてみる

いかにPostmanが便利かを分かってもらう為には、まず素で叩いてみた時との差をお見せする必要があるので、まずは素でNotionAPIを叩いてみます。

事前準備

  • Notionのアカウントを作っておきます
  • なんか適当なデータベースのページを作っておきます
  • jqをインストールしておきましょう
    • brew install jq

API Tokenを取得

Notionにログインした状態で以下のページを開きます

Image in a image block

インターナルで「新しいインテグレーションを作成」。

Image in a image block

適当な名前をつけて「送信」します

Scopeの設定

機能をひらきます

Image in a image block

トークンがどんなスコープを保有するかはこのページで設定します。今回はデフォルトのままでOK。

Image in a image block

シークレットをコピーしておく

表示してコピーしておきます

Image in a image block

適当なデータベースにインテグレーションを追加

データベースのページ右上のメニューから「コネクトの追加」を行い、先程作ったインテグレーションを追加しておきます。

Image in a image block

データベースIDを取得しておく

URLから取得できます。NotionのURLはnotion.so/{org-name}/{databaseID}?v={viewID} の構成になっていますので、データベースのIDをどこかに控えておきましょう

Image in a image block

今回は以下のデータベースを利用します

cURLでDBを操作してみる

NotionAPIのリファレンスを見ながら操作していきます

データベースそのものの情報を取得(GET)

まずは先程作ったデータベースをそのまま読み取ってみます

上記のリファレンスのSampleリクエストをベースに、トークンとデータベースだけ変更して実行します。

$ NOTION_API_KEY="secret_*************" ## トークンを変数に入れておく
$ curl 'https://api.notion.com/v1/databases/6a2d3cff1246491f95a6473996feec26' \
  -H 'Authorization: Bearer '"$NOTION_API_KEY"'' \
  -H 'Notion-Version: 2022-06-28'

{"object":"database","id":"6a2d3cff-1246-491f-95a6-473996feec26","cover":null,"icon":null,"created_time":"2023-04-21T21:31:00.000Z","created_by":{"object":"user","id":"9f06cee1-6b89-44e5-82d7-dd14560d610a"},"last_edited_by":{"object":"user","id":"9f06cee1-6b89-44e5-82d7-dd14560d610a"},"last_edited_time":"2023-04-21T21:37:00.000Z","title":[{"type":"text","text":{"content":"テストDB","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"テストDB","href":null}],"description":[],"is_inline":false,"properties":{"価格(小)":{"id":"hQIE","name":"価格(小)","type":"number","number":{"format":"yen"}},"店名":{"id":"title","name":"店名","type":"title","title":{}}},"parent":{"type":"workspace","workspace":true},"url":"https://www.notion.so/6a2d3cff1246491f95a6473996feec26","archived":false}%

ちょっとわかりにくいのでプロパティのみ取得し、整形します。

$ curl 'https://api.notion.com/v1/databases/6a2d3cff1246491f95a6473996feec26' \
  -H 'Authorization: Bearer '"$NOTION_API_KEY"'' \
  -H 'Notion-Version: 2022-06-28' \
  | jq '.properties'

{
  "価格(小)": {
    "id": "hQIE",
    "name": "価格(小)",
    "type": "number",
    "number": {
      "format": "yen"
    }
  },
  "店名": {
    "id": "title",
    "name": "店名",
    "type": "title",
    "title": {}
  }
}

このエンドポイント v1/databases/{databeseID} では、データベースそのものの情報しか取れません。

データベースの中身を取得(POST)

v1/databases/{databaseID}/queryに対してリクエストを投げると、データベースの個別のプロパティ(カラム)の値を取得できます。

curl -X POST 'https://api.notion.com/v1/databases/6a2d3cff1246491f95a6473996feec26/query' \
  -H 'Authorization: Bearer '"$NOTION_API_KEY"'' \
  -H 'Notion-Version: 2022-06-28' \
  -H "Content-Type: application/json" \
  | jq ' .results | .[] | {"name": .properties."店名".title[].text.content, "price": .properties."価格(小)".number}'

{
  "name": "小岩店",
  "price": 850
}
{
  "name": "横浜関内店",
  "price": 830
}

"filter" を使うことでNotionのフィルタのように特定の値だけ取ってくることもできます。

試しに「価格(小)」が850円以上のものだけ取得します

そのフィルターの条件は以下のとおりです。

{
  "filter": {
    "property": "価格(小)",
    "number": {
      "greater_than_or_equal_to": 850
    }
  }
}

これを—data で渡して、最後にjq します。

curl -X POST 'https://api.notion.com/v1/databases/6a2d3cff1246491f95a6473996feec26/query' \
  -H 'Authorization: Bearer '"$NOTION_API_KEY"'' \
  -H 'Notion-Version: 2022-06-28' \
  -H "Content-Type: application/json" \
--data '{
  "filter": {
    "property": "価格(小)",
    "number": {
      "greater_than_or_equal_to": 850
    }
  }
}' \
  | jq ' .results | .[] | {"name": .properties."店名".title[].text.content, "price": .properties."価格(小)".number}'

{
  "name": "小岩店",
  "price": 850
}
💡
filterを書くのがめんどくさすぎて正直jq で全部書いた方がマシマシです
データベースを更新(PATCH)

データベースそのものの名前を更新してみます

curl --location --request PATCH 'https://api.notion.com/v1/databases/6a2d3cff1246491f95a6473996feec26' \
--header 'Authorization: Bearer '"$NOTION_API_KEY"'' \
--header 'Content-Type: application/json' \
--header 'Notion-Version: 2022-06-28' \
--data '{
    "title": [
        {
            "text": {
                "content": "ラーメンチェーン店舗DB"
            }
        }
    ]
}'
Image in a image block

テストDBから「ラーメンチェーン店舗DB」に名前が変わりました。

次に、店舗を1つ増やします

データベースの行(ページ)を追加(POST)

Notionのデータベースの行の追加のエンドポイントはv1/databasesではなくv1/pagesです。Notionのデータベースの各行は開いて記事を書くことが出来ますよね?つまりページなのです。

💡
偉そうに書いてますが、実は30分以上ハマりました笑
curl 'https://api.notion.com/v1/pages' \
  -H 'Authorization: Bearer '"$NOTION_API_KEY"'' \
  -H "Content-Type: application/json" \
  -H "Notion-Version: 2022-06-28" \
  --data '{
	"parent": { "database_id": "6a2d3cff1246491f95a6473996feec26" },
	"properties": {
		"店名": {
			"title": [
				{
					"text": {
						"content": "八王子野猿街道店2"
					}
				}
			]
		},
		"価格(小)": { "number": 850 }
	}
}'

新しい店舗が追加されました。

Image in a image block

Notion APIをPostmanで叩いてみる

事前準備

まずは、以下のホームページからGoogleログインでアカウント作成しておきましょう

データベースを更新(PATCH)

cURLではv1/databases/{databaseID}/queryに対して以下のようなリクエストを投げると、データベースの個別のプロパティ(カラム)の値を取得できましたね。

curl --location --request PATCH 'https://api.notion.com/v1/databases/6a2d3cff1246491f95a6473996feec26' \
--header 'Authorization: Bearer '"$NOTION_API_KEY"'' \
--header 'Content-Type: application/json' \
--header 'Notion-Version: 2022-06-28' \
--data '{
    "title": [
        {
            "text": {
                "content": "ラーメンチェーン店舗DB"
            }
        }
    ]
}'

Postmanの場合は上部のタブから新しいリクエストを作成できます。エンドポイントのURLを入力し、リクエストタイプを「PATCH」にします

Image in a image block

次にAuthorizationタブでタイプをBearer Tokenに変更し、自身のTokenを右側に入力しておきます

Image in a image block

次にHeadersタブで、Notion-Versionのヘッダーを追加します

Image in a image block

Bodyタブで、rawを選択してJSONを入力し、最後に「Send」

Image in a image block

このとおりちゃんとアップデートされました

Image in a image block

🚫 Arrow icon of a page linkPost not found

ただ、これだとあまり便利さを感じないと思います。

コレクションを使ってみる

Image in a image block

実は、色んなWebサービスにおいて、Postman用のリクエストを集めたコレクションが用意されているのです。個人がメンテしているものもあれば、Notionのように提供企業がメンテしているものもあります。

GitHubのようにForkして使うことが出来、自分用にカスタマイズすることもできます。

またSecretなどはコレクションやワークスペースの環境全体に変数として設定することが出来るので、簡単にリクエストを作ることが出来るようになります。

Image in a image block

Documentをすぐ見れる

Image in a image block

APIのドキュメントもPostmanのコレクションからすぐに閲覧可能です。

あとがき

他にも色んな便利な機能があるので是非使ってみてください。

類似のサービス

VSCodeにはPostmanのコレクションをインポートして使えるThunder Clientという拡張機能があり、こちらも非常に便利です。

APIDOGというサービスもまだベータ版ですが、「Postmanよりパワフル」をうたっており、こちらも結構良かったです。