Claude Media
Compliance APIでセッションの文字起こしを取得する手順

Compliance APIでセッションの文字起こしを取得する手順

Compliance APIでCoworkやClaude Codeのローカル/リモートセッションを一覧・取得する手順です。取れる内容の範囲、保持期間、OpenTelemetryとの違いをまとめます。

自社のセッションはどのエンドポイントで取れるか

Compliance APIは、CoworkやClaude Codeなどユーザーが実行するセッションのトランスクリプトを、コンプライアンス担当者向けに公開します。1セッションはClaudeとの1会話で、トランスクリプトはユーザーのプロンプト・アシスタントの応答・ツール呼び出しと結果の並びです。eDiscovery(電子証拠開示)エクスポートとDLP(データ損失防止)の実施が主な用途で、対象はClaude Enterpriseの組織に限られます。

このページが扱うのはセッションのトランスクリプトです。claude.aiのチャット・ファイル・プロジェクトは別のエンドポイントで、Compliance APIでチャット・ファイル・プロジェクトを取得・削除するにあります。

必要なのはCompliance APIのセットアップとアクセスキー作成で作ったCompliance Access Keyのread:compliance_user_dataだけです。チャット・ファイル・プロジェクトのエンドポイントと同じキーとスコープで、新しいキーも設定変更もクライアントの更新も要りません。

Admin API keyでは、このページのどのエンドポイントも呼べません。次のように403 Forbiddenが返ります。

Missing required scopes. Got: ['read:compliance_activities'] Needed one of: ['read:compliance_user_data', 'read:org_audit']

セッションは実行場所で2系統に分かれます。ユーザーのマシンで動くものがローカル、Anthropicのクラウドで動くものがリモートです。応答のproduct_surfaceで、どの製品のセッションかを見分けられます。

製品と実行場所エンドポイント系統product_surface
Cowork(Claude Desktop、ユーザーのマシン)エンドポイント系統ローカル(/v1/compliance/apps/sessions/local)product_surfacecowork
Claude Code(ターミナル・Claude Desktop・IDE拡張)エンドポイント系統ローカルproduct_surfaceclaude_code
Claude Scienceデスクトップアプリエンドポイント系統ローカルproduct_surfaceclaude_science
Claude for Microsoft 365(Excel/PowerPoint/Word/Outlook)エンドポイント系統ローカルproduct_surfaceoffice_agents/excelなど。アプリが特定できないときはoffice_agents
Claude in Chrome(拡張機能のチャット)エンドポイント系統ローカルproduct_surfaceclaude_in_chrome
claude.ai web/mobileで開始したCoworkセッション(クラウド実行)エンドポイント系統リモート(/v1/compliance/apps/sessions/remote)product_surfacecowork_remote

安定版として扱われるのはCowork・Claude Code・Claude for Microsoft 365で、Claude ScienceとClaude in Chromeはベータです。表の値は今後増えるので、未知のproduct_surfaceはそのまま通す実装にしておきます。

対象外

取得対象外になるセッション

  • 認証・経路が違うClaude Code

    Claude Console APIキーで認証したセッション、およびAmazon Bedrock・Google Cloud・Microsoft Foundry経由のセッションは記録されません。

  • クラウドで動くClaude Code

    Claude Codeのクラウドセッションは、クラウド実行のルーティンも含めてどちらの系統にも出ません。リモートが返すのはCoworkだけで、名前から「クラウドで動くものは全部入る」と読むと取りこぼします。

  • HIPAA readiness有効の組織

    ローカルで返るのはCoworkとClaude Codeだけになり、保存期間も30日に縮みます。

  • ZDRが適用されたセッション

    一覧から除外され、個別取得もメッセージ取得も404になります。

ローカルセッションの一覧を取る

ローカルセッションは、ユーザーがClaude Enterpriseアカウントでサインインしている間に、ユーザーのマシン上で実行されるセッションです。デバイスには何もインストールされず、Anthropicはクライアントから届くClaude APIへのリクエストだけをサーバー側で記録します。トランスクリプトに残るのは「Claudeに何を頼み、何が返ったか」で、APIに届かないローカルファイル操作などは残りません。

一覧はGET /v1/compliance/apps/sessions/localです。組織やユーザーでの絞り込みは無く、created_at.gteとcreated_at.ltで期間を切ります。

curl --fail-with-body -sS -G \
  "https://api.anthropic.com/v1/compliance/apps/sessions/local" \
  --header "x-api-key: $ANTHROPIC_COMPLIANCE_ACCESS_KEY" \
  --header "anthropic-version: 2023-06-01" \
  --data-urlencode "created_at.gte=2026-07-01T00:00:00Z" \
  --data-urlencode "limit=100"

時刻はUTCオフセット付きのRFC 3339で書きます。オフセットが無いと400になり、メッセージはcreated_at.gte: Input should have timezone infoです。両方の境界を付けるときは、created_at.ltをcreated_at.gteより後にします。同じ時刻や逆順だとcreated_at.lt must be strictly after created_at.gte.の400が返ります。

結果はcreated_atの新しい順で、1回の上限は既定100件・最大500件です。次のページは、応答のnext_pageをpageパラメーターに渡して取り、next_pageがnullになったら終わりです。has_moreフィールドはありません。

一覧に載るのはメタデータだけです。user.idは常に入り、アカウントが削除されても残ります。user.email_addressは、アカウント削除済みか、キーが読めない組織のメンバーでなくなったときにnullになります。workspace_idはワークスペースと無関係なセッションでnullです。

ローカルセッションの単位はクライアント側のセッションIDです。クライアントで新しい会話を始めたり、コンテキストをクリアしたりすると、別のセッションとして記録されます。

次のような場面は、仕様どおりの挙動です。

  • Claude Scienceでは、会話のタイトル付けなどアプリ自身の裏作業が別セッションとして一覧に並ぶ
  • Claude Scienceの会話が一部のアプリ更新をまたぐと、2セッションに分かれて見える
  • Claude for Microsoft 365でアドイン側が会話を削除しても、APIには反映されず、保持期間が過ぎるまで一覧に残る

差分を取り続ける巡回の組み方

一覧にはupdated_at.gteという第3のフィルターがあります。最後のAPI呼び出しがその時刻以降のセッションを返すので、前回の巡回以降に動いたセッションだけを拾えます。created_atのフィルターとも併用でき、並び順やページ送りは変わりません。

ここで落とし穴になるのが、反映の遅れです。新しいセッションやメッセージが結果に出るまでには、通常数分かかります。updated_atも、ページ境界で動いているセッションについては最新のアクティビティより少し古い値になりえます。

手順

巡回の1周分の手順

  1. 1

    前回の開始時刻の数分前から始める

    前回の開始時刻ちょうどを境界にすると、境界の瞬間にインデックス中だったセッションが、境界が進んだあとの巡回から永久に外れます。

  2. 2

    一覧を24時間以内に最後まで歩く

    24時間を過ぎたカーソルも受理されますが、その時点の保持期限で再評価されます。期限が迫ったセッションが途中で抜けることがあります。

  3. 3

    セッションの重複を除き、トランスクリプトを取り直す

    古いセッションが再び出てくるのは、重なりを持たせた設計の想定内です。created_atは保持期間の経過で進むため、重複排除のキーには使えません。キーはidです。

  4. 4

    メッセージの重複も除く

    メッセージもidで重複を除きます。個別取得とメッセージ取得は、常に保持されている最新の呼び出しまでを反映します。窓を広げる代わりに、古い期間を定期的に洗い直す方法もあります。

ローカルセッションのトランスクリプトを取得する

セッションIDを指定して/messagesを呼びます。

session_id="clls_01HxKpLmNoPqRsTuVwXyZaBc"
 
curl --fail-with-body -sS \
  "https://api.anthropic.com/v1/compliance/apps/sessions/local/$session_id/messages" \
  --header "x-api-key: $ANTHROPIC_COMPLIANCE_ACCESS_KEY" \
  --header "anthropic-version: 2023-06-01"

メッセージは古い順に返ります。order=descで逆順にできます。ただし非常に大きなセッションでは、読み出せないほど大きなページが400になることがあり、descのほうがはるかに多く起きます。その場合はascで、最初のページから読み直します。1回の上限は既定100件・最大1,000件です。上限に満たない件数でページが終わることがあるので、件数ではなくnext_pageがnullになるまで読みます。カーソルは取得したセッションと並び順に紐づき、最初のページから24時間で期限が切れます。別のセッションや別のorderのカーソルを渡すと、期限切れと同じ400になります。

各メッセージにはrole(user/assistant)と、text・tool_use・tool_resultのいずれかを並べたcontent配列があります。通常のアシスタントのメッセージには、応答したモデル名がmodelに入ります。ユーザーのメッセージと、provenanceが付いたアシスタントのメッセージではnullです。

形でつまずきやすい点が3つあります。

  • tool_useのinputはオブジェクトでなく、JSONをエンコードした文字列です
  • 同じAPI呼び出しから復元されたメッセージは同じcreated_atを持つので、並べ替えず返却順を保つ
  • 応答のsession.user.email_addressは常にnullで、メールアドレスは一覧か個別取得のuser.idと突き合わせる

inputが文字列である点は、jqで試すとすぐ分かります。公式の応答例と同じ形のJSONから、切り詰められていないtool_useのファイルパスを取り出すと次の結果になります。

jq -r '.data[].content[]
  | select(.type=="tool_use" and .truncated==false)
  | .input | fromjson | .file_path' transcript.json
tests/auth_test.py

fromjsonを挟まないと、.inputはエスケープ済みの文字列のままです。truncatedがtrueのブロックはfromjsonで失敗するので、selectで外します。

切り詰めと置き換えのルール

トランスクリプトは、ユーザーのプロンプト・アシスタントのテキスト・ツール呼び出し・ツール結果のテキスト部分を、サイズによる切り詰め以外はそのまま返します。URL・認証情報・個人データはマスクされないので、取得したトランスクリプトは機密情報として保管します。次の内容は含まれないか、置き換えられます。

  • Thinking(思考過程)ブロックは常に含まれない
  • システムプロンプトは[system prompt content not shown]というマーカーに置き換わる(通常はセッションにつき1回)
  • ツール定義とMCPサーバー設定は含まれない
  • 画像・PDFなどバイナリは[image content not shown]のようなtextブロックになり、truncatedがtrueになる
  • ツール結果の中のWeb検索結果やコード実行ツールの出力は、[N non-text item(s) not shown]の1エントリになる。対応するtool_useのinputには検索クエリやコードが残る
  • textブロックの引用メタデータ(Web検索の出典など)は省かれ、本文だけがtruncated: trueで返る

CLAUDE.mdのようなプロジェクト指示ファイルは、通常のユーザーロールの文章として現れます。スキルの内容もクライアントがメッセージとして送ったときに現れ、ほかのユーザーの文章と見分けるフィールドはありません。

ツール入力とツール結果の各テキストは既定で10,000バイトに切り詰められます。tool_use_input_max_bytesとtool_result_max_bytesに-1を渡すと、サーバー上限(1文字列あたり約1MiB)まで広がります。0を渡すと400で、上限を超える値は上限に丸められます。textブロック自体は常にこの約1MiBが上限で、パラメーターでは広げられません。

切り詰められた文字列には、…[truncated; pass tool_result_max_bytes=-1 for the server max]のような目印が末尾に付きます。そのためtool_useのinputはJSONとして壊れます。上限を上げて取り直せば、末尾まで読めます。

Claude Scienceは、コネクター(MCPサーバー)をreplツール経由のコードから呼びます。Coworkならmcp__<server>__<tool>という名前のtool_useが並ぶのに対し、Claude Scienceのトランスクリプトにはコネクター名のブロックがありません。コネクターの利用を監視するときは、replのinputに含まれるコードを文字列として調べます。コードが10,000バイトで切れる前にコネクター呼び出しが現れるよう、tool_use_input_max_bytes=-1を付けて取得します。

欠けた箇所をprovenanceで読み分ける

トランスクリプトは「Claude APIに届いた内容の復元」なので、欠けた部分や、出どころを保証できない部分が出ます。各メッセージのprovenanceが、その扱いを示します。通常のキャプチャ済みコンテンツではnullです。

読み方

provenanceの3種類

  • content_unavailable

    内容を返せません。contentは空配列で、reasonが理由を示します。

    • not_captured: 取得できた内容がない。保存記録が無い証拠にはならず、データ取り扱い方針で出せない内容も同じ理由になる
    • client_aborted: 応答の完了前にクライアントが接続を閉じた。途中までのストリーム出力も含まれない。アシスタントのターンだけに付く
    • retention_elapsed: 保持期間を過ぎた
    • oversize: 1メッセージがサイズ上限を超えた。メッセージ自体は空のcontentで返る
  • client_asserted

    クライアントが会話履歴として渡したアシスタントのメッセージで、取得済みの応答と突き合わせられなかったものです。発言者の真正性は確認されていません。

  • synthetic_marker

    エンドポイント自身が作った記録です。システムプロンプトの代わりのマーカーのほか、クライアントがコンテキストの圧縮などで履歴を書き換えた箇所に挿入されます。

組織に有限の保持期間があり、書き換え後の内容にアシスタントのメッセージが含まれるときは、その最後のアシスタントメッセージまでの内容が伏せられます。2つ目のマーカーがそれを示します。書き換え後の内容のうち見えるのはその後のユーザーメッセージだけで、そのあとのセッション本体は通常どおり続きます。コンテキスト圧縮が起きた長いセッションの証跡を探すとき、ここで抜けが生じます。

公式の応答例の形に、応答完了前にクライアントが切断したclient_abortedのメッセージを1件足したJSONで、provenanceがnullでないメッセージだけを一覧にすると、こうなります。

jq -r '.data[] | select(.provenance != null)
  | "\(.id) \(.provenance.type) \(.provenance.reason // "-")"' transcript.json
clsm_a synthetic_marker -
clsm_c content_unavailable client_aborted

reasonの値は今後増えることがあります。未知のprovenanceの種類や理由が来ても読み飛ばせるよう、フォワード互換な実装にしておきます。

カスタマーマネージド暗号化キー(CMEK)を使う組織では、トランスクリプトがそのキーで暗号化されたまま通常どおり返ります。キーが無効化・失効・到達不能になると、影響を受けるページのメッセージ取得が503になります。このときのメッセージはnot_capturedとして返されず、一覧とメタデータの取得は影響を受けません。

cmek_key_revokedというreasonは、キーが使えない組織のために予約されているだけで、現状は返りません。キーが使えないときは503になるためです。

リモートセッションを取得する

claude.aiのwebやモバイルで始めたCoworkセッションは、Anthropicが管理するクラウド環境で動き、リモートセッションとして別のエンドポイントから取ります。

curl --fail-with-body -sS -G \
  "https://api.anthropic.com/v1/compliance/apps/sessions/remote" \
  --header "x-api-key: $ANTHROPIC_COMPLIANCE_ACCESS_KEY" \
  --header "anthropic-version: 2023-06-01" \
  --data-urlencode "created_at.gte=2026-06-01T00:00:00Z" \
  --data-urlencode "limit=100"

ローカルとの違いは次のとおりです。

くらべる

ローカルとリモートで変わる取り方

ユーザーのマシン

ローカル

組織・ユーザーでの絞り込みはなく、時間だけで切ります。updated_at.gteでポーリングでき、statusはありません。レート制限は共有の1本だけです。IDはclls_で始まります。

クラウド

リモート

organization_ids[](最大500件)かuser_ids[](1〜10件)で絞れます。updated_atのフィルターはありません。statusがあり、共有のレート制限に加えて専用の第2の予算を消費します。IDはcse_で始まります。

user_ids[]に入れるIDは、組織のユーザー一覧エンドポイントで取ります。このフィルターはセッションの所有者に対して効くので、user_ids[]を指定するとエージェントが所有するセッションは対象から外れます。

リモートの一覧には、ローカルに無い項目が2種類あります。

  • 所有者: セッションはユーザーかエージェントのどちらか一方が所有します。ユーザー所有ならuserにIDとメールアドレスが入ります。エージェント所有(Coworkのスケジュールタスクをクラウドで走らせた実行など)ならuserはnullで、agent_id(cagt_で始まる)と、実行を起動した人を示すstarted_by_userが入ります
  • claude_project_id: セッションが属するclaude.aiプロジェクトのID(claude_proj_で始まる)で、プロジェクト外ならnull

スケジュールタスクの1回の実行が1セッションです。タスクの名前や周期を持つフィールドはないので、どのタスクの実行かは、トランスクリプトの中身から判断することになります。

statusはpending・active・paused・archived・failedのいずれかです。pendingは環境を用意している最中で、トランスクリプトはまだなく、メッセージ取得は404になります。削除されたセッションは返りません。

メッセージ取得の応答では、sessionの封筒のuser.email_address・started_by_user・claude_project_idが常にnullです。これらの値は一覧から取ります。メッセージにはcontent_unavailable(真偽値)があり、サイズ超過などで内容を返せないときにtrueになります。エージェント所有のセッションでは、ユーザーのメッセージを送った人が特定できればsent_by_user_idに入ります。

専用の第2予算が尽きたときの429は、retry-afterが常に1で返ります。実際のリセット時刻ではなく最小待機時間なので、再発するなら指数バックオフで待ちます。

OpenTelemetryとの使い分け

CoworkとClaude Codeには、Compliance APIと別に、自前のコレクターへイベントを流すOpenTelemetryロギングもあります。

項目ローカルリモートOpenTelemetry
配信ローカルPull(HTTPS)リモートPull(HTTPS)OpenTelemetryPush(自前のOTLPコレクター)
運用ローカルAnthropicがホストリモートAnthropicがホストOpenTelemetryコレクターとストレージを自組織で運用
保持期間ローカル既定6年(組織のカスタム期間があればそちら、HIPAA readinessなら30日)リモート6年(ユーザーが削除すれば短い)OpenTelemetry自組織の方針
ツール入力ローカル既定10,000バイトで切り詰めリモート同左OpenTelemetry切り詰めた要約
ホスト・端末のメタデータローカルなしリモートなしOpenTelemetryあり(ターミナルの種類、作業パスなど)
トークン使用量・コストローカルなしリモートなしOpenTelemetryあり

セッション内容の取得にはCompliance APIが推奨されています。OpenTelemetryもプロンプトと応答を取れますが、役割は「起きている間のイベントを自前の基盤へ流す」ことで、保存済みのトランスクリプトをあとから引くのとは別物です。

トークン使用量とコストはClaude Enterprise Analytics APIで取ります。コストと使用量は従量課金のEnterpriseプランで取れ、席課金のプランでは使用クレジット分だけが返ります。キーはread:analyticsスコープのAnalytics APIキーを、Compliance Access Keyとは別に作ります。OpenTelemetryとはユーザーIDと組織IDを共有するので、突き合わせて使えます。

保持期間と削除

ローカルセッションの内容は、取得から既定6年保持されます。組織がclaude.ai > Organization settings > Data and privacyで有限のカスタム会話保持期間を設定していると、そちらが代わりに適用され、既定より短くても長くても同じです。複数のカスタム期間があるときは最短が使われます。HIPAA readinessを有効にした組織は30日、または30日より短いカスタム期間です。6年の既定は適用されません。

設定を変えたときの動きは、見える範囲と保存期間で別々です。

  • 変更はすぐ反映され、新しい期間より古いアクティビティはエンドポイントから返らなくなる
  • すでに保存されたメッセージは、保存された時点の保持期間のまま残る
  • 期間をあとから延ばしても、すでに期限切れになった内容は戻らない

ローカルセッションはAPI呼び出しの単位で保持が適用されます。created_atは残っている最も古い呼び出しの時刻で、古い呼び出しが期限を過ぎるたびに進みます。すべての呼び出しが期限を過ぎると、セッションは一覧から消えます。

リモートセッションは、ユーザーが削除しない限り6年保持されます。ユーザーが削除すると一覧から返らなくなり、トランスクリプトはCompliance APIを使っても復元できません。法的保全やアーカイブに使う内容は、削除される前に取得して自前で保管します。

取得が失敗したときの切り分け

セッション系のエンドポイントでは、同じステータスコードでも原因が複数あります。メッセージの文面で見分けます。

症状原因対処
ローカルが404 Local session not found.原因読めない組織のセッション、存在しないID、ZDR適用、全呼び出しが保持期間切れのいずれか。応答では区別できない対処一覧にIDがあるか確認する。一覧にも無ければ保持期間切れで、取れないのでキューから外す
ローカルが404 Local sessions are not available.原因親組織に対してローカルセッションのエンドポイントが使えない状態。IDには依存せず、一時的なこともある対処一覧も含めて同じ応答なら、キューのIDを残して次回の定期実行で再試行する
リモートが404 Remote session not found.原因存在しない・削除済み・読めない組織のセッション、またはstatusがpending対処statusを一覧で確認する。pendingなら開始後に再試行する
ローカルが503 Captured content is temporarily unavailable. Try again shortly.原因一時的な不調。CMEKを使う組織では、キーが使えない間は続く対処指数バックオフで再試行する。CMEKで続くなら、その組織の取得を止めてキーの状態を確認する
ローカルが503 …cannot currently evaluate retention overrides for this page. Try again later.原因保持・データ取り扱いの設定を評価できない。負荷でなく、その組織のデータと設定に依存し、長引くことがある対処待ち続けず、一覧ならcreated_atの窓を狭めて取れる範囲を先に出し、スキップした範囲は後日取る
ローカルが503 The local-sessions index is temporarily unavailable. Try again shortly.原因一覧のインデックスが一時的に使えない対処少し待って再試行する
429原因親組織で毎分600リクエストの共有上限(全キー・全/v1/compliance/*エンドポイント合算)、またはリモートの第2予算対処retry-afterの秒数を待つ。カーソルは進めない。再開は直前の成功ページのカーソルから

セッションIDの形式が不正なら400です。

まとめ

取りたい対象のClaude製品がどちらの系統か(Claude Code・Coworkのローカル実行ならローカル、claude.ai発のCoworkならリモート)を先に決めれば、必要なのは同じCompliance Access Keyだけです。ZDRがどの契約形態で有効になるかは、Claude Zero Data Retentionが有効になる契約形態の切り分けで確認できます。

この記事を共有:XはてブLinkedIn