はじめに
hkob の雑記録の第503回目(連続76日目)は、最近サボっていた Developer Docs の ChangeLogs を紹介します。3つほど貯めているので、1日一つずつ紹介していきます。
ChangeLog の内容
5/11 に以下のように ChangeLog が更新されていました。

新しい Query meeting notes エンドポイント(
POST /v1/blocks/meeting_notes/query)は、Integration のユーザーに紐づく AI Meeting Notes を返す。filter / sort / limit は任意で指定できる。attendeesエイリアスはサーバ側で正規化されるため、フィルタが往復(round-trip)しても整合する。
agent_id親タイプエージェントに親子付け(parented)されたページおよびブロックは、拒否や書き換えではなく、
parentを{ "type": "agent_id", "agent_id": "..." }としてシリアライズするようになった。親タイプの一覧は Parent object を参照。SDK 対応:
@notionhq/clientのv5.21.0で、notion.blocks.meetingNotes.query()とagent_id親バリアントの型付きサポートが追加された。
API Reference の確認
せっかくなので、API Reference も確認してみます。部分ごとに引用し、コメントを追記していきます。
Overview
このエンドポイントは、meeting notes を block objects(
objectがblock、typeがmeeting_notes)として一覧で返す。対象は、(ワークスペース内で)Integration に紐づくユーザーがそのブロックの attendee として含まれている meeting notes である。レスポンスに含まれるもの:
results: meeting note blocks(meeting_notesペイロードに title / status / children tab IDs(例: summary / notes / transcription)を含む。存在する場合は、カレンダー・録画に関するメタデータも含む)has_more: 現在の filter / sort /limitに対して、このレスポンス以降にも追加の行があるかフィールド選択: フィールドの部分取得パラメータはない。
results[]の各要素は完全な block object である。必要なフィールド(例:meeting_notes、timestamp、people)をレスポンスから読み取る。返す meeting notes の絞り込みはfilterを使う。利用可能なプロパティ名と演算子は、このエンドポイントの request body schema に定義される。このエンドポイントはカーソルベースページネーションを使わない。
start_cursorやnext_cursorは存在しない。結果セットの調整にはfilter/sort/limit(最大値は後述)を用いる。
Notion 内ではライブラリで Notion AI を一覧で確認できます。この仕組みはデータベースではないですが、Notion API からも検索し、一覧を取得できるようになりました。ただ、カーソルベースのページネーションには対応しないようなので、ある程度フィルタリングして抽出する必要がありそうです。
Request body
リクエストボディは JSON オブジェクトで、全フィールドが任意。
Field Description filter単一の property フィルタ、または filters配列を持つ combinator("and"/"or")。詳細は Filtering を参照。sortsort の順序付きリスト。各要素は propertyとdirection(ascending/descending)を持つ。先に書いたものが優先。limit返す meeting notes の最大数。1〜50 の 整数。省略時はサーバが 50 を用いる。 Default
{}Sort and cap results
{ "sort": [ { "property": "last_edited_time", "direction": "descending" } ], "limit": 10 }
Request body に入れられるのは、filter, sort, limit の三つだけのようです。先ほど示したようにカーソル指定がないので、うまく filter で絞り込む必要があります。
Filtering
filter は次のいずれか:
- Property filter(単一条件) —
filterフィールド直下に、propertyとfilter(operator と任意のvalue)を持つオブジェクトを置く。- Combinator —
operator("and"または"or")とfilters配列を持つオブジェクト。filtersの各要素は別の property filter、または(ネストは 1 階層まで)内側のfiltersが property フィルタのみからなる combinator(正確な形は API リファレンスの request schema を参照)。テキスト/日付/person のフィルタにおけるプロパティ名、演算子、
value形状は request body schema に完全に定義される。無効なプロパティや不正なフィルタは 400 validation error となる。
フィルタは Property filter と Combinator で包まれた Property filter で構成されます。この下にサンプルが掲載されています。
Filter examples
以下 3 パターンは、単一 property filter、
andcombinator、orcombinator をカバーする。より多くのプロパティや演算子は上記 schema を参照。サンプル文字列や UUID は適宜置換すること。Simple property (title)
{ "filter": { "property": "title", "filter": { "operator": "string_contains", "value": { "type": "exact", "value": "standup" } } } }Combinator: and
{ "filter": { "operator": "and", "filters": [ { "property": "title", "filter": { "operator": "string_contains", "value": { "type": "exact", "value": "planning" } } }, { "property": "attendees", "filter": { "operator": "is_not_empty" } } ] } }Combinator: or, with sort and limit
{ "filter": { "operator": "or", "filters": [ { "property": "title", "filter": { "operator": "string_contains", "value": { "type": "exact", "value": "standup" } } }, { "property": "title", "filter": { "operator": "string_contains", "value": { "type": "exact", "value": "sprint" } } } ] }, "sort": [ { "property": "last_edited_time", "direction": "descending" } ], "limit": 20 }
Query a data source の filter とは全く表現方法が異なりますね。このため、DataSource 用の Query の子クラスではなく、専用の QueryMeetingNotesFilter のようなクラスを一つ作成した方がよさそうです。
Sorting
各 sort 要素は
propertyとdirection(ascending/descending)を持つ。propertyは request body schema で定義されるものと同一の集合である。複数 sort がある場合、先に書いたものが優先される。{ "sort": [ { "property": "last_edited_time", "direction": "descending" }, { "property": "title", "direction": "ascending" } ] }
これもプロパティごとに違いはなさそうなので、上記で作成したクラスで実装してもよさそうです。
Response shape
resultsの各要素は、meeting_notesオブジェクトと、通常の block メタデータを含む meeting note block である(詳細は本エンドポイントの response schema を参照)。
Integration capabilities このエンドポイントは Integration の Read content 権限を要する。ワークスペース側に、Integration のユーザーに対する AI meeting notes が存在しない場合、呼び出しは validation error を返す。capabilities guide を参照。
results の各要素は meeting_notes の配列として取得されるようです。summary_block_id, notes_block_id, transcript_block_id という children が含まれているようです。この id からそれぞれのブロックが取得できそうです。
Errors
Integration のユーザーに AI meeting notes が存在しない場合、または filter / sort が不正な場合、HTTP 400 を返す。
リクエストが request limits を超えた場合、HTTP 400 または 429 を返す。
Note: Public API の各エンドポイントは複数のエラーコードを返し得る。詳細は Status codes ドキュメントの Error codes section を参照。
ユーザ用の AI meeting notes が存在しなかったり、filter / sort が不正な場合に 400 が返るようです。基本的にインテグレーションキーのユーザが会議に参加することはないので、PAT 認証を想定しているものと思います。meeting note の作成自体をインテグレーションキーで実行した場合は、参照できるのかもしれません。
ここから先はパラメータの詳細について書かれているので、省略します。
おわりに
ChangeLog のチェックをしばらくサボっていたので、溜まってしまっていました。紹介が終わった段階で、NotionRubyMapping のアップデートも進めていきます。先日の markdown のアップデートもすでに修正が入っていました。なるべく早めに対応します。
https://hkob.notion.site/hkob-16dd8e4e98ab807cbe3cf3cc94cdfe0f?pvs=4hkob.notion.site