コンテンツにスキップ

共有とディスカッション

レポート は 2 つの方法で公開できます。公開共有(public share) は、URL (と任意のパスコード)を知っていれば誰でも開ける capability リンクを発行します。レポートの不変な 1 バージョンが、Spantail アカウント不要で公開ビューアから配信されます。ディスカッション(discussion) は送信されたコンテンツバージョンごとに付随し、その参加者(レポート所有者とそのバージョンの Send-to 受信者)が本文にリアクションし、スレッド形式のコメントを残せます。

共有はレポートの不変なコンテンツバージョン 1 件を参照します — 所有者がレポート画面から発行すれば現在の バージョン、受信者が受信メッセージから発行すれば配信されたバージョンです。 バージョンは変更されず個別に削除もされないため、後でレポートを編集しても公開ページは変わりません。 プレーンテキストのトークンが capability そのものなので、URL は秘密として扱ってください。

すべての共有は発行した本人が管理します。リンクの一覧・失効ができるのは発行者だけで、所有者と受信者の 一覧が混ざることはありません。

フィールド 説明
id string 一意の識別子。
reportContentId string このリンクが配信する不変なレポートバージョン。
token string capability トークン(22 文字の base64url 文字列)。公開 URL は /share/<token>
hasPasscode boolean 閲覧にパスコードが必要かどうか。パスコード自体はサーバーから出ません。
expiresAt string | null ISO 8601 の有効期限。無期限なら null
revokedAt string | null ISO 8601 の失効時刻。有効なら null
viewCount integer ページが閲覧された回数。
lastViewedAt string | null 最後に閲覧された ISO 8601 時刻、または null
createdAt string ISO 8601 の作成時刻。

GET /api/v1/reports/:id/shares scope: read

レポートの所有者が発行した共有(プレーンテキストのトークンを含む)を返します。配信の受信者が発行した リンクは受信トレイ側のビューに属し、ここには現れません。レポートの読み取りアクセスに従います。 所有者(現在のワークスペースメンバーシップで再チェック)、インスタンス管理者、または単一ワークスペース レポートのワークスペース管理者・オーナーです。それ以外は 404 を返します。

[
  {
    "id": "shr_ab12cd",
    "reportContentId": "rct_q2v3",
    "token": "Hs9Kp2mNv8rT3wYbL6dQx7",
    "hasPasscode": true,
    "expiresAt": "2026-07-28T00:00:00.000Z",
    "revokedAt": null,
    "viewCount": 4,
    "lastViewedAt": "2026-06-28T11:00:00.000Z",
    "createdAt": "2026-06-28T09:45:00.000Z"
  }
]

POST /api/v1/reports/:id/shares scope: write

所有者のみ(現在のワークスペースメンバーシップで再チェック)。レポートの現在の不変バージョンへの リンクを発行します。両フィールドとも任意で、空ボディはパスコードなし・無期限のリンクを発行します。

リクエストボディ

フィールド 必須 説明
passcode string いいえ 閲覧に必要なパスコード(4〜128 文字)。ハッシュ化して保存(PBKDF2)。
expiresInDays integer いいえ 失効までの日数(1〜365)。省略すると無期限。
curl -X POST "https://<your-instance>/api/v1/reports/rep_q2/shares" \
  -H "Authorization: Bearer spantail_pat_yourtoken" \
  -H "Content-Type: application/json" \
  -d '{ "passcode": "sunflower", "expiresInDays": 30 }'

201 Created を返します。

POST /api/v1/inbox/:id/shares scope: write GET /api/v1/inbox/:id/shares scope: read

Send-to の受信者は、受信トレイのメッセージにも同じ公開リンクを発行できます。 リンクが配信するのは配信されたバージョンそのものです。受信者のみが使え、送信者を含む他のユーザーには 404 を返します。受信コピーは受信者のものなので(既にダウンロードもできます)、発行時にワークスペース メンバーシップの再チェックはありません — 送信時の受信者検証が配布のゲートです。POST のボディは 共有の作成と同じで、GET はこのメッセージのバージョンに対して呼び出し元が発行した リンクを一覧します。

POST /api/v1/report-shares/:id/revoke scope: write

発行者のみ — レポート所有者、または受信トレイからリンクを発行した受信者。失効は露出を減らすだけなので、 ワークスペースメンバーシップの再チェックは省略されます。冪等で、再失効しても最初の revokedAt を保持 します。失効したリンクはコンテンツの配信を直ちに停止します。更新後の共有オブジェクトを返します。

curl -X POST "https://<your-instance>/api/v1/report-shares/shr_ab12cd/revoke" \
  -H "Authorization: Bearer spantail_pat_yourtoken"

公開ビューアは共有されたバージョンを /share/:token で HTML として配信します(/api/v1 プレフィックス なし・認証なし)。不正・不明・失効・期限切れのトークンはすべて同じ HTML の 404 を返すため、リンクが過去に存在した ことは決して明かされません。ページは noindexno-store・厳格な Content-Security-Policy で配信されます。

GET /share/:token public

レポートページを HTML で返します。共有にパスコードがある場合は、代わりにパスコード入力ページを返します。 下の POST フォームでパスコードを送信してください。

POST /share/:token public

フォームエンコードの passcode フィールドを受け付けます。正しいパスコードはレポートページを返し、 誤りはパスコードページを 401 で再表示します。パスコードのない共有はページを直接返します。

curl -X POST "https://<your-instance>/share/Hs9Kp2mNv8rT3wYbL6dQx7" \
  --data-urlencode "passcode=sunflower"

ディスカッションはレポート単位ではなく コンテンツバージョン 単位(/report-contents/:id/…)で 管理されます。送信されたバージョンごとに独立したスレッドを持つため、レポートを編集すると新しい ディスカッションが始まり、受信者は自分が受け取った本文そのものについてだけ議論します。ID は reportContentId から解決します — レポート(現行バージョン) または 受信メッセージ(配信されたバージョン)に 載っています。

バージョンのディスカッションは 参加者(レポート所有者とそのバージョンの Send-to 受信者)に限定 されます。参加者でないインスタンス管理者(または単一ワークスペースレポートのワークスペース管理者・ オーナー)は、レポートの読み取りアクセスのもとでスレッドを 読む ことはできますが、書き込みは参加者 専用です。コメントとリアクションは、そのバージョンが共有された後(配信が 1 件以上ある)にのみ書き込め ます。未送信のバージョンは空の読み取り専用スレッドです。

フィールド 説明
id string 一意の識別子。
reportContentId string このコメントが属するコンテンツバージョン。
authorUserId string | null 作成者。アカウント削除後は null(固定の authorName が単独で残る)。
authorName string 作成者の表示名。書き込み時に固定。
authorImageUrl string | null 作成者のライブアバター URL、または null
body string Markdown のコメント本文。
createdAt string ISO 8601 の作成時刻。
updatedAt string ISO 8601 の最終更新時刻。
editable boolean 呼び出し元が作成者のとき true(編集/削除メニューを駆動)。
reactions object[] このコメントへの集計済みリアクション(下記参照)。

リアクション集計 は 1 つの絵文字を集約します: { "emoji": "+1", "count": 2, "reactedByMe": true, "userNames": ["Ana", "Bo"] }。リアクション絵文字はグリフではなく安定したコンテンツキーです: +1-1laughhoorayconfusedheartrocketeyes

GET /api/v1/report-contents/:id/discussion scope: read

バージョンの本文レベルのリアクションとコメント(各自のリアクション付き)に加え、shared を返します。 一度も送信されていないバージョンでは sharedfalse(その場合 UI はパネルを隠します)。

curl "https://<your-instance>/api/v1/report-contents/rct_q2v3/discussion" \
  -H "Authorization: Bearer spantail_pat_yourtoken"

POST /api/v1/report-contents/:id/comments scope: write

参加者のみ。バージョンが共有済みである必要があります。作成したコメントを 201 で返します。

リクエストボディ

フィールド 必須 説明
body string はい Markdown のコメント(1〜10000 文字)。
curl -X POST "https://<your-instance>/api/v1/report-contents/rct_q2v3/comments" \
  -H "Authorization: Bearer spantail_pat_yourtoken" \
  -H "Content-Type: application/json" \
  -d '{ "body": "Looks great — shipping it." }'

PATCH /api/v1/report-contents/:id/comments/:commentId scope: write

作成者のみ。作成と同じ body フィールド。存在しないコメント・誤ったバージョン・非作成者はいずれも 404 を 返し、区別されません。

DELETE /api/v1/report-contents/:id/comments/:commentId scope: write

作成者のみ。204 No Content を返します。

バージョン本文へのリアクション

Section titled “バージョン本文へのリアクション”

PUT /api/v1/report-contents/:id/reactions scope: write

参加者のみ。バージョンが共有済みである必要があります。指定された絵文字での呼び出し元のリアクションを バージョン本文にトグルします(同じ絵文字で再度呼ぶと解除)。本文の更新後のリアクション集計を返します。

リクエストボディ

フィールド 必須 説明
emoji string はい リアクションキーのいずれか(+1-1laughhoorayconfusedheartrocketeyes)。
curl -X PUT "https://<your-instance>/api/v1/report-contents/rct_q2v3/reactions" \
  -H "Authorization: Bearer spantail_pat_yourtoken" \
  -H "Content-Type: application/json" \
  -d '{ "emoji": "rocket" }'

PUT /api/v1/report-contents/:id/comments/:commentId/reactions scope: write

参加者のみ。単一コメント(そのバージョンに属することを検証)への呼び出し元のリアクションをトグル します。そのコメントの更新後のリアクション集計を返します。

curl -X PUT "https://<your-instance>/api/v1/report-contents/rct_q2v3/comments/cmt_7x/reactions" \
  -H "Authorization: Bearer spantail_pat_yourtoken" \
  -H "Content-Type: application/json" \
  -d '{ "emoji": "heart" }'