Introduction

Pulsate Specification は Pulsate プロジェクトに関するAPIエンドポイントや設計などの仕様を記述したドキュメントです.

プロジェクトの概要については こちら をご覧ください.

note

この仕様書は現在開発中の Pulsate v0.1 となります. 今後のバージョンアップにより仕様が変更される可能性があります.

プロジェクト概要

プロジェクトの目標

高速で安全な ActivityPub 実装

  1. パフォーマンス重視

  2. セキュリティ重視

  3. ActivityPub 仕様の重視

実装方針

パフォーマンス・セキュリティの強化

  • Misskey や Mastodon よりも高速に動作する次世代の ActivityPub 実装.
    • 各APIリクエストに対するレスポンスを始めとするパフォーマンスの向上(タイムラインの読み込み, メディアのレスポンスなど).
  • TypeScript での開発を行い, パフォーマンスの向上を図る.
    • TypeScript は JavaScript に比べて型安全性が高く, パフォーマンスが向上する.
  • SQL Injection や XSS などセキュリティに関わる脆弱性が少ない. 見つかったとしてもすぐに修正できる仕組みづくり.
    • パスワードレスログイン, 2FA など.

ActivityPub 実装の重視

  • 無駄な機能は実装せずあくまで ActivityPub の実装として忠実に従う.
  • MFM など特定の分散型ソフトウェアのみの実装に従わない. ただし Mastodon や Misskey などの主要実装が互いに実装している機能は実装する. (引用など)

クライアント, App 周りのサポートの強化

  • PWA は対応状況が酷い.
    • Chromium系ブラウザは概ね対応しているが, Firefox や Safari は対応していない.
  • ターゲットはモバイルユーザーが大半だと考え, Pulsate ではネイティブアプリとして iOS App, Android App をリリースする(構想段階).
  • ネイティブアプリと同様コミュニティが開発するサードパーティクライアントも尊重し, API リファレンスなどリソースを多く用意しコミュニティの開発を支援する.

開発手法の厳格化 / 改善

  • semver (セマンティックバージョニング) に従い, 破壊的変更をなるべく少なくする. 破壊的変更が行われる場合は予めコミュニティに通告する.
  • Rust のエディション方式を採用し, 同じエディション内では基本的に後方互換性を保つ.
    • エディションが切り替わる = リリース の切り替わり (メジャーバージョンアップ)
  • またエディションをまたぐときには, そのエディションの変更点をまとめたガイドを提供したりスクリプトを提供することで, 既存のインスタンスを新しいエディションに対応させる手助けをする.
    • これは Rust の思想を受けたもの.

Rust 1.0 のリリースでは、Rust のコア機能として「よどみない安定性」が提供されるようになりました。 Rust は、1.0 のリリース以来、いちど安定版にリリースされた機能は、将来の全リリースに渡ってサポートし続ける、というルールの下で開発されてきました。

一方で、後方互換でないような小さい変更を言語に加えることも、ときには便利です。 最もわかりやすいのは新しいキーワードの導入で、これは同名の変数を使えなくします。 例えば、Rust の最初のバージョンには asyncawait といったキーワードはありませんでした。 後のバージョンになってこれらを突然キーワードに変えてしまうと、例えば let async = 1; のようなコードが壊れてしまいます。

我々は、クレートを新しいエディションにアップグレードするのが簡単になるよう目指しています。 新しいエディションがリリースされるとき、我々は移行を自動化するツールも提供します。 このツールは、新しいエディションに適合させるために必要な小さな変更をコードに施します。 例えば、Rust 2018 への移行の際は、async と名のつく全てのものを、等価な生識別子構文である r#async へと書き換える、といった具合です。

ref: エディションとは? - Rust エディションガイド

コミュニティの声を聞く

  • 簡単に言えば Discord や GitHub Discussions の採用.
  • バグ報告は基本的に インスタンス管理者 , ユーザー から受けるのが多いと考えるため, Discord での報告も受け付ける. (GitHub Issues には Discord Bot を使ってうまく Import する)

プロジェクトコードネーム

Pulsate

  • 意味: 脈打つ, 鼓動する; 〈光・音などが〉振動する; ドキドキする; など.
  • 由来: indigo la End のアルバム "PULSATE" から.

バージョンコードネーム

v0, v1 - Antenna

v0 (開発途上バージョン), v1 (最初の安定版) のコードネーム.

由来は Mrs. GREEN APPLE の ANTENNA から.

ER図 (WIP)

ER図

Mermaid code
erDiagram
account {
  string id PK
  string name
	string nickname
	string mail
  string passphrase_hash
  string bio
  int role "権限"
  int status "アカウントの状態"
	datetime created_at
	datetime updated_at
	datetime deleted_at
}
account ||--o{ note : "has"
account ||--o{ list : "has"
account ||--o{ bookmark : "has"
account ||--o{ following : "has"
account ||--o{ medium : "hosts"
account ||--o{ reaction : "has"

following {
	string from FK
  string to FK
	int state "FOLLOWING/REQUESTING_FOLLOW/BLOCKINGの3値を取る"
	datetime created_at
	datetime updated_at
	datetime deleted_at
}


note {
  string id PK
  string text "投稿本文"
  string author_id FK "投稿者のID"
  int visibility "公開範囲"
	datetime created_at
	datetime deleted_at
}
note ||--o{ bookmark : "has"
note ||--o{ reaction : "has"

reaction {
  string reacted_by FK "リアクションしたユーザーID"
  string reacted_to FK "リアクションしたノートID"
  string body "内容(絵文字)"
	datetime created_at
	datetime deleted_at
}

bookmark {
  string note_id FK
  string author_id FK "ブックマークをしたユーザーID"
	datetime created_at
	datetime deleted_at
}

list {
  string id PK
  string title "リスト名"
  int visibility "公開するかどうか"
	datetime created_at
	datetime updated_at
	datetime deleted_at
}
list ||--o{ list_member : "has"

list_member {
  string list_id FK
  string member_id FK "メンバのアカウントID"
	datetime created_at
	datetime deleted_at
}
list_member }o--|| account : ""

medium {
  string id PK
  string name "ファイル名"
  string mime "mime type"
  string author_id FK
	datetime created_at
	datetime deleted_at
}

note_attachment {
	string medium_id FK
	string note_id FK
  string alt "altテキスト"
	datetime created_at
	datetime deleted_at
}
note_attachment }o--|| note: ""
note_attachment }o--|| medium: "references"

  • 未定義リスト
    • リノートの扱い
      1. notesがrenoteに対してリレーションを持つようにする
      2. notesにrenote先のIDを持たせる
    • 登録中アカウント用のテーブルを作るか否か
    • アカウント(同士の)関係

note

ドライブが階層構造などを持たないという仕様になった上, 一旦これ以上は複雑化させない方針になっているのでメディアが直接アカウントに紐づく形になっています.

important

CONSIDERATIONS:

  • note_attachements との関連は多対多になるかも?
  • accounts に bookmarks が直接関連しているのは正しいのか?

モデルリファレンス

ID

Twitter の Snowflake をベースに, 次のようなビットフィールド (図はビッグエンディアン) からなる 64 ビット整数です.

先頭に時刻を含んでいるため, そのまま時刻順にソートが可能です.

111111111111111111111111111111111111111111 1111111111 111111111111
64                                         22         12          0
timestamp                                  worker id  incremental

各ビットフィールドの意味は以下のとおりです.

フィールドビット範囲意味
timestamp[64, 22)Pulsate エポックからのミリ秒数. エポックは 2022 年 1 月 1 日 0 時 0 分 0.000 秒. UNIX 時間のミリ秒に 1640995200000 を足すことでこれに変換可能.
worker id[22, 12)この ID を生成したワーカーの識別子
incremental[12, 0)ワーカーにて同一時刻で ID を生成する度に増える値

TypeScript 上ではこのような型として表現します. 型引数によりエンティティ間で ID を取り違えるようなミスを防ぎます.

declare const snowflakeNominal: unique symbol;
export type ID<T> = string & { [snowflakeNominal]: T };

認証トークン

JSON Web Token の一種で, ペイロードには 更新トークン など以下の情報を含みます.

更新トークンも JWT なので, JWT がネストしています.

  • sub: 発行対象のアカウント名
  • iat: 発行時刻 (UNIX エポックの秒数)
{
  "sub": "hogehoge-user",
  "iat": 1640995201
}

このトークンの有効期限は発行時刻から 15 分 (900 秒) です.

生成や検証の自作は実装ミスによる脆弱性を誘発しますのでライブラリを利用します.

更新トークン

JSON Web Token の一種で, ペイロードには以下の情報を含みます.

{
  "sub": "3e1644833000002",
  "iat": 1640995201
}

このトークンの有効期限は発行時刻から 30 日 (2,592,000 秒) です. 特に再発行はされず, 手動でのログイン時にのみ発行されます.

なおこのトークンは長命なので, 利用後に無効化しておかないと奪取されて再利用されるリスクがあります. 危険度は高いですがネットワーク上に流れることがほとんどないため, このリスクには対処せず保有することにします.

連合

このシステムが実際に稼働しているプロセスを表すものです. この連合 (つまり Pulsate サーバーのインスタンス) は次の属性を持ちます.

  • id: すべての連合において一意な ID
  • origin: オリジン
  • name: 名称
  • description: 説明
  • version: (ソフトウェア)バージョン
  • software_name : ソフトウェア名
  • extensions: 拡張対応リスト
  • maintainer_name : 管理者名

アカウント

自然人, 団体, ボットなど, このシステム上でオブジェクトを発行する主体となるものです. これは次の制約を持つ属性を備えます.

  • name: アカウント名
    • 1 文字以上の URL 安全な ASCII 文字からなる
  • nickname: 表示名, アカウントの表示に用いる自然言語の名称
    • 初期値は空文字列
    • 空文字列の場合はアカウント名にフォールバックする
    • RTL 制御文字を除く任意の UTF-8 シーケンス
  • created_at: このアカウントが作成された時刻
  • mail: メールアドレス
    • 有効なメールアドレスであることが検証済み
  • passphrase_hash: パスフレーズのハッシュ
    • 元となったパスフレーズは以下の性質を満たします
      • 文字種は正規化された UTF-8 シーケンス
      • 連続する空白タイプの文字 (スペース, タブ, 全角スペース, 改行文字など) は 1 つの半角スペースへと置き換えられる
      • 長さは Unicode スカラー値で 8 つぶん以上
  • salt: パスフレーズのハッシュに使ったソルト
    • パスフレーズの平文にこれを連結したもののハッシュは, passphrase_hash に等しい

なお, 基本情報はアカウント ID に関連付けられるようにし, このモデル自体は基本情報を保持しません.

アカウント状態

アカウント状態図

Mermaid code
stateDiagram-v2
	NOT_ACTIVATED --> ACTIVE
	ACTIVE --> FROZEN
	ACTIVE --> SILENCED
	SILENCED --> FROZEN
	FROZEN --> SILENCED
	SILENCED --> ACTIVE
	FROZEN --> ACTIVE

登録中アカウント

まだ実際にアカウントが発行されておらず, メールアドレスを検証するスキームに入れられているアカウントです. アカウントに加えて次の属性を持っており, このアカウントは通常のアカウントとは別の領域に永続化されます.

  • state: メールアドレスの検証のために mail へと送信した暗号学的乱数

なお, 登録中アカウントが追加されてから 168 時間(7days) が経過したものは無効とみなします.

アカウント関係

アカウントが他のアカウントに対してどのような関係性を持っているかを表すステートマシンです. あるアカウントから他のアカウントに対しては次のような関係が存在します.

  • NONE: なし
  • REQUESTING_FOLLOW: フォローリクエスト中
  • FOLLOWING: フォロー中
  • BLOCKING: ブロック中

そしてこれらの関係は次の遷移図のように遷移できます.

アカウント関係図

Mermaid code
stateDiagram-v2
    NONE --> REQUESTING_FOLLOW
    REQUESTING_FOLLOW --> NONE
    REQUESTING_FOLLOW --> FOLLOWING
    FOLLOWING --> NONE
    FOLLOWING --> BLOCKING
    NONE --> BLOCKING
    BLOCKING --> NONE

検索述語

タイムラインの設定や検索クエリに用いられる組み合わせ可能な述語です. これは後述の検索命題を用いて帰納的に構成されます.

  • Atom: 原子式で, ある検索命題をそのまま述語とします.
  • Not: 論理否定です. ある検索述語によって選択されなかったもののみを選択する述語です.
  • And: 論理積です. 2 つの検索述語の両方によって選択されたものを選択する述語です.
  • Or: 論理和です. 2 つの検索述語のいずれか一方または両方によって選択されたものを選択する述語です.
  • Xor: 排他的論理和です. 2 つの検索述語のどちらか一方のみによって選択されたものを選択する述語です.

検索命題

命題は 所属, 特定のワード, ユーザー ID などを表す次の属性のあつまりとして定義されます. いずれの属性の条件も未設定にでき, その場合は選択されずそのまま次の条件へと渡ります.

  • id_mask: そのユーザー ID が完全に一致するのもだけを選択します.
  • belonging: その投稿が所属する連合が完全一致するのもだけを選択します.
  • match_word: 任意の自然言語エントリに対してそのテキストが部分一致するものだけを選択します.

メディアソース

文章, 画像, 動画などのコンテンツを効率的かつ高速に配信するオリジンおよびその URL, その配信を提供するサービスを指します.

内部メディアソース

(wip)

外部メディアソース

(wip)

投稿

Pulsate に対して送信されたユーザー生成コンテンツのエンティティです.

すべての投稿は ID を保持しています. これに加えて, 以下の属性が関連付けられます.

(wip)

タイムライン

main ブランチの最新 API リファレンスは api.pulsate.dev/reference で閲覧可能.

APIのバージョニング

APIの規定パス(Base Path)は /api/v0 である.

APIのバージョンは以下の通り.

バージョンステータス
v0策定途中

資格情報が必要なエンドポイントの実行方法

Pulsate v0 APIでは殆どのエンドポイントで資格情報が必要である.

資格情報が必要なエンドポイントへアクセスするためには, 以下の方法でエンドポイントにアクセスする必要がある.

エンドポイントへアクセスするときのAuthorization HTTPヘッダーに

Bearer <token>

の形式で 認証トークン をつけて送信する必要がある.

例:

Bearer

“文字数”の扱い

特に明記しない限り、文字数は 以下のコードを実行して計算できる文字数 とする.

const count = (s: string) => {
  const segmenter = new Intl.Segmenter({ granularity: "word" });
  return [...segmenter.segment(s)].length;
};

このAPIを実装する実行環境のリストはMDNを参照せよ.

Intl.Segmenter - JavaScript | MDN

“時刻/時間”の扱い

特に明記しない限り、システム上の時刻の扱いは以下の通りである.

  • 日時は例外なくタイムゾーンをUTCとして扱う
  • 時刻のフォーマットは ISO 8601 とする.
    • "yyyy-MM-DDTHH:mm:ss.SSSZ"形式
    • タイムゾーン指定されていた場合は指定したタイムゾーンの日時をUTCに変換する.
      • 例:
        • 2023-11-21T09:00:00.000+09:00 : 日本時間(JST, UTC+9) 2023年11月21日09:00:00.000 → 2023-11-21T00:00:00.000Z : 世界協定時(UTC) 2023年11月21日00:00:00.000
    • 以上の形式に合致しない形で日時の表現がされた場合はエラー終了するものとする.

絵文字の扱い

絵文字とは, Unicodeによって定義される絵文字とカスタム絵文字のことである.

その他の記号や環境依存文字は絵文字ではないとする.

Unicode絵文字

Unicode絵文字とは,Unicodeによって定義される絵文字である.

APIとやり取りするテキストデータでは特殊な記法を用いずUnicodeで表現する.

例:

{
  "content": "🎉"
}

カスタム絵文字

カスタム絵文字を文字列内に埋め込むための形式は以下の通りである.

以下の形式に沿わない場合は単なる文字列であると解釈する.

  • 全体を<> で囲む
    • カスタム絵文字のエイリアスは::で囲む
    • カスタム絵文字に関する詳細な定義はここでは行わない. (ToDo)
  • エイリアスのあとに(絵文字があるインスタンスではなく,APIを提供するインスタンスでの)カスタム絵文字のIDを表記する.

例:

<:alias:2949583895994> <:ii_hanashi:284745363>

特殊なテキスト埋め込みオブジェクト

投稿本文, CW注釈, アカウントbio のテキスト内にカスタム絵文字やメンションなど, Unicodeで規定された文字以外のデータを表現するときの記法

カスタム絵文字は カスタム絵文字 を参照せよ.

メンション

表記法は以下の通り

<@[email protected]>
  • 宛先のホスト名(FQDN)は 省略不可
<@[email protected]> <@[email protected]> <@[email protected]>

基本エラーオブジェクト

APIにおいて何らかのエラーが発生した際には以下のようなエラーオブジェクトを返却する.

{
  "error": "TEST_ERROR_CODE"
}

errorの中にはエラーコード が入る. エラーコードはエラーを返却するAPIのエンドポイントでどのようなコードを返すか指定するものとする.

エラーオブジェクトはエラーコードのみをメンバーとして含むオブジェクトである.

エラーコード以外の情報をエラーオブジェクトとして返却することは許容されない.

NSFWフラグ

言葉の意味:

NSFWとは、英語圏で用いられるインターネットスラングで、「職場では見ない方がいい」(職場での閲覧は危険)という意味の略語である。日本語の「閲覧注意」におおむね相当する。

NSFWは画像がメインの掲示板や、掲示板中の画像へのリンクなどに付けて用いられやすい。たいていは卑猥(エロ画像)・残酷(グロ画像)といった要素の強い、不用意な閲覧ははばかられる類のコンテンツが掲載されている。

  • NSFWフラグとは,画像/音声/動画の内容がNSFWであることを示すためのフラグである.
  • 大抵の場合画像/音声/動画にぼかし(ブラー)がかけられたり,閲覧注意の文言が(システムのUI上で)表示される.

ContentsWarning/CWフラグ

  • CWフラグとは,投稿本文に何らかのコンテンツ警告があることを示すフラグである.
  • 大抵の場合,投稿の注釈(投稿本文より短い,本文の内容を端的に表した文)のみが表示され,本文は[続きを読む]といったボタンを押さないと見ることができない

  • リファレンスへの追加状況 (See: pulsate-dev/specification#3 )
    • アカウント
      • アカウント情報(プロフィール)を管理する
      • アカウント情報の取得
      • アカウントの削除
      • アカウントの検索
      • アカウントのサイレンス
      • アカウトのサイレンス解除
      • アカウントの凍結
      • アカウトの解凍
      • ログイン
      • アカウント登録
    • フォロー
      • アカウントをフォロー
      • アカウントをフォロー解除
    • ノート
      • ノートの作成
      • (自分の)ノートの削除
      • リノートの作成
      • リノートの解除(削除)
      • ノートへのリアクションの作成
      • ノートへのリアクションの解除
      • ノートのブックマーク
      • ノートの検索
      • ノートの取得
    • リスト
      • リストの作成
      • リストの削除
      • リストへのアカウントの追加
      • リストへのアカウントの除外/削除
      • リストのノート取得
    • ドライブ
      • ファイルのアップロード
      • ファイルの取得
      • ノートへの紐付け
      • NSFWフラグの設定

アカウントAPI

POST /accounts

新規アカウントを作成する 正確には登録中の状態のアカウントを作成し,アカウント登録スキームを開始するものである.

入力

body: application/json

項目名制約/説明文字数制約
namestring文字は A-Z a-z 0-9 - . _である必要がある. 先頭,及び最後の文字は A-Z a-z 0-9 のみとする.1 ≤ N ≤ 64 [文字]john ※登録される情報は@[email protected]
emailstringメールアドレスとして正しい形式 (メールアドレスを受信可能であるかは問わない)7≤N≤319[文字][email protected]
passphrasestringスペース,タブ,全角スペース,改行,ヌルを除くUTF-8文字列8≤N≤512[文字]じゃすた・いぐざんぽぅ, just~@_examp1e!
captcha_tokenstringCloudflare Turnstile などの手動操作検証のトークン

入力例

{
  "name": "example",
  "email": "[email protected]",
  "passphrase": "じゃすた・いぐざんぽぅ",
  "captcha_token": "hogehogehgoe"
}

出力

200 OK

{
  "id": "38477395",
  "name": "example",
  "email": "[email protected]"
}

body: application/json

項目名説明文字数
idsnowflakeアカウントのID-30848577730000
namestringユーザー名8≤N≤512[文字]@[email protected]
emailstringメールアドレスとして正しい形式 (メールアドレスを受信可能であるかは問わない)7≤N≤319[文字][email protected]

400 Bad Request

{
  "error": "TEST_ERROR_CODE"
}
  • INVALID_ACCOUNT_NAME: 使用できない文字が含まれている,文字の使用制限に違反している
  • TOO_LONG_ACCOUNT_NAME: アカウント名が長すぎる
  • EMAIL_IN_USE: メールアドレスが既に使用されている
  • YOU_ARE_BOT: captcha_token の検証に失敗した

409 Conflict

{
  "error": "TEST_ERROR_CODE"
}
  • ACCOUNT_NAME_IN_USE: アカウント名が既に使用されている
  • EMAIL_IN_USE : メールアドレスが既に使用されている

PATCH /accounts/{account_name}

アカウント情報を指定のパラメータで編集するエンドポイント.

入力の body から次の情報のいずれか 1 つ以上を受け付け、それらを同時に適用できるかを検証し,反映する.

競合を防ぐために「更新前のニックネームと更新前のメールアドレスを結合した文字列」のハッシュを ETag (Entity Tag) として用いる.

これをMD5でハッシュするものとする.

メールアドレスを更新した場合はそのメールアドレスの確認スキームが開始される.

そしてそのメールアドレスが確認されるまで,メールアドレスの更新処理は遅延される.

ニックネームも同時に更新した場合,ニックネームの更新は先に反映される.

warning

ETag が一致しないときは 412 Precondition Failed のエラーとなる. 結合方法は 更新前のニックネーム:更新前のメールアドレスである

入力

  • body: application/json
項目名制約/説明文字数制約
namestring文字は A-Z a-z 0-9 - . _である必要がある. 先頭,及び最後の文字は A-Z a-z 0-9 のみとする.1 ≤ N ≤ 64 [文字]john ※登録される情報は@[email protected]
emailstringメールアドレスとして正しい形式 (メールアドレスを受信可能であるかは問わない)7≤N≤319[文字][email protected]
passphrasestringスペース,タブ,全角スペース,改行,ヌルを除くUTF-8文字列8≤N≤512[文字]じゃすた・いぐざんぽぅ, just~@_examp1e!
captcha_tokenstringCloudflare Turnstile などの手動操作検証のトークン
biostring自己紹介文. 0文字である場合はnullundefinedではなく空の文字列""である必要がある.0≤N≤1024"" (空文字列), いい感じの自己紹介🆓, This is bio hello^~ <:javascript:358409384>

入力例

{
  "nickname": "example",
  "email": "[email protected]",
  "passphrase": "じゃすた・いぐざんぽぅ",
  "bio": "テストユーザーなのぜ"
}

出力

200 OK

編集に成功しました.

{
  "id": "38477395",
  "name": "@[email protected]",
  "nickname": "John Doe",
  "bio": "テストユーザーなのぜ",
  "email": "[email protected]"
}
項目名説明文字数
idsnowflakeアカウントのID-30848577730000
namestringユーザー名8≤N≤512[文字]@[email protected]
emailstringメールアドレスとして正しい形式 (メールアドレスを受信可能であるかは問わない)7≤N≤319[文字][email protected]
nicknamestring表示名,アカウントの表示に用いる短い文字列1≤N≤256JohnDoe<:json:299384730049>
ジョン・ドゥ🚉

202 Accepted

メールアドレスが更新された場合

{
  "id": "38477395",
  "name": "@[email protected]",
  "nickname": "John Doe",
  "bio": "テストユーザーなのぜ",
  "email": "[email protected]"
}

400 Bad Request

{
  "error": "TEST_ERROR_CODE"
}
  • INVALID_SEQUENCE: パラメータ内に使用不可能な文字種を含んでいる
  • VULNERABLE_PASSPHRASE: 新しいパスフレーズがパスフレーズとしての要件を満たしていない

404 Not Found

{
  "error": "TEST_ERROR_CODE"
}
  • ACCOUNT_NOT_FOUND: 名前が account_name のアカウントが見つからない

412 Precondition Failed

{
  "error": "TEST_ERROR_CODE"
}
  • INVALID_ETAG: ETagが不正である

PUT /accounts/{account_name}/freeze

アカウントを凍結するエンドポイント.

モデレータ以上の権限を持つアカウント認証情報が必要である.

凍結されると以下のような挙動になる.

  • ログインできなくなる.
    • ログインしようとするとエラー終了する.
  • 投稿できなくなる.
  • (公開APIを除く)いかなるAPIへの操作も受け付けなくなる.

入力

  • パスパラメータ
    • account_name: string
      • アカウント名
  • body: application/json
    • 空のオブジェクトを送信せよ.
      • 空でない場合のメンバーは無視される.

入力例

{}

出力

204 No Content

凍結が完了した.

※レスポンスボディは空になる.

400 Bad Request

{
  "error": "TEST_ERROR_CODE"
}
  • ALREADY_FROZEN: すでに凍結済みである.

403 Forbidden

{
  "error": "TEST_ERROR_CODE"
}
  • NO_PERMISSION: アカウントを凍結できる権限がない.

404 Not Found

{
  "error": "TEST_ERROR_CODE"
}
  • ACCOUNT_NOT_FOUND: アカウントが見つからない.

DELETE /accounts/{account_name}/freeze

アカウントを凍結解除する(解凍と表記することもある).

モデレータ以上の権限の持つアカウント認証情報が必要.

入力

  • パスパラメータ
    • account_name: string
      • アカウント名
  • body: application/json
    • 空のオブジェクトを送信せよ.
      • 空でない場合のメンバは無視される.

入力例

{}

出力

204 No Content

凍結解除した.

※レスポンスボディは空になる.

403 Forbidden

{
  "error": "TEST_ERROR_CODE"
}
  • NO_PERMISSION: アカウントを凍結解除できる権限がない.

404 Not Found

{
  "error": "TEST_ERROR_CODE"
}
  • ACCOUNT_NOT_FOUND: アカウントが見つからない.

POST /accounts/{account_name}/resend_verify_email

メールアドレスの検証コードを再送

入力

  • パスパラメータ
    • account_name: string
      • アカウント名

body: application/json

項目名制約/説明文字数
captcha_tokenstringCloudflare Trunstileなどの検証トークン

入力例

{
  "captcha_token": "hogehogehgoe"
}

出力

204 No Content

再送した

※レスポンスボディは空になる.

400 Bad Request

{
  "error": "TEST_ERROR_CODE"
}
  • ACCOUNT_ALREADY_VERIFIED: アカウントのメールアドレスはすでに検証されている.

404 Not Found

{
  "error": "TEST_ERROR_CODE"
}
  • ACCOUNT_NOT_FOUND: アカウントが見つからない

POST /accounts/{account_name}/verify_email

メールアドレス認証が終了していないアカウントに対して,

メールアドレスに送信された認証トークンを検証することでメールアドレス認証を行う.

処理が完了すると,検証済みアカウントになりログインなどの各種操作が行えるようになる(ToDo 行うことのできる操作の一覧へのリンク

入力

  • パスパラメータ
    • account_name: string
      • アカウント名
  • body: application/json
項目名制約/説明文字数
tokenstring認証トークン: モデル を参照

入力例

{
  "token": "vq34rvyanho10q9hbc98ydbvaervna43r0varhj"
}

出力

204 No Content

検証に成功

※ レスポンスボディは空になります

400 Bad Request

{
  "error": "TEST_ERROR_CODE"
}
  • INVALID_TOKEN: トークンの検証に失敗.

404 Not Found

{
  "error": "TEST_ERROR_CODE"
}
  • ACCOUNT_NOT_FOUND: 指定した名前のアカウントは存在しない.

POST /login

ログインして認証/更新トークンを作成します.

warning

認証トークンの有効期限は15分(900秒), 更新トークンの有効期限は30日(2,592,000秒)である. どちらのトークンも,APIサーバーが再起動されると無効になり,その場合は再度ログインする必要がある.

入力

  • body: application/json
項目名制約/説明文字数
namestringアカウント名8≤N≤512[文字]@[email protected]
passphrasestringパスフレーズ8≤N≤512じゃすた・いぐざんぽぅ, just~@_examp1e!
captcha_tokenstringCloudflare Trunstileなどの検証トークン

入力例

{
  "name": "@[email protected]",
  "passphrase": "じゃすた・いぐざんぽぅ",
  "captcha_token": "hogehogehoge"
}

出力

200 OK

ログインしました

{
  "authorization_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.  eyJzdWIiOiIzZTE2NDQ4MzMwMDAwMDIiLCJpYXQiOjE2NDA5OTUyMDEsInJlZnJlc2hfdG9rZW4iOiJleUpoYkdjaU9pSklVekkxTmlJc0luUjVjQ0k2SWtwWFZDSjkuZXlKemRXSWlPaUl6WlRFMk5EUTR  Nek13TURBd01ESWlMQ0pwWVhRaU9qRTJOREE1T1RVeU1ERjkud2Q4cWJVcWowWGtCU1hud0FxM0lRYU1nQS1RTFd2MHVKU1NLX3BIVTZCYyJ9.mRUfLIYOGlLuC9D72zBriVvrHYrQgVHW7ntQ-bp5SHs",
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.  eyJzdWIiOiIzZTE2NDQ4MzMwMDAwMDIiLCJpYXQiOjE2NDA5OTUyMDEsInJlZnJlc2hfdG9rZW4iOiJleUpoYkdjaU9pSklVekkxTmlJc0luUjVjQ0k2SWtwWFZDSjkuZXlKemRXSWlPaUl6WlRFMk5EUTR  Nek13TURBd01ESWlMQ0pwWVhRaU9qRTJOREE1T1RVeU1ERjkud2Q4cWJVcWowWGtCU1hud0FxM0lRYU1nQS1RTFd2MHVKU1NLX3BIVTZCYyJ9.mRUfLIYOGlLuC9D72zBriVvrHYrQgVHW7ntQ-bp5SHs",
  "expires_in": 1672498800
}
項目名制約/説明文字数
authorization_tokenstring認証トークン
refresh_tokenstring更新トークン
expires_innumber有効期限. Pulsate Epochからの秒数: モデル を参照.

400 Bad Request

{
  "error": "TEST_ERROR_CODE"
}
  • FAILED_TO_LOGIN: パスフレーズかアカウント名が間違っている
  • YOU_ARE_BOT: captchaトークンの検証に失敗

403 Forbidden

{
  "error": "TEST_ERROR_CODE"
}
  • YOU_ARE_FROZEN: ログインしようとしたアカウントは凍結されている

POST /refresh

更新トークンで認証トークンを再発行

入力

  • body: application/json
    • refresh_token: string
      • 更新トークン
項目名制約/説明文字数
refresh_tokenstring更新トークン 参照

入力例

{
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIzZTE2NDQ4MzMwMDAwMDIiLCJpYXQiOjE2NDA5OTUyMDEsInJlZnJlc2hfdG9rZW4iOiJleUpoYkdjaU9pSklVekkxTmlJc0luUjVjQ0k2SWtwWFZDSjkuZXlKemRXSWlPaUl6WlRFMk5EUTRNek13TURBd01ESWlMQ0pwWVhRaU9qRTJOREE1T1RVeU1ERjkud2Q4cWJVcWowWGtCU1hud0FxM0lRYU1nQS1RTFd2MHVKU1NLX3BIVTZCYyJ9.mRUfLIYOGlLuC9D72zBriVvrHYrQgVHW7ntQ-bp5SHs"
}

出力

200 OK

ログインに成功した

{
  "authorization_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIzZTE2NDQ4MzMwMDAwMDIiLCJpYXQiOjE2NDA5OTUyMDEsInJlZnJlc2hfdG9rZW4iOiJleUpoYkdjaU9pSklVekkxTmlJc0luUjVjQ0k2SWtwWFZDSjkuZXlKemRXSWlPaUl6WlRFMk5EUTRNek13TURBd01ESWlMQ0pwWVhRaU9qRTJOREE1T1RVeU1ERjkud2Q4cWJVcWowWGtCU1hud0FxM0lRYU1nQS1RTFd2MHVKU1NLX3BIVTZCYyJ9.mRUfLIYOGlLuC9D72zBriVvrHYrQgVHW7ntQ-bp5SHs"
}
項目名制約/説明文字数
autorization_tokenstring認証トークン
共通 を参照

400 Bad Request

{
  "error": "TEST_ERROR_CODE"
}
  • INVALID_TOKEN: 更新トークンが不正
  • EXPIRED_TOKEN: トークンの有効期限切れ

GET /accounts/{account_name}

アカウント情報を取得

入力

  • パスパラメータ
    • account_name: string
      • アカウント名

出力

200 OK

取得に成功

{
  "id": "2874987398",
  "name": "@[email protected]",
  "nickname": "John Doe",
  "bio": "I am Test User.",
  "avatar": "https://example.com/images/avatar.png",
  "header": "https://example.com/images/header.png",
  "followed_count": 200,
  "following_count": 10,
  "note_count": 20000
}
項目名制約/説明文字数
idsnowflakeアカウントID2934002842
namestringアカウント名8≤N≤512[文字]@[email protected]
nicknamestring表示名,アカウントの表示に用いる短い文字列1≤N≤256JohnDoe<:json:299384730049>, ジョン・ドゥ🚉
biostring自己紹介文. 0文字である場合はnullやundefinedではなくからの文字列である必要がある.0≤N≤1024"" (空文字列), いい感じの自己紹介🆓,This is bio hello^~ <:javascript:358409384>
avatarstringアカウントのアイコン画像のURL
headerstringアカウントのヘッダー画像のURL
followed_countnumberそのアカウントをフォローしている人数
following_countnumberそのアカウントがフォローしている人数
note_countnumberそのアカウントの投稿数

404 Not Found

{
  "error": "TEST_ERROR_CODE"
}
  • ACCOUNT_NOT_FOUND: 指定した名前のアカウントは存在しない

PUT /accounts/{account_name}/silence

アカウントをサイレンスする.モデレータ以上の権限を持つアカウント認証情報が必要.

サイレンスされると以下のような挙動になる.

  • 公開投稿(投稿範囲がpublicになる投稿)ができなくなる

入力

  • パスパラメータ
    • account_name: string
      • アカウント名
  • body: application/json
    • ボディは空オブジェクトである必要がある.
    • 空でない場合,メンバは無視される.

入力例

{}

出力

204 No Content

凍結に成功

※レスポンスボディは空になる.

403 Forbidden

{
  "error": "TEST_ERROR_CODE"
}
  • NO_PERMISSION: アカウントをサイレンスできる権限がない.

404 Not Found

{
  "error": "TEST_ERROR_CODE"
}
  • ACCOUNT_NOT_FOUND: 指定した名前のアカウントは存在しない.

DELETE /accounts/{account_name}/silence

アカウントをサイレンス解除

モデレータ以上の権限の持つアカウント認証情報が必要.

入力

  • パスパラメータ
    • account_name: string
      • アカウント名
  • body: application/json
    • オブジェクトは空である必要がある.
    • 空でない場合,メンバは無視される.

入力例

{}

出力

204 No Content

サイレンスを解除

※レスポンスボディは空になる.

403 Forbidden

{
  "error": "TEST_ERROR_CODE"
}
  • NO_PERMISSION: アカウントをサイレンス解除できる権限がない

404 Not Found

{
  "error": "TEST_ERROR_CODE"
}
  • ACCOUNT_NOT_FOUND: 指定した名前のアカウントは存在しない

POST /accounts/{account_name}/follow

指定したアカウントをフォロー

入力

  • パスパラメータ
    • account_name: string
      • フォローしたいアカウント名
  • body: application/json
    • 空オブジェクトを送信せよ
      • 空でない場合のメンバは無視される

入力例

{}

出力

201 Accepted

フォローを受け付けた

{
  "pending": true
}
  • フォローする相手がフォローを手動承認制にしている場合はpendingがtrueになる.
    • フォローする相手がフォローを手動承認制にしていない場合もある.
      • この場合はpendingは必ずfalseになる.
  • v2以降の予定: フォローする相手が同じインスタンスに所属していない場合はすべての場合でpendingがtrueになる.

400 Bad Request

{
  "error": "TEST_ERROR_CODE"
}
  • ALREADY_FOLLOWING: アカウントをすでにフォローしている
  • YOU_ARE_BLOCKED: 相手にブロックされている

404 Not Found

{
  "error": "TEST_ERROR_CODE"
}
  • ACCOUNT_NOT_FOUND: 指定した名前のアカウントは存在しない.

DELETE /accounts/{account_name}/follow

フォローを解除します

入力

  • パスパラメータ
    • account_name: string
      • フォロー解除したいアカウント名
  • body: application/json
    • リクエストボディは空オブジェクトを送信せよ.
      • 空でない場合のメンバは無視される.

入力例

{}

出力

204 No Content

フォローを解除した.

※レスポンスボディは空になる.

400 Bad Request

{
  "error": "TEST_ERROR_CODE"
}
  • YOU_ARE_NOT_FOLLOW_ACCOUNT: 指定したアカウントをフォローしていない

404 Not Found

{
  "error": "TEST_ERROR_CODE"
}
  • ACCOUNT_NOT_FOUND: 指定した名前のアカウントは存在しない

ドライブAPI

GET /drive

自分がアップロードした画像のリストを取得します

入力

なし

出力

200 OK

[
  {
    "id": "2938492384",
    "name": "image.jpeg",
    "author_id": "384880009940302",
    "hash": "nf9:e;g711*c@drgj55",
    "mime": "image/jpeg",
    "nsfw": false,
    "url": "https://images.example.com/image.jpeg",
    "thumbnail": "https://images.example.com/thumb-image.jpeg"
  }
]
項目名説明制約
idsnowflakeファイルのID
namestringファイル名1≤N≤256[文字]
author_idsnowflakeアップロードしたアカウントのID
hashstring画像のblurhash
mimestringmimeタイプ
nsfwbooleanNSFWフラグ
urlstring画像へのリンク
thumbnailstring, undefined(利用可能な場合のみ) 縮小版のサムネイル画像

404 Not Found

{
  "error": "TEST_ERROR_CODE"
}
  • FILE_NOT_FOUND: ファイルが存在しません

POST /drive/

添付ファイルをアップロードします

入力

  • body: multipart/form-data
項目名説明制約
namestringファイル名拡張子が必須1≤N≤256[文字]neko.png, 箱根駅伝.mp3
file(ファイルの実体)アップロードするファイル. アップロード可能なファイル種類は後述1≤100 [MB]
nsfwstring ( "true", "false" )NSFWフラグ
アップロード可能なファイル種類(mimeタイプ) mimeタイプについて詳しくは [https://www.iana.org/assignments/media-types/media-types.xhtml](https://www.iana.org/assignments/media-types/media-types.xhtml) を参照

画像:

  • image/apng
  • image/avif
  • image/gif
  • image/jpeg
  • image/png
  • image/webp

音声、動画:

  • audio/wave , audio/wav
  • audio/webm
  • audio/mpeg
  • video/mpeg
  • video/webm
  • audio/ogg

出力

200 OK

アップロードが完了しました.

{
  "id": "2938492384",
  "name": "image.jpeg",
  "author_id": "493094050",
  "hash": "nf9:e;g711*c@drgj55",
  "mime": "image/jpeg",
  "nsfw": false,
  "url": "https://images.example.com/image.jpeg",
  "thumbnail": "https://images.example.com/thumb-image.jpeg"
}
項目名説明制約
idsnowflakeファイルのID
namestringファイル名1≤N≤256[文字]
author_idsnowflakeアップロードしたアカウントのID
hashstring画像のblurhash
mimestringmimeタイプ
nsfwbooleanNSFWフラグ
urlstring画像へのリンク
thumbnailstring, undefined(利用可能な場合のみ) 縮小版のサムネイル画像

400 Bad Request

{
  "error": "TEST_ERROR_CODE"
}
  • FILE_SIZE_TOO_BIG: ファイルサイズが大きすぎます
  • FILE_NAME_TOO_LONG: ファイル名が長すぎます

DELETE /drive/{file_id}

指定したファイルを削除します

warning

ファイルを削除すると,紐付けられているすべてのノートに影響します.

入力

  • パスパラメータ
    • file_id: snowflake
      • ファイルのID

出力

204 No Content

削除しました.

※レスポンスボディは空になります.

404 Not Found

{
  "error": "TEST_ERROR_CODE"
}
  • FILE_NOT_FOUND: ファイルが存在しません

GET /drive/{file_id}

ファイルのメタ情報を取得します

入力

  • パスパラメータ
    • file_id: snowflake
      • ファイルのID

出力

200 OK

{
  "id": "2938492384",
  "name": "image.jpeg",
  "author_id": "384880009940302",
  "hash": "nf9:e;g711*c@drgj55",
  "mime": "image/jpeg",
  "nsfw": false,
  "url": "https://images.example.com/image.jpeg",
  "thumbnail": "https://images.example.com/thumb-image.jpeg"
}
項目名説明制約
idsnowflakeファイルのID
namestringファイル名1≤N≤256[文字]
author_idsnowflakeアップロードしたアカウントのID
hashstring画像のblurhash
mimestringmimeタイプ
nsfwbooleanNSFWフラグ
urlstring画像へのリンク
thumbnailstring, undefined(利用可能な場合のみ) 縮小版のサムネイル画像

404 Not Found

{
  "error": "TEST_ERROR_CODE"
}
  • FILE_NOT_FOUND: ファイルが存在しません

PUT /drive/{file_id}

ファイルの情報を変更します

warning

情報を変更すると、そのファイルが紐付けられているすべてのノートに影響します

入力

  • パスパラメータ

    • file_id: snowflake
      • ファイルのID
  • body: application/json

項目名説明制約
nsfwbooleanNSFWフラグ

入力例

{
  "nsfw": false
}

出力

200 OK

{
  "id": "2938492384",
  "name": "image.jpeg",
  "author_id": "384880009940302",
  "hash": "nf9:e;g711*c@drgj55",
  "mime": "image/jpeg",
  "nsfw": false,
  "url": "https://images.example.com/image.jpeg",
  "thumbnail": "https://images.example.com/thumb-image.jpeg"
}
項目名説明制約
idsnowflakeファイルのID
namestringファイル名1≤N≤256[文字]
author_idsnowflakeアップロードしたアカウントのID
hashstring画像のblurhash
mimestringmimeタイプ
nsfwbooleanNSFWフラグ
urlstring画像へのリンク
thumbnailstring, undefined(利用可能な場合のみ) 縮小版のサムネイル画像

404 Not Found

{
  "error": "TEST_ERROR_CODE"
}
  • FILE_NOT_FOUND: ファイルが存在しません
項目名説明制約
idsnowflakeファイルのID
namestringファイル名1≤N≤256[文字]
author_idsnowflakeアップロードしたアカウントのID
hashstring画像のblurhash
mimestringmimeタイプ
nsfwbooleanNSFWフラグ
urlstring画像へのリンク
thumbnailstring, undefined(利用可能な場合のみ) 縮小版のサムネイル画像

リストAPI

POST /lists/

リストを作成します

入力

  • body: application/json
項目名説明制約
titlestringリストのタイトル1≤N≤100[文字]
publicbooleanデフォルト: false (非公開) 公開:  リストにアサインされたアカウントには通知が飛びます. 非公開: 通知は飛ばず、自分以外のアカウントからは見えません

入力例

{
  "title": "Pulsate Developers",
  "public": false
}

出力

200 OK

{
  "id": "18342938400393",
  "title": "Pulsate Developers",
  "public": false
}

400 Bad Request

{
  "error": "TEST_ERROR_CODE"
}
  • TITLE_TOO_LONG: タイトルが長すぎます

PATCH /lists/{list_id}

リスト情報を編集します

入力

  • パスパラメータ

    • list_id: string
      • 編集したいリストのID
  • body: application/json

項目名説明制約
titlestringリストのタイトル1≤N≤100[文字]
publicboolean公開・非公開のフラグ

入力例

{
  "title": "Edited Title",
  "public": true
}

出力

200 OK

{
  "id": "18342938400393",
  "title": "Edited Title",
  "public": true,
  "assignees": [
    {
      "id": "1838933554",
      "name": "@[email protected]"
    }
  ]
}

404 Not Found

{
  "error": "TEST_ERROR_CODE"
}
  • LIST_NOTFOUND: リストが見つかりません

400 Bad Request

{
  "error": "TEST_ERROR_CODE"
}
  • TITLE_TOO_LONG: タイトルが長すぎます

GET /lists/{list_id}

リスト情報を取得します

入力

  • パスパラメータ
    • list_id: string
      • 取得したいリストのID

出力

200 OK

{
  "id": "18342938400393",
  "title": "Pulsate Developers",
  "public": false,
  "assignees": [
    {
      "id": "1838933554",
      "name": "@[email protected]"
    }
  ]
}

404 Not Found

{
  "error": "TEST_ERROR_CODE"
}
  • LIST_NOTFOUND: リストが見つかりません

GET /lists/accounts/{account_id}

アカウントが持つリストを取得します

入力

  • パスパラメータ
    • account_id: snowflake
      • アカウントのID

出力

200 OK

[
  {
    "id": "18342938400393",
    "title": "Pulsate Developers",
    "public": false,
    "assignees": [
      {
        "id": "1838933554",
        "name": "@[email protected]"
      }
    ]
  }
]

404 Not Found

{
  "error": "TEST_ERROR_CODE"
}
  • ACCOUNT_NOT_FOUND : ユーザーが存在しません
  • LIST_NOTFOUND: リストが見つかりません

POST /lists/{list_id}

リストにアカウントをアサインします

入力

  • パスパラメータ
    • list_id: string
      • リストのID
  • body: application/json
    • account_id: Array<snowflake>
      • アカウントID
      • 一度にアサインできる最大アカウント数: 30

出力

200 OK

{
  "account_id": [
    "389384553329569",
    "586039500493885",
    "4847377595"
  ]
}

400 Bad Request

{
  "error": "TEST_ERROR_CODE"
}
  • TOO_MANY_TARGETS: アサインするアカウント数が多すぎます

404 Not Found

{
  "error": "TEST_ERROR_CODE"
}
  • ACCOUNT_NOT_FOUND: アカウントが存在しません
  • LIST_NOTFOUND: リストが見つかりません

DELETE /lists/{list_id}

リストからアカウントを削除します

入力

  • パスパラメータ
    • list_id: string
      • リストのID
  • body: application/json
    • account_id: Array<snowflake>
      • 削除するアカウントのID
      • 一度に削除できるアカウント数: 30

入力例

{
  "account_id": [
    "389384553329569",
    "586039500493885",
    "4847377595"
  ]
}

出力

204 No Content

削除しました.

※レスポンスボディは空になります.

400 Bad Request

{
  "error": "TEST_ERROR_CODE"
}
  • TOO_MANY_TARGETS : 削除するアカウント数が多すぎます

404 Not Found

{
  "error": "TEST_ERROR_CODE"
}
  • ACCOUNT_NOT_FOUND: アカウントが存在しません
  • LIST_NOTFOUND: リストが見つかりません

DELETE /lists/{list_id}

リストを削除します.

入力

  • パスパラメータ
    • list_id: string
      • リストのID

出力

204 No Content

削除しました.

※レスポンスボディは空になります.

404 Not Found

{
  "error": "TEST_ERROR_CODE"
}
  • LIST_NOTFOUND: リストが見つかりません

GET /lists/{list_id}/notes

リストのノートを取得します.

入力

  • パスパラメータ
    • list_id: snowflake
      • リストのID
  • クエリパラメータ
    • has_attachment: bool | undefined
      • デフォルト: false
      • ファイルを含む投稿のみを返します
    • no_nsfw : bool | undefined
      • デフォルト: false
      • NSFWフラグの立っているファイルを含む投稿を返さなくなります
    • before_id : ``snowflake| undefined
      • デフォルト: undefined
        • デフォルトでは現在取得できる最新の投稿から20件取得します.
      • 指定したIDより古い投稿を返します.指定したIDの投稿は含まれません

出力

200 OK

取得に成功しました

[
  {
    "id": "3893974892",
    "content": "hello world!",
    "cw_comment": "",
    "visibility": "public",
    "created_at": "2023-09-27T14:17:29.169Z",
    "attachment_files": [
      {
        "id": "204980348583",
        "filename": "hello.png",
        "content_type": "image/png",
        "url": "https://example.com/images/hello.png",
        "blur": "eoig:woi!our@nj/d",
        "nsfw": false
      }
    ],
    "reactions": [
      {
        "emoji": "<:alias:11938437>",
        "reacted_by": "3085763644"
      },
      {
        "emoji": "🎉",
        "reacted_by": "494984128"
      }
    ],
    "author": {
      "id": "2874987398",
      "name": "@[email protected]",
      "display_name": "John Doe",
      "bio": "I am Test User.",
      "avatar": "https://example.com/images/avatar.png",
      "header": "https://example.com/images/header.png",
      "followed_count": 200,
      "following_count": 10
    }
  }
]

404 Not Found

{
  "error": "TEST_ERROR_CODE"
}
  • LIST_NOTFOUND: リストが見つかりません
  • NOTHING_LEFT: これ以上古い投稿はありません
    • 1つでも古い投稿がある場合は投稿を返します

投稿API

note

投稿は”ノート”, 再投稿は”リノート”と言い換えられている場合があります.

ダイレクト投稿: ノートのうち,公開範囲がダイレクトに指定されているもの

POST /notes

ノートを作成

入力

  • body: application/json
項目名制約/説明数制約
contentstring投稿本文添付ファイルが存在する場合は0文字を許容1≤3000[文字]
visibilitystring, undefined投稿の公開範囲 デフォルト: public とり得る値: public home followers, direct-
attachment_file_idsArray<snowflake>, undefined投稿の添付ファイルID 1つでもファイルが存在しない場合はエラー終了する0≤N≤16[個]
cw_commentstringCW時の注釈. CW/CWフラグ 参照デフォルトは空文字列0≤N≤256[文字]
send_tosnowflake, undefinedダイレクト投稿の宛先公開範囲がdirectのときのみ指定可能

入力例

{
  "content": "hello world!",
  "visibility": "public",
  "attachment_file_ids": [
    "11938472"
  ],
  "cw_comment": ""
}
{
  "content": "hello world!",
  "visibility": "direct",
  "attachment_file_ids": [
    "11938472"
  ],
  "cw_comment": "",
  "send_to": "8585030584"
}

出力

201 Created

投稿を作成しました.

{
  "id": "3893974892",
  "content": "hello world!",
  "cw_comment": "",
  "visibility": "public",
  "created_at": "2023-09-27T14:17:29.169Z",
  "attachment_files": [
    {
      "id": "11938472",
      "filename": "hello.png",
      "content_type": "image/png",
      "url": "https://example.com/images/hello.png",
      "blur": "eoig:woi!our@nj/d",
      "nsfw": false
    }
  ]
}
項目名説明数制約
idsnowflake投稿のID
contentstring投稿本文. 添付ファイルが存在する場合は0文字を許容1≤3000[文字]
visibilitystring投稿の公開範囲. デフォルト: public. とり得る値: public home followers direct-
attachment_filesArray<object>投稿の添付ファイルのオブジェクト (後述)0≤N≤16[個]
cw_commentstringCW時の注釈, 参照 デフォルトは空文字列0≤N≤256[文字]
send_toSnowflake, undefinedダイレクト投稿の宛先. 公開範囲がdirectのときのみ指定可能
created_atstring投稿の送信日時
  • 添付ファイル (attchment_files)
項目名説明数制約
idsnowflake投稿のID
filenamestringファイル名3≤N≤256[文字]
content_typestringmimeタイプ
urlstring添付ファイルのURL
blurhashstring, undefined添付ファイルが画像であるときのサムネイルの blurhash
nsfwbooleanToDo

400 Bad Request

{
  "error": "TEST_ERROR_CODE"
}
  • TOO_MANY_ATTACHMENTS : 添付ファイルが制限を超過
  • TOO_MANY_CONTENT`` : CW注釈/投稿本文の文字数制限を超過
  • NO_DESTINATION: 公開範囲がdirectのノートでsend_toが指定されていない
  • INVALID_VISIBILITY: 公開範囲が正しい形式でない

403 Forbidden

{
  "error": "TEST_ERROR_CODE"
}
  • YOU_ARE_SILENCED : サイレンスされている際に公開範囲をpublicに指定した場合

404 Not Found

{
  "error": "TEST_ERROR_CODE"
}
  • ATTACHMENT_NOT_FOUND: 添付したファイルが存在しない
  • ACCOUNT_NOT_FOUND: 宛先(send_to)に指定したアカウントが存在しない

GET /notes/{note_id}

特定の投稿を取得します.

入力

  • パスパラメータ
    • note_id: string
      • 取得したい投稿のID

出力例

200 OK

投稿を取得しました.

{
  "id": "3893974892",
  "content": "hello world!",
  "cw_comment": "",
  "visibility": "public",
  "created_at": "2023-09-27T14:17:29.169Z",
  "attachment_files": [
    {
      "id": "204980348583",
      "filename": "hello.png",
      "content_type": "image/png",
      "url": "https://example.com/images/hello.png",
      "blur": "eoig:woi!our@nj/d",
      "nsfw": false
    }
  ],
  "reactions": [
    {
      "emoji": "<:alias:11938437>",
      "reacted_by": "3085763644"
    },
    {
      "emoji": "🎉",
      "reacted_by": "494984128"
    }
  ],
  "author": {
    "id": "2874987398",
    "name": "@[email protected]",
    "display_name": "John Doe",
    "bio": "I am Test User.",
    "avatar": "https://example.com/images/avatar.png",
    "header": "https://example.com/images/header.png",
    "followed_count": 200,
    "following_count": 10
  }
}
項目名説明数制約
idsnowflake投稿のID

404 Not Found

{
  "error": "TEST_ERROR_CODE"
}
  • NOTE_NOT_FOUND: 指定したIDのノートが存在しない
    • 指定したIDのノートを(アクセスしたユーザーが)取得できない場合もこのエラーを返す.

POST /notes/{note_id}/renote

指定したIDのノートをリノートします.

入力

  • パスパラメータ
    • note_id: string
      • 取得したい投稿のID
  • body: application/json
項目名説明数制約
idsnowflake投稿のID
contentstring投稿本文. 添付ファイルが存在する場合は0文字を許容1≤3000[文字]
visibilitystring投稿の公開範囲. デフォルト: public. とり得る値: public home followers direct-
attachment_filesArray<object>投稿の添付ファイルのオブジェクト (後述)0≤N≤16[個]
cw_commentstringCW時の注釈, 参照 デフォルトは空文字列0≤N≤256[文字]
send_toSnowflake, undefinedダイレクト投稿の宛先. 公開範囲がdirectのときのみ指定可能
created_atstring投稿の送信日時

attachment_files:

項目名説明数制約
idsnowflake投稿のID
filenamestringファイル名ToDo
content_typestringmimeタイプ
ToDo
urlstring添付ファイルのURL
blurstring添付ファイルが画像であるときのサムネイルの blurhash
nsfwbooleanToDo

入力例

{
  "content": "hello world!",
  "visibility": "public",
  "attachment_file_ids": [
    "11938472"
  ],
  "cw_comment": ""
}

出力

200 OK

リノートしました

{
  "id": "3893974892",
  "content": "hello world!",
  "cw_comment": "",
  "visibility": "public",
  "renote_id": "4973874850",
  "created_at": "2023-09-27T14:17:29.169Z",
  "attachment_files": [
    {
      "id": "11938472",
      "filename": "hello.png",
      "content_type": "image/png",
      "url": "https://example.com/images/hello.png",
      "blur": "eoig:woi!our@nj/d",
      "nsfw": false
    }
  ]
}
項目名説明数制約
idsnowflake投稿のID
contentstring投稿本文. 添付ファイルが存在する場合は0文字を許容1≤3000[文字]
visibilitystring投稿の公開範囲. デフォルト: public. とり得る値: public home followers direct-
attachment_filesArray<object>投稿の添付ファイルのオブジェクト (後述)0≤N≤16[個]
cw_commentstringCW時の注釈, 参照 デフォルトは空文字列0≤N≤256[文字]
send_toSnowflake, undefinedダイレクト投稿の宛先. 公開範囲がdirectのときのみ指定可能
created_atstring投稿の送信日時
項目名説明数制約
idsnowflake投稿のID
filenamestringファイル名ToDo
content_typestringmimeタイプ
ToDo
urlstring添付ファイルのURL
blurstring添付ファイルが画像であるときのサムネイルの blurhash
nsfwbooleanToDo

400 Bad Request

{
  "error": "TEST_ERROR_CODE"
}
  • TOO_MANY_CHAR_LENGTH : CW注釈/投稿本文の文字数制限を超過
  • INVALID_VISIBILITY: 公開範囲が正しい形式でない
  • NO_DESTINATION: 公開範囲がdirectのノートでsend_toが指定されていない

403 Forbidden

{
  "error": "TEST_ERROR_CODE"
}
  • YOU_ARE_SILENCED : サイレンスされている際に公開範囲をpublicに指定した

404 Not Found

{
  "error": "TEST_ERROR_CODE"
}
  • ATTACHMENT_NOT_FOUND: 添付したファイルが存在しない
  • NOTE_NOT_FOUND: ノートが存在しない

POST /notes/{note_id}/reply

指定したIDのノートに返信します.

入力

  • パスパラメータ
    • note_id: string
      • 取得したい投稿のID
  • body: application/json
項目名説明数制約
idsnowflake投稿のID
contentstring投稿本文. 添付ファイルが存在する場合は0文字を許容1≤3000[文字]
visibilitystring投稿の公開範囲. デフォルト: public. とり得る値: public home followers direct-
attachment_filesArray<object>投稿の添付ファイルのオブジェクト (後述)0≤N≤16[個]
cw_commentstringCW時の注釈, 参照 デフォルトは空文字列0≤N≤256[文字]
created_atstring投稿の送信日時

attachment_files:

項目名説明数制約
idsnowflake投稿のID
filenamestringファイル名ToDo
content_typestringmimeタイプ
ToDo
urlstring添付ファイルのURL
blurstring添付ファイルが画像であるときのサムネイルの blurhash
nsfwbooleanToDo

入力例

{
  "content": "hello world!",
  "visibility": "public",
  "attachment_file_ids": [
    "11938472"
  ],
  "cw_comment": ""
}

出力

200 OK

投稿を作成しました.

{
  "id": "3893974892",
  "content": "hello world!",
  "cw_comment": "",
  "reply_to": "2948933000",
  "visibility": "public",
  "created_at": "2023-09-27T14:17:29.169Z",
  "attachment_files": [
    {
      "id": "11938472",
      "filename": "hello.png",
      "content_type": "image/png",
      "url": "https://example.com/images/hello.png",
      "blur": "eoig:woi!our@nj/d",
      "nsfw": false
    }
  ]
}
項目名説明数制約
idsnowflake投稿のID
contentstring投稿本文. 添付ファイルが存在する場合は0文字を許容1≤3000[文字]
visibilitystring投稿の公開範囲. デフォルト: public. とり得る値: public home followers direct-
attachment_filesArray<object>投稿の添付ファイルのオブジェクト (後述)0≤N≤16[個]
cw_commentstringCW時の注釈, 参照 デフォルトは空文字列0≤N≤256[文字]
send_toSnowflake, undefinedダイレクト投稿の宛先. 公開範囲がdirectのときのみ指定可能
created_atstring投稿の送信日時
項目名説明数制約
idsnowflake投稿のID
filenamestringファイル名ToDo
content_typestringmimeタイプ
ToDo
urlstring添付ファイルのURL
blurstring添付ファイルが画像であるときのサムネイルの blurhash
nsfwbooleanToDo

400 Bad Request

{
  "error": "TEST_ERROR_CODE"
}
  • TOO_MANY_CHAR_LENGTH : CW注釈/投稿本文の文字数制限を超過
  • INVALID_VISIBILITY: 公開範囲が正しい形式でない

403 Forbidden

{
  "error": "TEST_ERROR_CODE"
}
  • YOU_ARE_SILENCED : サイレンスされている際に公開範囲をpublicに指定した
  • YOU_ARE_BLOCKED: 返信先ユーザーにブロックされている

404 Not Found

{
  "error": "TEST_ERROR_CODE"
}
  • ATTACHMENT_NOT_FOUND: 添付したファイルが存在しない
  • NOTE_NOT_FOUND: ノートが存在しない

DELETE /notes/{note_id}

投稿を削除します.

NOTICE: 自分以外のノートを削除する場合はモデレータ以上の資格情報が必要です.

入力

  • パスパラメータ
    • note_id: string
      • 削除するノートのID

出力

204 No Content

削除しました.

※ レスポンスボディは空になります

403 Forbidden

{
  "error": "TEST_ERROR_CODE"
}
  • NO_PERMISSION: ノートの投稿者でないため削除できない

404 Not Found

{
  "error": "TEST_ERROR_CODE"
}
  • NOTE_NOT_FOUND: 削除するノートが存在しない

POST /notes/{note_id}/reaction

指定したノートにリアクションします.

入力

  • パスパラメータ
    • note_id: string
      • リアクションしたい投稿のID

body: application/json

項目名説明
emojistring絵文字
表記法は カスタム絵文字 を参照<:alias:11938437>
🎉

入力例

{
  "emoji": "🎉"
}
{
  "emoji": "<:awesome:489395643749>"
}

出力

200 OK

リアクションしました.

{
  "id": "3893974892",
  "content": "hello world!",
  "cw_comment": "",
  "visibility": "public",
  "created_at": "2023-09-27T14:17:29.169Z",
  "attachment_files": [
    {
      "id": "204980348583",
      "filename": "hello.png",
      "content_type": "image/png",
      "url": "https://example.com/images/hello.png",
      "blur": "eoig:woi!our@nj/d",
      "nsfw": false
    }
  ],
  "reactions": [
    {
      "emoji": "<:alias:11938437>",
      "reacted_by": "3085763644"
    },
    {
      "emoji": "🎉",
      "reacted_by": "494984128"
    }
  ],
  "author": {
    "id": "2874987398",
    "name": "@[email protected]",
    "display_name": "John Doe",
    "bio": "I am Test User.",
    "avatar": "https://example.com/images/avatar.png",
    "header": "https://example.com/images/header.png",
    "followed_count": 200,
    "following_count": 10
  }
}
項目名説明数制約
idsnowflake投稿のID
contentstring投稿本文. 添付ファイルが存在する場合は0文字を許容1≤3000[文字]
visibilitystring投稿の公開範囲. デフォルト: public. とり得る値: public home followers direct-
attachment_filesArray<object>投稿の添付ファイルのオブジェクト (後述)0≤N≤16[個]
cw_commentstringCW時の注釈, 参照 デフォルトは空文字列0≤N≤256[文字]
send_toSnowflake, undefinedダイレクト投稿の宛先. 公開範囲がdirectのときのみ指定可能
created_atstring投稿の送信日時

attachment_files:

項目名説明数制約
idsnowflake投稿のID
filenamestringファイル名ToDo
content_typestringmimeタイプ
ToDo
urlstring添付ファイルのURL
blurstring添付ファイルが画像であるときのサムネイルの blurhash
nsfwbooleanToDo

reactions:

項目名説明
emojistring絵文字. 表記法は 絵文字の扱い を参照🎉, <:alias:11938437>
reacted_bysnowflakeリアクションしたアカウントID48499372

400 Bad Request

{
  "error": "TEST_ERROR_CODE"
}
  • ALREADY_REACTED: すでにリアクション済み
  • EMOJI_NOT_FOUND: 指定した絵文字が存在しない(カスタム絵文字のみ)/複数指定している(Unicode絵文字

404 Not Found

{
  "error": "TEST_ERROR_CODE"
}
  • NOTE_NOT_FOUND: リアクションするノートが存在しない

DELETE /notes/{note_id}/reaction

指定したノートにつけたリアクションを解除します

入力

  • パスパラメータ
    • note_id: string
      • リアクションしたい投稿のID

出力

204 No Content

削除しました.

※ レスポンスボディは空になります.

400 Forbidden

{
  "error": "TEST_ERROR_CODE"
}
  • NOT_REACTED: リアクションしていない

404 Not Found

{
  "error": "TEST_ERROR_CODE"
}
  • NOTE_NOT_FOUND: ノートが存在しない

POST /notes/{note_id}/bookmark

指定した投稿をブックマークします

入力

  • パスパラメータ
    • note_id: string
      • リアクションしたい投稿のID

出力

200 OK

ブックマークしました

{
  "id": "3893974892",
  "content": "hello world!",
  "cw_comment": "",
  "visibility": "public",
  "created_at": "2023-09-27T14:17:29.169Z",
  "attachment_files": [
    {
      "id": "204980348583",
      "filename": "hello.png",
      "content_type": "image/png",
      "url": "https://example.com/images/hello.png",
      "blur": "eoig:woi!our@nj/d",
      "nsfw": false
    }
  ],
  "reactions": [
    {
      "emoji": "<:alias:11938437>",
      "reacted_by": "3085763644"
    },
    {
      "emoji": "🎉",
      "reacted_by": "494984128"
    }
  ],
  "author": {
    "id": "2874987398",
    "name": "@[email protected]",
    "display_name": "John Doe",
    "bio": "I am Test User.",
    "avatar": "https://example.com/images/avatar.png",
    "header": "https://example.com/images/header.png",
    "followed_count": 200,
    "following_count": 10
  }
}
項目名説明数制約
idsnowflake投稿のID
contentstring投稿本文. 添付ファイルが存在する場合は0文字を許容1≤3000[文字]
visibilitystring投稿の公開範囲. デフォルト: public. とり得る値: public home followers direct-
attachment_filesArray<object>投稿の添付ファイルのオブジェクト (後述)0≤N≤16[個]
cw_commentstringCW時の注釈, 参照 デフォルトは空文字列0≤N≤256[文字]
send_toSnowflake, undefinedダイレクト投稿の宛先. 公開範囲がdirectのときのみ指定可能
created_atstring投稿の送信日時

attachment_files:

項目名説明数制約
idsnowflake投稿のID
filenamestringファイル名ToDo
content_typestringmimeタイプ
ToDo
urlstring添付ファイルのURL
blurstring添付ファイルが画像であるときのサムネイルの blurhash
nsfwbooleanToDo

reactions:

項目名説明
emojistring絵文字
表記法は 絵文字の扱い を参照<:alias:11938437
🎉
reacted_bysnowflakeリアクションしたアカウントID48499372

404 Not Found

{
  "error": "TEST_ERROR_CODE"
}
  • NOTE_NOT_FOUND: ノートが存在しない

DELETE /notes/{note_id}/bookmark

指定した投稿をブックマーク解除します

入力

  • パスパラメータ
    • note_id: string
      • ブックマーク解除したい投稿のID

出力

204 No Content

ブックマーク解除しました

※レスポンスボディは空になります.

404 Not Found

{
  "error": "TEST_ERROR_CODE"
}
  • NOTE_NOT_FOUND: ノートが存在しない

項目名説明数制約
idsnowflake投稿のID
contentstring投稿本文. 添付ファイルが存在する場合は0文字を許容1≤3000[文字]
visibilitystring投稿の公開範囲. デフォルト: public. とり得る値: public home followers direct-
attachment_filesArray<object>投稿の添付ファイルのオブジェクト (後述)0≤N≤16[個]
cw_commentstringCW時の注釈, 参照 デフォルトは空文字列0≤N≤256[文字]
send_toSnowflake, undefinedダイレクト投稿の宛先. 公開範囲がdirectのときのみ指定可能
created_atstring投稿の送信日時
項目名説明数制約
idsnowflake投稿のID
filenamestringファイル名ToDo
content_typestringmimeタイプ
ToDo
urlstring添付ファイルのURL
blurstring添付ファイルが画像であるときのサムネイルの blurhash
nsfwbooleanToDo
項目名説明
emojistring絵文字
表記法は 絵文字の扱い を参照<:alias:11938437
🎉
reacted_bysnowflakeリアクションしたアカウントID48499372

検索API

クエリ

ベースは Twitter v2 のクエリ.

オペレータ

Operator意味単独使用可能
keyword特定のキーワードを含む松江 AND どこyes
""文字列の完全一致"造幣局 桜"yes
from:特定ユーザーによるノートfrom:@[email protected] or from:@[email protected]yes
is:renoteリノートhello world -is:renoteno
is:quote引用リノート#筑後川花火大会 is:quoteno
has:link本文にリンクを含むノートnowplaying has:linkno
has:media添付ファイルを含むノート#徳川家康 has:mediano

演算子

演算子説明
ANDスペースを挟んで連続する演算子はAND 論理演算となり、両方の条件を満たしたノートが返されます
OROR を挟んで連続する演算子はOR論理演算となり、どちらかの条件を満たしたノートが返されます.
-キーワードの前にハイフンをつけると、そのキーワードを論理否定することができます.
()カッコでくくると演算子をグループ化できます. AND>ORの順で適用されます.

GET /search/notes

投稿を検索します. 返す最大件数は100件です

入力

  • クエリパラメータ
    • query: string
      • 検索クエリ
      • 上記の内容を受け取ります

出力

200 OK

検索に成功

出力の内容はタイムラインと同一である.

[
  {
    "id": "3893974892",
    "content": "hello world!",
    "cw_comment": "",
    "visibility": "public",
    "created_at": "2023-09-27T14:17:29.169Z",
    "attachment_files": [
      {
        "id": "204980348583",
        "filename": "hello.png",
        "content_type": "image/png",
        "url": "https://example.com/images/hello.png",
        "blur": "eoig:woi!our@nj/d",
        "nsfw": false
      }
    ],
    "reactions": [
      {
        "emoji": "<:alias:11938437>",
        "reacted_by": "3085763644"
      },
      {
        "emoji": "🎉",
        "reacted_by": "494984128"
      }
    ],
    "author": {
      "id": "2874987398",
      "name": "@[email protected]",
      "display_name": "John Doe",
      "bio": "I am Test User.",
      "avatar": "https://example.com/images/avatar.png",
      "header": "https://example.com/images/header.png",
      "followed_count": 200,
      "following_count": 10
    }
  }
]

400 Bad Request

{
  "error": "TEST_ERROR_CODE"
}
  • INVALID_QUERY: クエリが正しくありません

タイムラインAPI

warning

取得した投稿は時系列順にソートされた状態で返されます.
一度に取得できる件数は最大20件です.

GET /timeline/{timeline_type}

タイムラインを取得します.

入力

  • パスパラメータ
    • timeline_type: string, undefined
      • とり得る値: home / global
      • デフォルト: home
  • クエリパラメータ
    • has_attachment: bool | undefined
      • デフォルト: false
      • ファイルを含む投稿のみを返します
    • no_nsfw : bool | undefined
      • デフォルト: false
      • NSFWフラグの立っているファイルを含む投稿を返さなくなります
    • before_id : snowflake| undefined
      • デフォルト: undefined
        • デフォルトでは現在取得できる最新の投稿から20件取得します.
      • 指定したIDより古い投稿を返します.指定したIDの投稿は含まれません

出力

200 OK

タイムラインを取得します.

[
  {
    "id": "3893974892",
    "content": "hello world!",
    "cw_comment": "",
    "visibility": "public",
    "created_at": "2023-09-27T14:17:29.169Z",
    "attachment_files": [
      {
        "id": "204980348583",
        "filename": "hello.png",
        "content_type": "image/png",
        "url": "https://example.com/images/hello.png",
        "blur": "eoig:woi!our@nj/d",
        "nsfw": false
      }
    ],
    "reactions": [
      {
        "emoji": "<:alias:11938437>",
        "reacted_by": "3085763644"
      },
      {
        "emoji": "🎉",
        "reacted_by": "494984128"
      }
    ],
    "author": {
      "id": "2874987398",
      "name": "@[email protected]",
      "display_name": "John Doe",
      "bio": "I am Test User.",
      "avatar": "https://example.com/images/avatar.png",
      "header": "https://example.com/images/header.png",
      "followed_count": 200,
      "following_count": 10
    }
  }
]

400 Bad Request

{
  "error": "TEST_ERROR_CODE"
}
  • INVALID_TIMELINE_TYPE: 指定したタイムラインタイプは存在しません

404 Not Found

{
  "error": "TEST_ERROR_CODE"
}
  • NOTHING_LEFT: これ以上古い投稿はありません
    • 1つでも古い投稿がある場合は投稿を返します

GET /timeline/accounts/{account_id|account_name}

特定のユーザーの投稿を取得します.

入力

  • パスパラメータ
    • account_id,account_name: snowflake|string
      • アカウント名かアカウントのIDを指定できます.
  • クエリパラメータ
    • has_attachment: bool | undefined
      • デフォルト: false
      • ファイルを含む投稿のみを返します
    • no_nsfw : bool | undefined
      • デフォルト: false
      • NSFWフラグの立っているファイルを1つでも含む投稿を返さなくなります
    • before_id : snowflake| undefined`
      • デフォルト: undefined
        • デフォルトでは現在取得できる最新の投稿から20件取得します.
      • 指定したIDより古い投稿を返します.指定したIDの投稿は含まれません

出力

200 OK

タイムラインを取得します.

[
  {
    "id": "3893974892",
    "content": "hello world!",
    "cw_comment": "",
    "visibility": "public",
    "created_at": "2023-09-27T14:17:29.169Z",
    "attachment_files": [
      {
        "id": "204980348583",
        "filename": "hello.png",
        "content_type": "image/png",
        "url": "https://example.com/images/hello.png",
        "blur": "eoig:woi!our@nj/d",
        "nsfw": false
      }
    ],
    "reactions": [
      {
        "emoji": "<:alias:11938437>",
        "reacted_by": "3085763644"
      },
      {
        "emoji": "🎉",
        "reacted_by": "494984128"
      }
    ],
    "author": {
      "id": "2874987398",
      "name": "@[email protected]",
      "display_name": "John Doe",
      "bio": "I am Test User.",
      "avatar": "https://example.com/images/avatar.png",
      "header": "https://example.com/images/header.png",
      "followed_count": 200,
      "following_count": 10
    }
  }
]

400 Bad Request

{
  "error": "TEST_ERROR_CODE"
}
  • INVALID_TIMELINE_TYPE: 指定したタイムラインタイプは存在しません

403 Forbidden

{
  "error": "TEST_ERROR_CODE"
}
  • YOU_ARE_BLOCKED: 指定したアカウントにブロックされています.

404 Not Found

{
  "error": "TEST_ERROR_CODE"
}
  • NOTHING_LEFT: これ以上古い投稿はありません
    • 1つでも古い投稿がある場合は投稿を返します
  • ACCOUNT_NOT_FOUND : 指定したアカウントが見つかりませんでした

GET /timeline/conversations

ダイレクト投稿を受け取った、もしくは送った相手を取得します.

入力

なし

出力

200 OK

[
  {
    "account": {
      "accountId": "20983985",
      "accountName": "@[email protected]",
      "nickname": "John Doe",
      "avatar": "https://example.com/images/avatar.png"
    },
    "updatedAt": "2023-09-10T00:00:00.000Z"
  }
]

GET /timeline/conversations/{account_id}

指定したアカウントとのダイレクト投稿を取得します.

入力

  • パスパラメータ
    • account_id: snowflake
      • ダイレクト投稿を取得したいアカウントID.
  • クエリパラメータ
    • before_id: snowflake | undefined
      • デフォルト: undefined
      • 指定したIDより古い投稿を返します.指定したIDの投稿は含まれません

出力

200 OK

タイムラインを取得します.

[
  {
    "id": "3893974892",
    "content": "hello world!",
    "cw_comment": "",
    "visibility": "public",
    "created_at": "2023-09-27T14:17:29.169Z",
    "attachment_files": [
      {
        "id": "204980348583",
        "filename": "hello.png",
        "content_type": "image/png",
        "url": "https://example.com/images/hello.png",
        "blur": "eoig:woi!our@nj/d",
        "nsfw": false
      }
    ],
    "reactions": [
      {
        "emoji": "<:alias:11938437>",
        "reacted_by": "3085763644"
      },
      {
        "emoji": "🎉",
        "reacted_by": "494984128"
      }
    ],
    "author": {
      "id": "2874987398",
      "name": "@[email protected]",
      "display_name": "John Doe",
      "bio": "I am Test User.",
      "avatar": "https://example.com/images/avatar.png",
      "header": "https://example.com/images/header.png",
      "followed_count": 200,
      "following_count": 10
    }
  }
]

404 Not Found

{
  "error": "TEST_ERROR_CODE"
}
  • NOTHING_LEFT: これ以上古い投稿はありません
    • 1つでも古い投稿がある場合は投稿を返します
  • ACCOUNT_NOT_FOUND : 指定したアカウントが見つかりませんでした

内部フロー・モジュール間通信

モジュール間通信を示す Mermaid ダイアグラム

Mermaid code
sequenceDiagram
autonumber
actor ユーザー

ユーザー ->> NoteModule: 投稿

opt ダイレクト投稿の場合
	NoteModule ->> AccountModule: 送信先アカウントの存在チェック
end

NoteModule ->> AccountModule: 投稿者情報取得

opt リノートの場合
	NoteModule ->> NoteModule: 引用 or リノート先情報取得
end

NoteModule ->> ユーザー: 投稿完了

NoteModule ->> SearchModule: 検索インデックス投入
NoteModule ->> TimelineModule: 投稿作成イベント発火
TimelineModule ->> AccountModule: フォロー関係情報取得
TimelineModule ->> NotificationModule:通知イベント発火
TimelineModule ->> ActivityPubModule: 投稿作成イベント発火

モジュールの概要

Note Module

  • ノート(投稿)の作成を行う.
  • ノートの削除を行う.
  • ノート情報を返す.

Account Module

  • アカウント情報の管理を行う.
  • アカウントを凍結/解除する.
  • アカウントをサイレンスする.

Timeline Module

  • タイムラインを構築する.
    • 特定のアカウントが見ることのできる投稿をフォロー関係と公開範囲から決定する.
  • (ActivityPub 外部配送 / Push通知)の送信先アカウントを決定する.

Notification Module

  • クライアントに対してPush通知・メール通知を送信する.

ActivityPub Module

  • ActivityPubを経由した外部サーバーへのノート配送を行う.
  • ActivityPubを経由したノートの受信を行う.

ユースケース図

全体

  • アクター
    • アカウント
    • 別インスタンスのアカウント
    • 管理者
  • ユースケース
    • アカウント
      • アカウント
        • アカウント情報(プロフィール)を管理する
        • アカウント情報の取得
        • アカウントの削除
        • アカウントの検索
        • アカウントのサイレンス
        • アカウントの凍結
      • フォロー
        • アカウントをフォロー
        • アカウントをフォロー解除
      • ノート
        • ノートの作成
        • (自分の)ノートの削除
        • リノートの作成
        • リノートの解除(削除)
        • ノートへのリアクションの作成
        • ノートへのリアクションの解除
        • ノートのブックマーク
        • ノートの検索
        • ノートの取得
      • リスト
        • リストの作成
        • リストの削除
        • リストへのアカウントの追加
        • リストへのアカウントの除外(削除)
        • リストのノート取得
      • ドライブ
        • ファイルのアップロード
        • ファイルの取得
        • ノートへの紐付け
        • ノートへの紐付け解除
        • NSFWフラグの設定