主要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_token を
Authorization: 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を使う POST、PUT、PATCH、
DELETE は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でも、認証の有無で返すフィードが変わります。
- 未認証では、インスタンス上の公開投稿だけを返します。コミュニティ限定投稿や宛先を限定した投稿は含みません。
- 認証済みでは、自分、フォロー中の利用者、参加中のコミュニティをまとめたホームフィードを返します。
-
community=<ap_id>を指定すると、閲覧できる1つのコミュニティに絞り込みます。
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_id は
https://...
形式の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/:identifierGET /api/actors/:identifier/postsPUT /api/actors/me
|
公開情報の取得は不要。プロフィール更新は必要 |
| 投稿 |
GET /api/posts/:encodedApIdPOST /api/postsPATCH /api/posts/:encodedApIdDELETE /api/posts/:encodedApId
|
閲覧範囲に応じる。作成・編集・削除は必要 |
| リアクション |
POST|DELETE /api/posts/:encodedApId/likePOST|DELETE /api/posts/:encodedApId/repostPOST|DELETE /api/posts/:encodedApId/bookmark
|
必要 |
| フォロー |
POST|DELETE /api/followPOST /api/follow/acceptPOST /api/follow/reject
|
必要 |
| DM |
GET /api/dm/contactsGET|POST /api/dm/user/:encodedApId/messagesPOST /api/dm/user/:encodedApId/read
|
必要 |
| ストーリー |
GET|POST /api/storiesPOST /api/stories/viewPOST /api/stories/delete
|
必要 |
| 通知 |
GET /api/notificationsGET /api/notifications/unread/countPOST /api/notifications/read
|
必要 |
| 検索 |
GET /api/search/actorsGET /api/search/postsGET /api/search/remote
|
検索対象に応じる |
| メディア |
POST /api/media/uploadGET /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 だけが必須です。visibility は
public、unlisted、
followers、direct を使用できます。
コミュニティを指定した場合は、そのコミュニティの参加状態と投稿ルールも確認されます。
成功レスポンス:
{
"post": {
"ap_id": "https://social.example.com/ap/objects/...",
"content": "今日の進捗です",
"visibility": "public",
"published": "2026-07-29T12:00:00.000Z"
}
}
実際のレスポンスにはauthor、添付、リアクション数なども含まれます。
主なエラー:
400— bodyや値が不正401— セッションがない、または期限切れ403— CSRF検証、公開範囲、コミュニティ権限に失敗404— 返信先や対象がない、または閲覧できない-
429— リクエストが多すぎる。Retry-Afterを確認
多くの失敗レスポンスは、次の形式です。
{
"error": "説明",
"code": "BAD_REQUEST"
}
code は常に付くとは限りません。画面に出す文言を
error
の英語文字列だけに依存させず、まずHTTPステータスで分類してください。
主な変更系API
| 操作 | body | 成功 | よくある失敗 |
|---|---|---|---|
POST /api/follow |
{ "target_ap_id": "..." } |
フォロー状態 | 400、401、404 |
POST /api/communities |
{ "name": "...", "display_name": "...", "summary": "..."
}
|
作成したコミュニティ | 400、401、409 |
POST /api/dm/user/:encodedApId/messages |
{ "content": "...", "attachments": [] } |
メッセージと会話ID | 400、401、403 |
POST /api/media/upload |
multipart/form-data の file |
url、r2_key、content_type
|
400、401、413 |
POST /api/notifications/read |
{ "ids": ["activity-ap-id"] }、または
{ "read_all": true }
|
{ "success": true } |
400、401 |
この表にある通常の変更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_token、
403 insufficient_scope、不正なbodyの
400 invalid_request、ストレージを利用できない場合の
503 object_storage_unavailable です。
ActivityPubとの関係
このページの /api/* はクライアント向けAPIです。
サーバー間連合で使うActivityPubのURLや、yurucommuが追加するオブジェクトについては
連合の仕組みを参照してください。