Microsoft Search APIは、Microsoft Graphの POST /search/query 1本でSharePoint・OneDriveのファイル、Outlookのメールと予定、Teamsのチャット、コネクタで取り込んだ外部データを検索するAPIです。エンドポイントは1本ですが、1回に送れる検索要求は1件だけで、組み合わせられるentityTypesも決まっています。アプリケーション権限ではregionの指定が必須です。この記事では、実装で引っかかる制約を公式ドキュメントの記述どおりに整理します。あわせて、SharePoint Search REST API(/_api/search/query)やCopilot Retrieval APIとどう使い分けるかも扱います。
- エンドポイントは
POST https://graph.microsoft.com/v1.0/search/query。requestsは配列ですが、現在処理されるsearchRequestは1回に1件だけです。 - 複数のentityTypesを混在できるのは、ファイル・サイト・外部データ系と検索回答系の2つのグループ内です。driveItem・listItem・site・list・drive・externalItemは同じグループですが、message・event・chatMessageはそれぞれ単独でしか指定できません。
- 1ページの件数は、message・eventが25件まで、SharePoint・OneDriveは概要ページで1000件までです。ただしsearchRequestのリファレンスは上限を500としているので、公式推奨の200件前後で設計すると安全です。
- アプリケーション権限で検索するときは
regionが必須で、既定では共有コンテンツしか検索されません。Sites.Selectedは権限表にありません。 - 結果ソースやランキングモデルを指定したい場合はSharePoint Search REST APIを使います。アプリのみのアクセスでは、Microsoft Entra IDアプリに登録した証明書で認証します(SharePoint Online向けAzure ACSは2026年4月2日に完全廃止)。
- 生成AIに渡すテキスト断片が欲しいならCopilot Retrieval APIが候補です。1回25件まで、ユーザーあたり1時間200リクエストまでで、KQLの構文を誤ると絞り込みが効かないまま実行されます。
Microsoft Search APIの位置づけと検索APIの選び分け
Microsoft 365のデータを検索するAPIは1つではありません。「SharePoint Search API」「Microsoft Graph Search」「Microsoft Search API」と呼び名が似ているため取り違えやすいので、まず次の4本を区別してください。
| API | エンドポイント | 検索範囲 | 向く用途 |
|---|---|---|---|
| Microsoft Search API | POST /search/query | ファイル・メール・予定・チャット・外部データ | 横断検索UI |
| driveItem search | GET …/root/search(q=) | 1つのドライブやフォルダ配下 | 場所が決まったファイル探し |
| SharePoint Search REST API | /_api/search/query | SharePointの検索インデックス | 結果ソース・FQLが要る検索 |
| Copilot Retrieval API | POST /copilot/retrieval | SharePoint・OneDrive・コネクタ | RAGのテキスト断片取得 |
driveItemの search(q=) は、ファイル名・メタデータ・ファイル内容をまとめて照合し、$top・$select・$orderby などのODataクエリパラメーターを使えます。サイトやフォルダが決まっているなら、こちらのほうが単純です。ただし公式リファレンスには This method doesn't support the Sites.Selected application permission. と明記されています。特定サイトだけに権限を絞ったアプリでは、パス指定で children をたどる実装に切り替えることになります。
SharePoint Search REST APIは、GETなら /_api/search/query、POSTなら /_api/search/postquery で呼び出します。KQLに加えてFQLも送れます。Graphには無い次のパラメーターが必要な場合は、こちらを選びます。
SourceId:結果ソースを指定します。Graphの概要ページは、カスタム検索スキーマや結果ソースがSearch APIの動作を妨げうると注意しています。RankingModelId:ランキングモデルを指定します。StartRow:開始行を指定します。上限は50,000で、それより深いページングには別途Pagination for large result setsの手法が案内されています。
認証は更新が必要な箇所です。Azure ACSは新規テナントでは2024年11月1日に使えなくなり、既存テナントでも2026年4月2日に完全廃止されました。SharePoint Add-Inも同じ日に全テナントで停止しています。現在、アプリのみのアクセスでSharePointのCSOM・REST APIを呼ぶには、Microsoft Entra IDアプリに証明書を登録する必要があります。公式手順は you must use a certificate と書いており、クライアントシークレットでは通りません。GraphとMSALへの移行手順はAzure AD Graph廃止後のEntra IDアプリ移行手順にまとめています。
GET https://contoso.sharepoint.com/sites/sales/_api/search/query?querytext='filetype:docx'&selectproperties='Title,Path,Author'&rowlimit=50&startrow=0
Accept: application/json;odata=nometadata
Authorization: Bearer {証明書で取得したアクセストークン}
検索できるentityTypesと組み合わせの制約
検索対象はsearchRequestの entityTypes で指定します。次の表は主に委任権限での検索に必要な権限を示します。アプリケーション権限では同じ対象をすべて検索できるわけではなく、search/queryの権限表に掲載されているのはFiles.Read.AllとSites.Read.Allです。
| entityType | 対象 | 必要な権限 |
|---|---|---|
| driveItem | ファイル・フォルダ・ページ・ニュース | Files.Read.All または Sites.Read.All |
| listItem | リストアイテム(ファイルも含む) | Sites.Read.All |
| site / list / drive | サイト・リスト・ドキュメントライブラリ | Sites.Read.All(driveはFiles.Read.Allも可) |
| message / event | メール・予定表 | Mail.Read / Calendars.Read |
| chatMessage | Teamsのメッセージ | Chat.Read または ChannelMessage.Read.All |
| externalItem | Copilotコネクタの取り込みデータ | ExternalItem.Read.All |
| acronym / bookmark / qna | 管理者が登録した検索回答 | Acronym.Read.All など |
公式の対応表で組み合わせ可(True)になっているのは、次のグループの中だけです。
- driveItem・listItem・site・list・drive・externalItem は相互に混在できます。
- acronym・bookmark・qna は相互に混在できます。
- message、event、chatMessage、person は、それぞれ単独でしか指定できません。
メールとファイルを1つの画面に並べたい場合は、要求を2回に分けてクライアント側でまとめます。requests が配列でも、サービスが処理するのは1回に1件だからです。なお contentSources はexternalItemのときだけ有効です。Microsoft Graph connectorsは現在「Microsoft 365 Copilot connectors」に改称されており、公式ドキュメントも formerly Microsoft Graph connectors と併記しています。
search/queryの基本リクエストとページング
以下は、委任権限でSharePointとOneDriveのWord文書を検索し、必要な列を25件ずつ受け取るHTTP要求例です。Files.Read.AllまたはSites.Read.Allを持つMicrosoft Graph向けアクセストークンを使用します。
POST https://graph.microsoft.com/v1.0/search/query
Content-Type: application/json
Authorization: Bearer {Microsoft Graph向けアクセストークン}
{
"requests": [
{
"entityTypes": ["driveItem"],
"query": { "queryString": "見積 filetype:docx" },
"fields": ["name", "webUrl", "lastModifiedDateTime", "createdBy"],
"from": 0,
"size": 25
}
]
}
レスポンスは value[0].hitsContainers[0].hits に結果が並び、moreResultsAvailable で続きの有無を判定します。from をずらして次のページを取りに行きます。
size上限の公式記述の差異とfromによるページング
公式ドキュメントの記述が2か所で食い違っています。searchRequestのリファレンスはsizeを The maximum value is 500. としています。一方、Search APIの概要ページは既定25件・最大1000件とし、SharePointとOneDriveについて A reasonable page size is 200. と推奨しています。どちらの上限でも問題が起きないよう、1ページ目は25件、以降は200件以下で増やす実装が安全です。概要ページが例示しているページングは次のとおりです。
| ページ | from | size |
|---|---|---|
| 1 | 0 | 25 |
| 2 | 25 | 50 |
| 3 | 75 | 75 |
| 4 | 150 | 100 |
message・eventは別の制約を持ちます。sizeの上限は25件で、1ページ目のfromが0でないとHTTP 400になります。また、関連度順の結果をページングすると、同じアイテムが複数のページに現れることがあります。重複を避けたいなら、並べ替えを固定するよう公式に推奨されています。
fields は、返すプロパティを絞る点でODataの $select に相当します。スキーマに無い名前や取得可能でない名前は、エラーにならず無視されます。列名を打ち間違えても400が返らないので、結果に列が無いときはまず綴りを疑ってください。スキーマで取得可能にした拡張列を返せるのはlistItemとexternalItemだけです。ドキュメントライブラリの独自列(例:案件番号)を取りたい場合は、entityTypeにdriveItemではなくlistItemを指定します。fieldsを省略した場合、listItemは独自列を返しません。externalItemは、コネクタのスキーマで取得可能にした列をすべて返します。
KQLでの絞り込み・並べ替え・集計
queryString には、キーワード・AND/OR・プロパティ制限をKQLで書けます。SharePointのKQLリファレンスの例は、filetype:docx(Word文書)、filename:budget.xlsx(ファイル名)、author:"John Smith"(作成者)です。実装時にはまりやすい規則が3つあります。
- プロパティ名・演算子・値のあいだに空白を入れると、プロパティ制限ではなくフリーテキスト検索として扱われます(
author: "John Smith"は不可)。 - ワイルドカード
*は後方にしか付けられません。title:"Advanced Sear*"は有効ですが、前方一致以外の部分一致は書けません。 - プロパティ制限の長さは2,048文字までです。
「ファイル名の一部で探したい」という要件では、filename:見積* のように先頭一致で書きます。末尾が一致するファイルを探す書き方はKQLにありません。要件を「先頭一致で足りるか」まで確認してから設計してください。
sortPropertiesで並べ替えできる対象と上限
既定の並び順は、message・eventが日付順、SharePoint・OneDrive・person・コネクタが関連度順です。sortProperties は最大5件まで指定できます。対象のプロパティは検索スキーマでsortableでなければならず、条件を満たさないとHTTP 400が返ります。また、関連度順をsortPropertiesで明示することはできません。message・eventは並べ替えに対応していません。externalItemについては、概要ページの既知の制限は非対応としていますが、並べ替えの解説ページはrefinableなプロパティなら対応すると書いており、記述が割れています。コネクタのデータを並べ替える設計なら、実テナントで確認してから採用してください。
{
"requests": [
{
"entityTypes": ["driveItem"],
"query": { "queryString": "filetype:pptx" },
"sortProperties": [
{ "name": "lastModifiedDateTime", "isDescending": true }
],
"aggregations": [
{ "field": "fileType", "size": 10, "bucketDefinition": { "sortBy": "count", "isDescending": true, "minimumCount": 0 } }
],
"from": 0,
"size": 50
}
]
}
aggregationsによる絞り込みと重複の除外
aggregations は、SharePointでいう絞り込み(refiner)です。driveItem・listItem・list・externalItemのrefinableなプロパティで使えます。レスポンスのバケットにある aggregationFilterToken を、トークン単体ではなくフィールド名と組み合わせた {field}:"{aggregationFilterToken}" 形式の文字列にして次の要求の aggregationFilters 配列に入れると、そのバケットの結果に絞れます。これで「ファイル種別で絞る」UIを組めます。指定したプロパティ値が共通する結果をまとめたい場合、委任権限では collapseProperties がv1.0で使え、対象はdriveItem・listItem・drive・list・site・externalItemです。多段で指定するときは、後の段のlimitを前の段以下にしないとHTTP 400になります。trimDuplicates の解説はbetaエンドポイントの例で書かれており、v1.0のsearchRequestのプロパティ一覧には載っていません。
委任権限とアプリケーション権限の設計
search/queryの権限表では、委任権限(職場・学校アカウント)の最小権限がMail.Read、アプリケーション権限の最小権限がFiles.Read.Allです。個人のMicrosoftアカウントは非対応です。実際に必要な権限は、前の章の表のとおりentityTypeで決まります。委任権限の検索はサインインしたユーザーの代理で実行され、公式ドキュメントのとおり Search results are scoped to enforce any access control applied to the items. です。
アプリケーション権限のregion指定と既定の検索対象
アプリケーション権限による検索は、1つの地理的リージョンに限られます。searchRequestに region を指定しないと実行できません。値はsiteCollectionリソースの dataLocationCode で取得します。既定では共有コンテンツだけが検索対象で、個人のプライベートなコンテンツは含まれません。含めたい場合は sharePointOneDriveOptions.includeContent に privateContent を指定します(値は sharedContent と privateContent)。ただし privateContent の初回要求で専用インデックスの構築が始まり、完了までは共有コンテンツだけが返ります。公式は中〜大規模テナントで数日〜1週間かかるとし、3か月間 privateContent の要求が無いとインデックスは廃棄されます。また、アプリケーション権限では深いページングが非対応とされ、fromが1000を超える場合が例示されています。全件走査を前提にした用途には適しません。
{
"requests": [
{
"entityTypes": ["driveItem"],
"query": { "queryString": "契約書" },
"region": "{dataLocationCodeの値}",
"sharePointOneDriveOptions": { "includeContent": "privateContent,sharedContent" },
"from": 0,
"size": 25
}
]
}
アプリケーション権限のFiles.Read.Allは、組織のすべてのSharePointとOneDriveのファイルを読める権限です。search/queryはSites.Selectedによるアプリケーション権限の制限には対応していません。KQLのPath条件で検索結果を特定サイトに絞ることはできますが、アプリ自体のアクセス権限をそのサイトだけに限定するものではありません。検索範囲を絞りたい要件なら、委任権限でユーザー本人の権限範囲に閉じる設計を先に検討してください。委任権限の検索では、ユーザーがアクセスできるアイテムのうち、検索条件に一致してインデックスに登録されたものが返ります。アプリケーション権限の検索では、アプリに付与された権限が基準となり、画面の利用者本人の権限に自動的に絞られるわけではありません。共有設定が緩いテナントでは、検索で思わぬ文書が見えてしまいます。事前に過剰共有の可視化とRCD・DLPの設定で棚卸ししておくと安全です。
導入前に確認すべき既知の制限
公式の既知の制限のうち、設計を変える必要があるものを挙げます。
- SharePoint検索のカスタマイズ(独自の検索スキーマや結果ソース)は、Search APIの動作を妨げることがあります。
- サイトレベルの検索スキーマは使えません。テナントレベルか既定の検索スキーマで管理プロパティを定義します。
- ゲストによる検索は、acronym・bookmark・message・chatMessage・event・person・qna・externalItemに対応していません。
- driveを検索する場合は、ドキュメントライブラリ名に含まれる語をqueryStringに入れる必要があります。
*で全ライブラリを列挙することはできません。 - XRANKによる順位の引き上げは、message・event・externalItemなどでは使えません。
このため、次のような要件ではSearch APIを第一候補にしないほうがよいです。サイトごとに作り込んだ結果ソースやランキングを再現する要件なら、SharePoint Search REST APIのほうが確実です。特定サイトだけにアプリの権限を限定する要件では、Sites.Selectedに対応する取得APIとサイトへの明示的な権限付与を組み合わせます。パス指定だけでは権限を限定できず、委任権限もユーザーがアクセスできる他サイトを自動的に除外するものではありません。社内ポータルに検索Webパーツを置くだけで済むなら、APIを書かずにSharePointの社内ポータル構成の範囲で解決できる場合もあります。
RAG用途ならCopilot Retrieval APIとの使い分け
生成AIの根拠データとしてMicrosoft 365の文書を使う場合、Search APIでファイルを探して本文を取り出し、自前で分割・ベクトル化することもできます。これに対し、Microsoft 365 Copilot Retrieval APIは、Copilotが使うハイブリッドインデックスから関連するテキスト断片を直接返します。エンドポイントは POST https://graph.microsoft.com/v1.0/copilot/retrieval で、betaにも同じ操作があります。
| 項目 | Retrieval APIの仕様 |
|---|---|
| 対象データ | SharePoint・OneDrive・Copilotコネクタ |
| 権限方式 | 委任権限のみ |
| SharePoint・OneDriveの権限 | Files.Read.AllとSites.Read.Allの両方 |
| コネクタの権限 | ExternalItem.Read.All |
| データソース | 1回に1つ(混在不可) |
| maximumNumberOfResults | 最大25 |
| queryString | 1,500文字まで |
| レート | ユーザーあたり1時間200リクエスト |
| 意味・ハイブリッド検索 | doc・docx・pptx・pdf・aspx・oneのみ |
| ライセンス | Copilotアドオンで追加費用なし |
| 従量課金(プレビュー) | 1 APIコール0.10ドル |
従量課金はAzureサブスクリプション経由のプレビューで、SLAはありません。対象はSharePointやコネクタといったテナント単位のデータソースだけで、OneDriveは使えません。実装で最も注意すべき点は、公式の既知の制限にある If the filterExpression request parameter has incorrect KQL syntax, the query successfully executes with no scoping. です。KQLを書き間違えてもエラーにならず、絞り込みが外れたまま検索されます。「承認済みライブラリだけを根拠にする」ためにfilterExpressionを使う設計では、単体テストで絞り込みが効いているかを検証してください。返る結果と断片は順不同なので、LLMの入力トークン数に厳しい制限がない限り、maximumNumberOfResultsを小さく制限せず、返された断片をすべてLLMへ渡すことが推奨されています。キーワード一致とベクトル検索を組み合わせる考え方はハイブリッド検索の仕組みとRRFで解説しています。
使い分けの判断は単純です。人が結果一覧を見て開く検索画面ならSearch API、LLMに根拠の文章を渡すならRetrieval APIを選びます。Copilotライセンスが無く、OneDriveも対象に含めたい場合は、Retrieval APIの従量課金では届かないため、Search APIと自前の分割処理が残る選択肢になります。
よくある質問
Microsoft Search APIとMicrosoft Graph APIは別物ですか?
別物ではありません。Microsoft Search APIは、Microsoft Graphの一部として提供される /search/query などの検索系APIの総称です。認証はほかのGraph APIと同じくMicrosoft Entra IDのアクセストークンで行い、Graph Explorerからも試せます。
使えます。/_api/search/query と /_api/search/postquery は現行のドキュメントに掲載されています。ただしAzure ACSは2026年4月2日に廃止されたため、アプリのみのアクセスではMicrosoft Entra IDアプリに証明書を登録して認証します。
検索結果は1回に何件まで取得できますか?
message・eventは1ページ25件までです。SharePoint・OneDriveは、概要ページでは1000件、searchRequestのリファレンスでは500件が上限と記述が割れています。公式推奨の200件前後でページングしてください。
個人のMicrosoftアカウントでも使えますか?
使えません。search/queryの権限表では、個人のMicrosoftアカウントは最小権限・上位権限とも非対応です。職場または学校アカウントのテナントが必要です。
Microsoft Graph connectorsで取り込んだデータも検索できますか?
できます。entityTypesに externalItem を指定し、contentSources に接続を指定します。Microsoft Graph connectorsは現在「Microsoft 365 Copilot connectors」という名称です。権限はExternalItem.Read.Allが必要です。