API リファレンス
公開エンドポイントは読み取り専用で認証は不要、IP ごとにレート制限があります。`/me/*` エンドポイントはコマンドラインツール `bsbot` 用で、トークン(`Authorization: Bearer`)が必要です。トークンは `bsbot login` がブラウザ経由で取得します(`POST /cli/token`)。CORS ヘッダーは送信しません。メインサイトでのみ提供され、ボットのハンドルのサブドメインでは提供されません。バージョン管理: メジャーバージョンはパスに含まれます(`/api/v1`)。v1 には後方互換の変更(新しいエンドポイント、新しい任意のフィールドやパラメーター)だけが入ります。互換性のない変更は `/api/v2` として提供し、その後も v1 は少なくとも 6 か月間動作し続け、`Deprecation` と `Sunset` ヘッダーで告知されます。docs/api.md を参照してください。
- ベース URL
- https://bluesky.bot/api/v1
- バージョン
- 1.0.0
ハンドルは取得できる?
GET/handles/{name}/availability
取得時とまったく同じサーバー側のルールを適用します。形式、予約済みの名前、不適切な語句を確認し、最後にすでにボットが持っていないかを確認します。
パラメーター
| 名前 | 場所 | 型 | 説明 |
|---|---|---|---|
| name (必須) | path | string | 名前の部分。例: `weather`。`@weather.bluesky.bot` も受け付けます。 |
レスポンス
| ステータス | 説明 | 本文 |
|---|---|---|
| 200 | 空き状況。取得できない場合はその理由も返します。 | Availability |
| 404 | 見つかりません。ボットのハンドルのサブドメインでも返されます。API はメインサイトでのみ提供されます。 | Error |
| 429 | レート制限に達しました(ポリシー `publicApi`、IP ごと)。 | Error |
| 500 | 予期しないエラー。 | Error |
例
curl https://bluesky.bot/api/v1/handles/weather/availability取得済みハンドルの DID
GET/resolve/{handle}
`https://<handle>/.well-known/atproto-did` と同じ応答です。`*.bluesky.bot` ハンドルのみ対象です。
パラメーター
| 名前 | 場所 | 型 | 説明 |
|---|---|---|---|
| handle (必須) | path | string | 完全なハンドル。例: `weather.bluesky.bot`(大文字と小文字は区別しません)。 |
レスポンス
| ステータス | 説明 | 本文 |
|---|---|---|
| 200 | ハンドルとその DID。 | Resolution |
| 400 | `*.bluesky.bot` ハンドルではありません(コード `invalid_handle`)。 | Error |
| 404 | 見つかりません。ボットのハンドルのサブドメインでも返されます。API はメインサイトでのみ提供されます。 | Error |
| 429 | レート制限に達しました(ポリシー `publicApi`、IP ごと)。 | Error |
| 500 | 予期しないエラー。 | Error |
例
curl https://bluesky.bot/api/v1/resolve/weather.bluesky.botディレクトリに掲載されたボット
GET/bots
作成者がディレクトリに掲載したボットだけを、新しい順に返します。カーソルによるページ送り: 次のページを取得するには、ページの `cursor` を渡します。最後のページでは null です。
パラメーター
| 名前 | 場所 | 型 | 説明 |
|---|---|---|---|
| limit | query | integer (1–100), default 20 | |
| cursor | query | string | 前のページの不透明なカーソル。 |
| category | query | string | 完全一致のカテゴリ。 |
| verified | query | string: "true", "false" | ハンドルが Bluesky で有効な(true)、またはまだ有効でない(false)ボットだけ。 |
| q | query | string | ハンドルと表示名を対象にした、大文字と小文字を区別しない検索。 |
レスポンス
| ステータス | 説明 | 本文 |
|---|---|---|
| 200 | ボットの 1 ページ分。 | BotList |
| 400 | 無効なクエリパラメーター(コード `bad_request`)。 | Error |
| 404 | 見つかりません。ボットのハンドルのサブドメインでも返されます。API はメインサイトでのみ提供されます。 | Error |
| 429 | レート制限に達しました(ポリシー `publicApi`、IP ごと)。 | Error |
| 500 | 予期しないエラー。 | Error |
例
curl https://bluesky.bot/api/v1/botsディレクトリに掲載された 1 つのボット
GET/bots/{handle}
パラメーター
| 名前 | 場所 | 型 | 説明 |
|---|---|---|---|
| handle (必須) | path | string | 完全なハンドル。例: `weather.bluesky.bot`(大文字と小文字は区別しません)。 |
レスポンス
| ステータス | 説明 | 本文 |
|---|---|---|
| 200 | ボット。 | Bot |
| 404 | 見つかりません。ボットのハンドルのサブドメインでも返されます。API はメインサイトでのみ提供されます。 | Error |
| 429 | レート制限に達しました(ポリシー `publicApi`、IP ごと)。 | Error |
| 500 | 予期しないエラー。 | Error |
例
curl https://bluesky.bot/api/v1/bots/weather.bluesky.botCLI のサインインコードをトークンと交換する
POST/cli/token
`bsbot login` のステップ 4: /cli/authorize が CLI のループバックアドレスに渡したワンタイムコードを、PKCE 検証子と同じリダイレクト URI と一緒に送ります。コードは 1 回だけ、2 分間有効で、失敗した試行で無効になります。トークンの有効期間は 30 日です。IP ごとにレート制限があります(`cliToken`)。
レスポンス
| ステータス | 説明 | 本文 |
|---|---|---|
| 200 | `/me/*` エンドポイント用のトークン。 | CliToken |
| 400 | 本文の形式が不正(`bad_request`)、またはコードが不明・期限切れ・使用済みか、検証子やリダイレクト URI と一致しません(`invalid_grant`)。 | Error |
| 404 | 見つかりません。ボットのハンドルのサブドメインでも返されます。API はメインサイトでのみ提供されます。 | Error |
| 429 | レート制限に達しました(ポリシー `publicApi`、IP ごと)。 | Error |
| 500 | 予期しないエラー。 | Error |
例
curl \
-X POST \
-H "Content-Type: application/json" \
-d '{"code":"…","code_verifier":"…","redirect_uri":"…"}' \
https://bluesky.bot/api/v1/cli/tokenトークンのアカウント
GET/me
レスポンス
| ステータス | 説明 | 本文 |
|---|---|---|
| 200 | あなたのアカウントとトークンの有効期限。 | Me |
| 401 | トークンがない、期限切れ、または取り消されています(コード `unauthorized`)。もう一度 `bsbot login` を実行してください。 | Error |
| 404 | あなたのアカウントにそのボットがないか、ボットのハンドルのサブドメインです(API はメインサイトでのみ提供されます)。 | Error |
| 429 | レート制限に達しました: IP ごとの `publicApi`、アカウントごとの `creatorApi`、そして取得・切り替え・確認・解放に対するアカウントごとの `handleChange`(ダッシュボードと共有)。 | Error |
| 500 | 予期しないエラー。 | Error |
例
curl \
-H "Authorization: Bearer $BLUESKY_BOT_TOKEN" \
https://bluesky.bot/api/v1/me自分のボット
GET/me/bots
ディレクトリへの掲載の有無にかかわらず、あなたのアカウントのすべてのボットを古い順に返します。ボットの追加はダッシュボードから行います。ボットのアカウントでのサインインが必要です。
レスポンス
| ステータス | 説明 | 本文 |
|---|---|---|
| 200 | あなたのボット。 | MyBotList |
| 401 | トークンがない、期限切れ、または取り消されています(コード `unauthorized`)。もう一度 `bsbot login` を実行してください。 | Error |
| 404 | あなたのアカウントにそのボットがないか、ボットのハンドルのサブドメインです(API はメインサイトでのみ提供されます)。 | Error |
| 429 | レート制限に達しました: IP ごとの `publicApi`、アカウントごとの `creatorApi`、そして取得・切り替え・確認・解放に対するアカウントごとの `handleChange`(ダッシュボードと共有)。 | Error |
| 500 | 予期しないエラー。 | Error |
例
curl \
-H "Authorization: Bearer $BLUESKY_BOT_TOKEN" \
https://bluesky.bot/api/v1/me/bots自分のボットにハンドルを取得し、切り替える
POST/me/bots/{did}/claim
ダッシュボードと同じルールです。形式、予約済みの名前、不適切な語句、空き状況(一意インデックスで保証)、解放されたハンドルの猶予期間を確認します。そのあと、ボットのハンドルをすぐに Bluesky で切り替えます。結果は `switch` に入ります。すでにハンドルを持つボットのハンドルを変更すると、古いハンドルは解放されます。
パラメーター
| 名前 | 場所 | 型 | 説明 |
|---|---|---|---|
| did (必須) | path | string | `GET /me/bots` が返すボットの DID。 |
レスポンス
| ステータス | 説明 | 本文 |
|---|---|---|
| 200 | 取得したハンドルと切り替えの結果。 | ClaimResult |
| 400 | 本文の形式が不正(`bad_request`)、または使用できない名前です(`invalid_handle`、`reason` 付き)。 | Error |
| 401 | トークンがない、期限切れ、または取り消されています(コード `unauthorized`)。もう一度 `bsbot login` を実行してください。 | Error |
| 403 | ボットは停止されています(`forbidden`)。 | Error |
| 404 | あなたのアカウントにそのボットがないか、ボットのハンドルのサブドメインです(API はメインサイトでのみ提供されます)。 | Error |
| 409 | 別のボットがそのハンドルを持っているか、猶予期間中です(`conflict`、理由は `taken`)。 | Error |
| 429 | レート制限に達しました: IP ごとの `publicApi`、アカウントごとの `creatorApi`、そして取得・切り替え・確認・解放に対するアカウントごとの `handleChange`(ダッシュボードと共有)。 | Error |
| 500 | 予期しないエラー。 | Error |
例
curl \
-X POST \
-H "Authorization: Bearer $BLUESKY_BOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"weather"}' \
https://bluesky.bot/api/v1/me/bots/did:plc:yourbot/claim取得済みハンドルを使うよう、ボットの PDS にもう一度依頼する
POST/me/bots/{did}/switch
パラメーター
| 名前 | 場所 | 型 | 説明 |
|---|---|---|---|
| did (必須) | path | string | `GET /me/bots` が返すボットの DID。 |
レスポンス
| ステータス | 説明 | 本文 |
|---|---|---|
| 200 | 切り替えの結果。 | SwitchResult |
| 401 | トークンがない、期限切れ、または取り消されています(コード `unauthorized`)。もう一度 `bsbot login` を実行してください。 | Error |
| 404 | あなたのアカウントにそのボットがないか、ボットのハンドルのサブドメインです(API はメインサイトでのみ提供されます)。 | Error |
| 429 | レート制限に達しました: IP ごとの `publicApi`、アカウントごとの `creatorApi`、そして取得・切り替え・確認・解放に対するアカウントごとの `handleChange`(ダッシュボードと共有)。 | Error |
| 500 | 予期しないエラー。 | Error |
例
curl \
-X POST \
-H "Authorization: Bearer $BLUESKY_BOT_TOKEN" \
https://bluesky.bot/api/v1/me/bots/did:plc:yourbot/switch取得済みハンドルが Bluesky で有効か確認する
POST/me/bots/{did}/verify
パラメーター
| 名前 | 場所 | 型 | 説明 |
|---|---|---|---|
| did (必須) | path | string | `GET /me/bots` が返すボットの DID。 |
レスポンス
| ステータス | 説明 | 本文 |
|---|---|---|
| 200 | 確認の結果。 | SwitchResult |
| 401 | トークンがない、期限切れ、または取り消されています(コード `unauthorized`)。もう一度 `bsbot login` を実行してください。 | Error |
| 404 | あなたのアカウントにそのボットがないか、ボットのハンドルのサブドメインです(API はメインサイトでのみ提供されます)。 | Error |
| 429 | レート制限に達しました: IP ごとの `publicApi`、アカウントごとの `creatorApi`、そして取得・切り替え・確認・解放に対するアカウントごとの `handleChange`(ダッシュボードと共有)。 | Error |
| 500 | 予期しないエラー。 | Error |
例
curl \
-X POST \
-H "Authorization: Bearer $BLUESKY_BOT_TOKEN" \
https://bluesky.bot/api/v1/me/bots/did:plc:yourbot/verifyボットのハンドルを解放する
POST/me/bots/{did}/release
可能であればボットは以前の Bluesky ハンドルに戻り、ハンドルは名前解決されなくなります。猶予期間中は、ほかの人はそのハンドルを使えません。
パラメーター
| 名前 | 場所 | 型 | 説明 |
|---|---|---|---|
| did (必須) | path | string | `GET /me/bots` が返すボットの DID。 |
レスポンス
| ステータス | 説明 | 本文 |
|---|---|---|
| 200 | 解放したハンドルと、元に戻した結果。 | ReleaseResult |
| 401 | トークンがない、期限切れ、または取り消されています(コード `unauthorized`)。もう一度 `bsbot login` を実行してください。 | Error |
| 403 | ボットは停止されています(`forbidden`)。 | Error |
| 404 | あなたのアカウントにそのボットがないか、ボットのハンドルのサブドメインです(API はメインサイトでのみ提供されます)。 | Error |
| 409 | ボットに解放するハンドルがありません(`conflict`、理由は `no_handle`)。 | Error |
| 429 | レート制限に達しました: IP ごとの `publicApi`、アカウントごとの `creatorApi`、そして取得・切り替え・確認・解放に対するアカウントごとの `handleChange`(ダッシュボードと共有)。 | Error |
| 500 | 予期しないエラー。 | Error |
例
curl \
-X POST \
-H "Authorization: Bearer $BLUESKY_BOT_TOKEN" \
https://bluesky.bot/api/v1/me/bots/did:plc:yourbot/releaseこのリクエストのトークンを取り消す
DELETE/me/token
`bsbot logout` が呼び出すもの。
レスポンス
| ステータス | 説明 | 本文 |
|---|---|---|
| 204 | 取り消しました。本文はありません。 | |
| 401 | トークンがない、期限切れ、または取り消されています(コード `unauthorized`)。もう一度 `bsbot login` を実行してください。 | Error |
| 404 | あなたのアカウントにそのボットがないか、ボットのハンドルのサブドメインです(API はメインサイトでのみ提供されます)。 | Error |
| 429 | レート制限に達しました: IP ごとの `publicApi`、アカウントごとの `creatorApi`、そして取得・切り替え・確認・解放に対するアカウントごとの `handleChange`(ダッシュボードと共有)。 | Error |
| 500 | 予期しないエラー。 | Error |
例
curl \
-X DELETE \
-H "Authorization: Bearer $BLUESKY_BOT_TOKEN" \
https://bluesky.bot/api/v1/me/tokenスキーマ
Error
| フィールド | 型 | 説明 |
|---|---|---|
| error (必須) | object | |
| error.code (必須) | string: "bad_request", "invalid_handle", "not_found", "rate_limited", "internal_error", "unauthorized", "forbidden", "conflict", "invalid_grant" | |
| error.message (必須) | string | |
| error.reason | string | `invalid_handle`、`conflict`、`forbidden` の場合。例: `reserved`、`taken`、`no_handle`、`suspended`。 |
| error.parameter | string | 無効なクエリパラメーター。 |
| error.retryAfterSeconds | integer (1–) | `rate_limited` の場合。 |
Availability
| フィールド | 型 | 説明 |
|---|---|---|
| name (必須) | string | 正規化した名前(無効な場合は入力どおり)。 |
| handle (必須) | string | null | 完全なハンドル。例: `weather.bluesky.bot`。名前が無効な場合は null。 |
| available (必須) | boolean | |
| reason (必須) | null | string: "required", "too_short", "too_long", "invalid_characters", "invalid_hyphen", "reserved", "not_allowed", "taken" | 取得できない理由。取得できる場合は null。名前は 3〜30 文字で、a-z、0-9、連続しないハイフンを使えます。 |
Resolution
| フィールド | 型 | 説明 |
|---|---|---|
| handle (必須) | string | |
| did (必須) | string |
Bot
| フィールド | 型 | 説明 |
|---|---|---|
| did (必須) | string | |
| handle (必須) | string | |
| displayName (必須) | string | null | |
| avatar (必須) | string | null | アバターの URL。 |
| description (必須) | string | null | |
| category (必須) | string | null | |
| verifiedAt (必須) | string | null, date-time | ハンドルが Bluesky で有効と確認された日時。まだの場合は null。 |
BotList
| フィールド | 型 | 説明 |
|---|---|---|
| bots (必須) | Bot[] | |
| cursor (必須) | string | null | 次のページのカーソル。最後のページでは null。 |
CliTokenRequest
| フィールド | 型 | 説明 |
|---|---|---|
| code (必須) | string | |
| code_verifier (必須) | string | PKCE 検証子(RFC 7636)。 |
| redirect_uri (必須) | string | /cli/authorize で使ったものと同じ `http://127.0.0.1:<port>/callback`。 |
CliToken
| フィールド | 型 | 説明 |
|---|---|---|
| token (必須) | string | 秘密にしてください。`/me/*` であなたとして動作します。 |
| tokenType (必須) | string = "Bearer" | |
| expiresAt (必須) | string, date-time | |
| creator (必須) | Account |
Account
| フィールド | 型 | 説明 |
|---|---|---|
| did (必須) | string | |
| handle (必須) | string | あなたの Bluesky ハンドル。 |
| displayName | string | null |
Me
| フィールド | 型 | 説明 |
|---|---|---|
| creator (必須) | Account | |
| token (必須) | object | |
| token.name (必須) | string | ログイン時に指定したマシン名。 |
| token.createdAt (必須) | string, date-time | |
| token.expiresAt (必須) | string, date-time |
MyBot
| フィールド | 型 | 説明 |
|---|---|---|
| did (必須) | string | |
| handle (必須) | string | null | 取得した `*.bluesky.bot` ハンドル。ない場合は null。 |
| previousHandle (必須) | string | null | ここでハンドルを取得する前のボットのハンドル。 |
| displayName (必須) | string | null | |
| avatar (必須) | string | null | |
| verifiedAt (必須) | string | null, date-time | 取得したハンドルが Bluesky で有効と確認された日時。 |
| listed (必須) | boolean | 公開ディレクトリに表示されるかどうか。 |
| status (必須) | string: "active", "suspended" |
MyBotList
| フィールド | 型 | 説明 |
|---|---|---|
| bots (必須) | MyBot[] |
ClaimRequest
| フィールド | 型 | 説明 |
|---|---|---|
| name (必須) | string | 名前の部分。例: `weather.bluesky.bot` なら `weather`。 |
SwitchOutcome
| フィールド | 型 | 説明 |
|---|---|---|
| status (必須) | string: "verified", "pending", "manual" | |
| verifiedAt | string, date-time | |
| reason | string: "reauthorize", "pds_refused", "pds_unreachable" |
ClaimResult
| フィールド | 型 | 説明 |
|---|---|---|
| handle (必須) | string | |
| switch (必須) | SwitchOutcome |
SwitchResult
| フィールド | 型 | 説明 |
|---|---|---|
| switch (必須) | SwitchOutcome |
ReleaseResult
| フィールド | 型 | 説明 |
|---|---|---|
| handle (必須) | string | 解放したハンドル。 |
| revert (必須) | object | `reverted`: ボットは `handle` に戻りました。`manual`: Bluesky でボットのハンドルを自分で変更してください。理由は `reason` に入ります。 |
| revert.status (必須) | string: "reverted", "manual" | |
| revert.handle | string | |
| revert.reason | string: "reauthorize", "pds_refused", "pds_unreachable", "no_previous_handle" | |
| revert.previousHandle | string | null |