Bitwarden Send を API 的に扱うための自動化アイディア
朝比奈幸太郎リリース:音のアプリ使い放題プラットフォーム『空音開発』
Bitwarden の Send は、ブラウザ拡張やデスクトップアプリから手軽に呼び出せる一時共有機能ですが、外部アプリケーションから自動的に Send を発行したい場合、公式の Public REST API には対応するエンドポイントが用意されていません。
Send の自動化を考えるとき、選択肢は事実上 Bitwarden CLI の bw send コマンドと、CLI に同梱されている bw serve によるローカル REST サーバの 2 つに絞られます。
本記事ではその選択肢を整理し、Python と Rust から扱うときの実装方針、そして Send の自動化が活きる具体的なユースケースを並べます。
Bitwarden Send の位置づけ
Send は Bitwarden 本体 Vault のアイテム共有とは別系統の機能で、テキストまたはファイルを一時 URL として配布できる仕組みです。
期限、最大アクセス回数、パスワード保護、メール認証などの制御が用意されており、メール認証はプレミアム機能で利用できます。
共有後のリンクは Bitwarden アカウント不要で受け取れます。
Bitwarden 本体の解説については過去記事に譲り、本稿は Send を API として扱う観点に集中します。
公式 Public API に Send が存在しない件
Bitwarden Public API は、組織のメンバー、コレクション、グループの管理を主目的とする運用 API です。
組織管理者がオンボーディングや権限管理を自動化することを想定しており、Vault アイテムや Send の作成・取得には対応していません。
Send 用の内部 API は vault.bitwarden.com/api/sends/... で動作していますが、これは公式に「内部実装であり予告なく変更されうる」と明言されています。
外部アプリから安定して Send を扱う前提では、内部 API を直接叩く選択肢は採用に値しません。
選択肢 1: Bitwarden CLI の bw send
CLI 単体で Send の作成、参照、編集、削除が可能です。テキスト Send であれば、一行で次のように書けます。
bw send -n "My First Send" -d 7 --hidden "共有したい中身"
-d 7 は期限 7 日、--hidden は受信側でクリックして初めて中身を表示する設定です。
より細かい制御が必要な場合は、テンプレートを編集する流儀が使えます。
bw send template send.text \
| jq '.name="My Send" | .text.text="secret" | .password="p@ss"' \
| bw encode \
| bw send create
ファイル Send なら bw send -f ./path/to/file.ext で発行できます。
list / get / edit / delete / receive といったサブコマンドも揃っており、CLI のみで Send の CRUD を一通りスクリプト化できます。
シェルから外部プロセスとして CLI を呼ぶ構成はシンプルですが、起動コストと標準入出力のハンドリングが毎回発生するため、頻度の高い自動化には向きません。
選択肢 2: bw serve でローカル REST を立てる
bw serve は CLI に組み込まれたコマンドで、起動するとローカルに HTTP サーバが立ち上がり、Vault Management API と呼ばれる RESTful なエンドポイント群が利用可能になります。
デフォルトは localhost:8087 で、--hostname と --port で変更できます。
bw serve --port 8087
別シェルからは curl で直接叩けます。
curl -X POST http://localhost:8087/send \
-H "Content-Type: application/json" \
-d '{"name":"test","text":{"text":"hello","hidden":false},"deletionDate":"2026-05-24T00:00:00.000Z"}'
Send 関連のエンドポイントは /send、/list/object/send、/object/send/{id} などが用意されています。CLI を毎回 exec する構成と比べ、HTTP クライアントから直接叩けるため、Python や Rust のような言語からの統合が大幅に簡単になります。
CLI 経由と bw serve 経由の比較
| 観点 | bw send を exec |
bw serve の REST |
|---|---|---|
| 呼び出しコスト | 毎回プロセス起動 | 起動済みプロセスへの HTTP |
| 統合のしやすさ | shell スクリプト向き | アプリ組み込み向き |
| 並列性 | プロセス並列 | HTTP の並列で素直に組める |
| デプロイ要件 | CLI バイナリのみ | CLI バイナリ + 常駐プロセス |
短い一発の運用なら CLI 直叩き、継続的な自動化や Web アプリへの組み込みなら bw serve が筋の良い選択になります。
Python での実装方針
bw serve を前提にすれば、Python からは requests か httpx で localhost:8087 を叩くだけで Send が作成できます。
最小例は次のとおりです。
import httpx
from datetime import datetime, timedelta, timezone
deletion = (datetime.now(timezone.utc) + timedelta(days=3)).isoformat()
payload = {
"name": "API test",
"text": {"text": "hello from python", "hidden": True},
"deletionDate": deletion,
}
res = httpx.post("http://localhost:8087/send", json=payload, timeout=10)
res.raise_for_status()
print(res.json()["data"]["accessUrl"])
エラーハンドリング、ロック状態の検知に /status エンドポイント、/unlock の自動化を組み合わせれば、長時間動くワーカープロセスから安全に Send を発行できます。
FastAPI で Send 発行用の内部 API を作り、社内システムから叩く構成も現実的です。
Rust での実装方針
筆者はRust環境もあるので、Rustでの例もメモしておきます。
Rust の場合は reqwest と serde の組み合わせで型付きの Send クライアントを書けます。
レスポンスに含まれる accessUrl、id、deletionDate などを構造体にマップしておけば、CI パイプラインの一部として安全に組み込めます。
use reqwest::Client;
use serde::{Deserialize, Serialize};
#[derive(Serialize)]
struct SendText { text: String, hidden: bool }
#[derive(Serialize)]
struct SendBody {
name: String,
text: SendText,
#[serde(rename = "deletionDate")]
deletion_date: String,
}
#[derive(Deserialize, Debug)]
struct SendResponse { data: SendData }
#[derive(Deserialize, Debug)]
struct SendData {
id: String,
#[serde(rename = "accessUrl")]
access_url: String,
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let body = SendBody {
name: "rust send".into(),
text: SendText { text: "hi".into(), hidden: true },
deletion_date: "2026-05-24T00:00:00.000Z".into(),
};
let res = Client::new()
.post("http://localhost:8087/send")
.json(&body)
.send().await?
.error_for_status()?
.json::<SendResponse>().await?;
println!("{}", res.data.access_url);
Ok(())
}
Rust は型でリクエストとレスポンスを縛れるため、Send の仕様変更が起きたときにコンパイル時点で検出しやすい利点があります。
Axum や Actix Web から Send 発行用のマイクロサービスを切り出す構成にも向いています。
活用アイディア 4 選
A. CI/CD で一時的な秘密値を配布する
ビルド成果物のうち、平文では出したくない接続情報やトークンを Send として発行し、URL だけを Slack や Email に流す構成です。
期限と最大アクセス回数を組み合わせれば、配布先の不注意による漏洩リスクを実用的な水準まで抑えられます。
CI の最終ステップに bw serve 経由の HTTP POST を一発挟むだけで成立します。
B. 開発環境用 .env の安全な共有
チームに新メンバーが加わったとき、.env をチャットに貼るのではなく、パスワード保護付きの Send として発行し、URL とパスワードを別経路で送る運用です。
受け取り側は CLI の bw send receive でも、ブラウザでも取得でき、一度取得済みであれば期限切れにできるためログに残り続けません。
C. 顧客サポートにおける一時ファイル送付
サポート担当が顧客に対し、ログのサンプルや設定ファイルの雛形を送るとき、メール添付や恒久 URL ではなく Send にする運用です。
社内ツールから「この顧客にこのファイルを送る」操作をワンクリックで行えるようにし、裏で bw serve の /send を叩く構成にすれば、配布物のトレーサビリティを保ちつつ運用負荷を下げられます。
D. 自動化された秘密情報のローテーション通知
定期的にローテーションする API キーや一時パスワードを、新しい値が発行されるたびに自動で Send として作成し、関係者に URL を通知するワークフローです。
Rust や Python のバッチジョブから bw serve を叩く構成と相性がよく、配布履歴は Send 側に残ります。
受信側が古い URL を踏むと期限切れで弾かれるため、誤った値の使用が物理的に防げます。
運用上の注意点
bw serve のローカル REST は認証を持たない構成のため、ローカルホストの外に公開してはいけません。
コンテナで動かす場合は --hostname 127.0.0.1 のままにし、必要であれば前段にリバースプロキシと認証を置く設計が必要です。
bw serve はあらかじめ bw login と bw unlock を済ませた状態を前提とするため、長時間動作するワーカープロセスでは BW_SESSION の有効性と自動再ロックの挙動を踏まえた監視が要ります。
公式 Public API に Send が含まれていない以上、bw serve を使う構成は CLI のライフサイクルに依存します。
CLI のアップデートでエンドポイント仕様が変わる可能性は残るため、運用前にバージョン固定とリグレッションテストを用意しておく価値があります。
出典
- Send from CLI | Bitwarden: https://bitwarden.com/help/send-cli/
- Password Manager APIs | Bitwarden: https://bitwarden.com/help/bitwarden-apis/
- Bringing a RESTful API to the Bitwarden CLI | Bitwarden: https://bitwarden.com/blog/bringing-restful-api-to-the-bitwarden-cli/
- The Vault management API, a visual guide | Bitwarden Community Forums: https://community.bitwarden.com/t/the-vault-management-api-a-visual-guide/85500
- Bitwarden Public API | Bitwarden: https://bitwarden.com/help/public-api/
- Send Operations | bitwarden/cli | DeepWiki: https://deepwiki.com/bitwarden/cli/4.4-send-operations