GitHub

主要APIの概要

yurucommuのクライアントを作る人に向けて、接続先の確認、認証、ページング、よく使うAPIを説明します。 すべてのエンドポイントを列挙した契約書ではありません。

APIはインスタンスごとに提供されます。まず接続先から情報を取得し、返されたURLを使ってください。 レスポンスの型を利用できる @takosjp/yurucommu-api が、通常のクライアント実装では第一候補です。

1. 接続先を確認する

GET /.well-known/social-server

最初にこのURLを取得します。APIの基準URL、利用できる認証方法、主要なエンドポイント、 サーバーが対応する機能が返ります。 /.well-known/yurucommu も同じ情報を返す互換URLです。

{
  "product": "yurucommu",
  "apiBaseUrl": "https://social.example.com",
  "issuer": "https://accounts.example.com",
  "auth": {
    "oidc": true,
    "password": false
  },
  "endpoints": {
    "api": "https://social.example.com/api",
    "currentUser": "https://social.example.com/api/auth/me",
    "timeline": "https://social.example.com/api/timeline"
  }
}

クライアント側で /api の場所や認証方法を決め打ちせず、 このレスポンスを起点にすると、別ドメインで動くインスタンスにも接続できます。

const serverOrigin = "https://social.example.com";
const discovery = await fetch(
  new URL("/.well-known/social-server", serverOrigin),
).then((response) => response.json());

2. TypeScriptクライアント

TypeScriptでは @takosjp/yurucommu-api の利用を推奨します。 投稿、プロフィール、コミュニティ、DM、通知などの型とリクエスト関数をまとめて利用できます。

import {
  fetchTimeline,
  setYurucommuApiTransport,
} from "@takosjp/yurucommu-api";

setYurucommuApiTransport({
  resolveUrl: (path) => new URL(path, discovery.apiBaseUrl).toString(),
  getAuthHeaders: () => ({
    Authorization: `Bearer ${mobileSessionToken}`,
  }),
  credentials: "omit",
});

const page = await fetchTimeline({ limit: 20 });

サーバーの新しいAPIが、公開済みSDKより先に使えるようになることがあります。 SDKにまだ関数がない場合は、そのルートだけ fetch で呼び出してください。たとえば GET /api/timeline/following はサーバー側にあり、 SDKの公開状況によっては直接呼び出す必要があります。

3. 認証

yurucommuの通常APIはセッションで利用者を識別します。 ブラウザとネイティブアプリでは、同じセッションを異なる方法で送ります。

用途 ログイン 以後のリクエスト
ブラウザ POST /api/auth/login または GET /api/auth/login/:provider セッションCookie。credentials: "include" を使用
ネイティブ・モバイル POST /api/auth/mobile/login または POST /api/auth/mobile/oidc 返された access_tokenAuthorization: Bearer ... で送信

モバイルの access_token は、そのyurucommuインスタンスが発行する セッション情報です。外部のOAuthアクセストークンではありません。 GET /api/auth/me で、現在の利用者とセッションの有効性を確認できます。

モバイルのパスワードログイン

POST /api/auth/mobile/login
Content-Type: application/json

{
  "password": "your-password"
}

成功すると、次の形式でセッション情報が返ります。

{
  "access_token": "...",
  "token_type": "Bearer",
  "expires_in": 2592000
}

CSRF保護

Cookieを使う POSTPUTPATCHDELETE はCSRF検証の対象です。 Origin、または Referer のoriginが、 インスタンスの APP_URL か、運用者が CSRF_ALLOWED_ORIGINS に登録したURLと一致する必要があります。

Cookieを付けずにモバイル用セッションを Authorization ヘッダーで送るリクエストは、 Cookieを利用したCSRFの対象ではありません。CookieとBearerを同時に送ると Cookieが優先され、CSRF検証も行われます。

用途が限定されたOAuthトークン

POST /api/apps/:name/deploy は通常の利用者セッションではなく、 apps:deploy スコープを持つOAuthアクセストークンを使います。 このトークンと、モバイルログインで返るセッショントークンは交換できません。

4. アカウントの切り替え

1つのインスタンスにはルートのownerアカウントがあり、ownerは最大20個の サブアカウントを作成できます。

API 内容
GET /api/auth/accounts ルートアカウントと、そのownerが作成したサブアカウントを取得
POST /api/auth/accounts サブアカウントを作成。インスタンスのownerだけが利用でき、上限は20個
POST /api/auth/switch 同じownerに属するアカウントへ切り替え

別のownerが持つアカウントへは切り替えられません。切り替え時には古いセッションが破棄され、 新しいセッションが発行されます。現在の /api/auth/switch はブラウザのCookieセッション専用です。

{
  "ap_id": "https://social.example.com/ap/users/sub-account"
}

5. フィードとページング

GET /api/timeline

同じURLでも、認証の有無で返すフィードが変わります。

GET /api/timeline/following

認証済みの利用者向けです。自分と、フォロー中の利用者の投稿だけを返します。

ページを続けて取得する

limit の初期値は20、最大値は90です。 次のページがあるときは next_cursor が返ります。 その値を変更せず、次のリクエストの before に渡してください。

{
  "posts": [],
  "has_more": true,
  "next_cursor": "server-issued-value"
}
const params = new URLSearchParams({
  limit: "20",
  before: previousPage.next_cursor,
});

const nextPage = await fetch(
  `${discovery.apiBaseUrl}/api/timeline?${params}`,
).then((response) => response.json());

next_cursor はサーバーだけが解釈する不透明な値です。 日時や ap_id として分解したり、最後の投稿の ap_id で置き換えたりしないでください。

6. IDをURLに入れるとき

投稿、利用者、コミュニティなどの ap_idhttps://... 形式のURLです。パスの1区間に入れる場合は、値全体を encodeURIComponent でエンコードします。

const path = `/api/posts/${encodeURIComponent(post.ap_id)}`;
const dmPath =
  `/api/dm/user/${encodeURIComponent(otherActor.ap_id)}/messages`;

クエリに入れる場合は URLSearchParams を使います。 URLを文字列連結だけで組み立てると、:/ が別のパスとして解釈されるため注意してください。

7. よく使うAPI

機能 主なAPI 認証
利用者 GET /api/actors/:identifier
GET /api/actors/:identifier/posts
PUT /api/actors/me
公開情報の取得は不要。プロフィール更新は必要
投稿 GET /api/posts/:encodedApId
POST /api/posts
PATCH /api/posts/:encodedApId
DELETE /api/posts/:encodedApId
閲覧範囲に応じる。作成・編集・削除は必要
リアクション POST|DELETE /api/posts/:encodedApId/like
POST|DELETE /api/posts/:encodedApId/repost
POST|DELETE /api/posts/:encodedApId/bookmark
必要
フォロー POST|DELETE /api/follow
POST /api/follow/accept
POST /api/follow/reject
必要
DM GET /api/dm/contacts
GET|POST /api/dm/user/:encodedApId/messages
POST /api/dm/user/:encodedApId/read
必要
ストーリー GET|POST /api/stories
POST /api/stories/view
POST /api/stories/delete
必要
通知 GET /api/notifications
GET /api/notifications/unread/count
POST /api/notifications/read
必要
検索 GET /api/search/actors
GET /api/search/posts
GET /api/search/remote
検索対象に応じる
メディア POST /api/media/upload
GET /media/:filename
アップロードは必要。取得はメディアの公開範囲に応じる

8. コミュニティのAPI

yurucommuの画面では「コミュニティ」と呼びます。ActivityPub上では Group として連合します。REST APIは役割ごとに次のまとまりに分かれています。

まとまり パス できること
検索・詳細 /api/communities
/api/communities/:identifier
公開コミュニティと、参加中の非公開コミュニティを取得
参加 /:identifier/join
/:identifier/leave
公開方針に従って参加、承認待ち、退出
メンバー /:identifier/members 一覧、削除、役割の変更
参加申請 /:identifier/requests 申請の一覧、承認、却下
招待 /:identifier/invites 招待の作成、一覧、取り消し
メッセージ /:identifier/messages コミュニティ内の会話を取得、送信、編集、削除
設定 /:identifier/settings 表示、参加方法、投稿できる役割などを変更

上の短いパスはすべて /api/communities に続きます。 管理操作にはownerまたはmoderatorの権限が必要です。 最後のownerを削除したり、owner以外へ変更したりすることはできません。

9. 変更リクエストの読み方

変更系APIを調べるときは、認証、送信するbody、成功レスポンス、 エラーの4点を確認してください。投稿作成を例にします。

POST /api/posts

認証: Cookieセッション、またはモバイル用Bearerセッションが必要です。

body:

{
  "content": "今日の進捗です",
  "summary": "開発メモ",
  "visibility": "public",
  "in_reply_to": "https://social.example.com/ap/objects/parent",
  "community_ap_id": "https://social.example.com/ap/groups/builders",
  "attachments": [
    {
      "url": "/media/photo.webp",
      "r2_key": "uploads/photo.webp",
      "content_type": "image/webp"
    }
  ]
}

content だけが必須です。visibilitypublicunlistedfollowersdirect を使用できます。 コミュニティを指定した場合は、そのコミュニティの参加状態と投稿ルールも確認されます。

成功レスポンス:

{
  "post": {
    "ap_id": "https://social.example.com/ap/objects/...",
    "content": "今日の進捗です",
    "visibility": "public",
    "published": "2026-07-29T12:00:00.000Z"
  }
}

実際のレスポンスにはauthor、添付、リアクション数なども含まれます。

主なエラー:

多くの失敗レスポンスは、次の形式です。

{
  "error": "説明",
  "code": "BAD_REQUEST"
}

code は常に付くとは限りません。画面に出す文言を error の英語文字列だけに依存させず、まずHTTPステータスで分類してください。

主な変更系API

操作 body 成功 よくある失敗
POST /api/follow { "target_ap_id": "..." } フォロー状態 400401404
POST /api/communities { "name": "...", "display_name": "...", "summary": "..." } 作成したコミュニティ 400401409
POST /api/dm/user/:encodedApId/messages { "content": "...", "attachments": [] } メッセージと会話ID 400401403
POST /api/media/upload multipart/form-datafile urlr2_keycontent_type 400401413
POST /api/notifications/read { "ids": ["activity-ap-id"] }、または { "read_all": true } { "success": true } 400401

この表にある通常の変更APIは、すべて利用者セッションが必要です。 ブラウザでは前述のCSRF条件も適用されます。

10. アプリを配置するAPI

POST /api/apps/:name/deploy

認証: apps:deploy スコープを持つOAuthアクセストークンを Authorization: Bearer ... で送ります。

body:

{
  "files": [
    {
      "path": "index.html",
      "content": "PGgxPkhlbGxvPC9oMT4=",
      "contentType": "text/html; charset=utf-8"
    }
  ]
}

content はBase64です。1回のリクエストで送れるファイルは最大1000件です。

成功レスポンス:

{
  "url": "https://social.example.com/hosted/oauth-subject/my-app/",
  "files": 1
}

主なエラー: 401 unauthorized / invalid_token403 insufficient_scope、不正なbodyの 400 invalid_request、ストレージを利用できない場合の 503 object_storage_unavailable です。

ActivityPubとの関係

このページの /api/* はクライアント向けAPIです。 サーバー間連合で使うActivityPubのURLや、yurucommuが追加するオブジェクトについては 連合の仕組みを参照してください。