https://サーバー名/api/v1/statuses/投稿ID
var xmlHttpRequest=new XMLHttpRequest();
xmlHttpRequest.addEventListener("load",function(event) {
// xmlHttpRequest.responseにレスポンスが入っています
},false);
xmlHttpRequest.responseType="json";
xmlHttpRequest.open("GET","https://サーバー名/api/v1/timelines/home");
xmlHttpRequest.setRequestHeader("Authorization","Bearer アクセストークン");
xmlHttpRequest.send();
var xmlHttpRequest=new XMLHttpRequest();
xmlHttpRequest.addEventListener("load",function(event) {
// xmlHttpRequest.responseにレスポンスが入っています
},false);
xmlHttpRequest.responseType="json";
xmlHttpRequest.open("POST","https://mstdn.jp/api/v1/statuses?access_token=アクセストークン");
xmlHttpRequest.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");
xmlHttpRequest.send("status="+encodeURIComponent("テスト")+"&visibility=unlisted");
// file:///以下から試すと422エラーになるので注意
xmlHttpRequest.addEventListener("load",function(event) {
// xmlHttpRequest.responseにレスポンスが入っています
// xmlHttpRequest.getResponseHeader("Link")にページング情報
var links=xmlHttpRequest.getResponseHeader("Link").split(/, /);
var pagination={};
for (var i=0;i<=links.length-1;i++)
{
var parsed=links[i].match(/<([^>]+)>; rel="([^"]+)"/);
pagination[parsed[2]]=parsed[1];
}
// 次ページを開くなら pagination.next
// 前ページを開くなら pagination.prev
},false);
var xmlHttpRequest=new XMLHttpRequest();
var lastResponse="";
var data="";
xmlHttpRequest.addEventListener("progress",function(event) {
// chunk=今回受信した断片
var chunk=xmlHttpRequest.response.substring(lastResponse.length);
lastResponse=xmlHttpRequest.response;
// data=まだ処理してない断片 (改行まで受信してるとは限らない)
data=data+chunk;
// 空行をスキップ
data=data.replace(/^\n/gm,"");
// タイムアウトで切断されないようにするためのダミーデータをスキップ
data=data.replace(/^:(.*)\n/gm,"");
var content;
do {
content=data.match(/^event: (.*)\ndata: (.*)\n([\s\S]*)$/);
if (content!=null)
{
var event=content[1];
var payload=(content[2]!="undefined" ? JSON.parse(content[2]) : null);
// event(イベント名), payload(データ内容)で処理をする
data=content[3];
}
} while (content!=null);
},false);
xmlHttpRequest.open("GET","https://mstdn.jp/api/v1/streaming/public/local");
xmlHttpRequest.send(null);
| イベント名 | イベント内容 | データ内容 |
|---|---|---|
| update | 新しい投稿 | Status |
| status.update | 投稿の更新 (Mastodon3.5.0〜) | Status |
| delete | 投稿の削除 | 削除された投稿のID |
| notification | 新しい通知 | Notification |
| filters_changed | 設定のフィルターの更新 (Mastodon2.4.3〜) | なし (undefinedの文字) |
| announcement | 新しいお知らせ (Mastodon3.1〜) | Announcement |
| announcement.reaction | お知らせへの新しいリアクション (Mastodon3.1〜) | AnnouncementReaction ? |
| announcement.delete | お知らせの削除 (Mastodon3.1〜) | 削除されたお知らせのID |
| encrypted_message | E2E暗号化されたダイレクトメッセージ (Mastodon3.2〜) ※使われていません | ? |
| WebSocket版 | Long polling版 | 内容 |
|---|---|---|
| /api/v1/streaming/?stream=user | GET /api/v1/streaming/user | 自分のホームタイムライン+通知 |
| /api/v1/streaming/?stream=user:notification | GET /api/v1/streaming/user/notification | 自分へ通知 (Mastodon1.4.2〜) |
| /api/v1/streaming/?stream=public | GET /api/v1/streaming/public | 連合タイムライン (認証不要) |
| /api/v1/streaming/?stream=public:local | GET /api/v1/streaming/public/local | ローカルタイムライン (認証不要) (Mastodon1.1〜) |
| /api/v1/streaming/?stream=public:remote | GET /api/v1/streaming/public/remote | 連合タイムラインの別サーバーのみ (認証不要) (Mastodon3.1.4〜) |
| /api/v1/streaming/?stream=public:media | GET /api/v1/streaming/public?only_media=true | 連合タイムラインのメディアのみ (認証不要) (Mastodon2.4〜) |
| /api/v1/streaming/?stream=public:local:media | GET /api/v1/streaming/public/local?only_media=true | ローカルタイムラインのメディアのみ (認証不要) (Mastodon2.4〜) |
| /api/v1/streaming/?stream=public:remote:media | GET /api/v1/streaming/public/remote?only_media=true | 連合タイムラインの別サーバーのメディアのみ (認証不要) (Mastodon3.1.4〜) |
| /api/v1/streaming/?stream=direct | GET /api/v1/streaming/direct | 自分のダイレクトメッセージ (Mastodon2.4〜) |
| /api/v1/streaming/?stream=hashtag | GET /api/v1/streaming/hashtag | 連合タイムラインのクエリーtag(#は含めない)で指定したハッシュタグの投稿 (認証不要) |
| /api/v1/streaming/?stream=hashtag:local | GET /api/v1/streaming/hashtag/local | ローカルタイムラインのクエリーtag(#は含めない)で指定したハッシュタグの投稿 (認証不要) (Mastodon1.1〜) |
| /api/v1/streaming/?stream=list | GET /api/v1/streaming/list | クエリーlistで指定した自分のリストの投稿 (Mastodon2.1〜) |
// instanceInfoには /api/v1/instance のレスポンスを入れておく
var socket=new WebSocket(instanceInfo.urls.streaming_api+"/api/v1/streaming/?stream=public:local");
socket.addEventListener("message",function(event) {
var data=JSON.parse(event.data);
var event=data.event;
var payload=data.payload;
if (event=="update" || event=="notification")
{
payload=JSON.parse(data.payload);
}
// event, payloadで処理をする
},false);
var socket=new WebSocket(instanceInfo.urls.streaming_api+"/api/v1/streaming");
socket.addEventListener("message",function(event) {
var data=JSON.parse(event.data);
var stream=data.stream;
// event, payloadの扱いは変更なし
if (stream[0]=="public")
{
// 連合タイムラインの場合
}
},false);
// 受け取るStreamingに連合タイムラインを追加
socket.send(JSON.stringify({ "type": "subscribe", "stream": "public" }));
// Service Workerを登録しておく
navigator.serviceWorker.register("serviceWorker.js");
// Notification APIの利用許可を得ておく
Notification.requestPermission(function(permission) { ... });
function encodeBase64(buffer)
{
return window.btoa(
String.fromCharCode.apply(null,new Uint8Array(buffer)))
.replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"");
}
function decodeBase64(string)
{
return new Uint8Array([].map.call(
window.atob((string+"=".repeat((4-string.length%4)%4))
.replace(/\-/g,"+").replace(/_/g,"/")),
function(c) { return c.charCodeAt(0) }));
}
navigator.serviceWorker.ready.then(function(registration) {
registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: decodeBase64("VAPID公開鍵"),
}).then(function(subscription) {
var endpoint=subscription.endpoint;
var publicKey=encodeBase64(subscription.getKey("p256dh"));
var authSecret=encodeBase64(subscription.getKey("auth"));
var xmlHttpRequest=new XMLHttpRequest();
xmlHttpRequest.open("POST","https://サーバー名/api/v1/push/subscription?access_token=アクセストークン");
xmlHttpRequest.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");
xmlHttpRequest.send(
"subscription[endpoint]="+endpoint+
"&subscription[keys][p256dh]="+publicKey+
"&subscription[keys][auth]="+authSecret+
"&data[alerts][follow]=true&data[alerts][favourite]=true"+
"&data[alerts][reblog]=true&data[alerts][mention]=true");
});
});
// serviceWorker.jsの中身
self.addEventListener("push",function(event) {
var data=event.data.json();
// data.notification_typeには"favourite"など通知の種類
return event.waitUntil(
self.registration.showNotification(
data.title, // 通知内容の文章
{
icon: data.icon,
body: data.body, // 対象の投稿など
}
)
);
});
var clientId,clientSecret;
var xmlHttpRequest=new XMLHttpRequest();
xmlHttpRequest.addEventListener("load",function(event) {
clientId =xmlHttpRequest.response.client_id; // クライアントキー
clientSecret=xmlHttpRequest.response.client_secret; // クライアントシークレット
// 次のステップへ
},false);
xmlHttpRequest.responseType="json";
xmlHttpRequest.open("POST","https://サーバー名/api/v1/apps");
xmlHttpRequest.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");
xmlHttpRequest.send("client_name="+encodeURIComponent("アプリ名")+
"&redirect_uris=リダイレクト先"+
"&scopes="+encodeURIComponent(["read","write"].join(" ")));
// file:///以下から試すと422エラーになるので注意
| scope | 許可される操作 |
|---|---|
| read | 読み取り系 |
| write | 書き込み系 (投稿) |
| follow | フォロー、ブロック (Mastodon3.5.0〜はread/writeを使うように変更) |
| push | Web Push (Mastodon2.4.0〜) |
https://サーバー名/oauth/authorize?client_id=クライアントキー&scope=許可される操作&response_type=code&redirect_uri=リダイレクト先
リダイレクト先?code=code&scope=許可される操作
var accessToken;
var xmlHttpRequest=new XMLHttpRequest();
xmlHttpRequest.addEventListener("load",function(event) {
accessToken=xmlHttpRequest.response.access_token; // アクセストークン
},false);
xmlHttpRequest.responseType="json";
xmlHttpRequest.open("POST","https://サーバー名/oauth/token");
xmlHttpRequest.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");
xmlHttpRequest.send("client_id="+clientId+"&client_secret="+clientSecret+
"&redirect_uri=リダイレクト先"+
"&grant_type=authorization_code"+
"&code="+code);
https://mstdn.jp/api/v2/search?q=https%3A%2F%2Fサーバー名%2F%40ユーザー名%2F投稿ID&resolve=true (投稿IDを探す)
https://mstdn.jp/api/v1/accounts/search?q=ユーザー名%40サーバー名&resolve=true (アカウントIDを探す)
https://mstdn.jp/api/v1/accounts/lookup?acct=ユーザー名%40サーバー名 (サーバー上に既にIDがあるアカウントIDを探す) (Mastodon3.4〜)
x-ratelimit-limit: 300
x-ratelimit-remaining: 299
x-ratelimit-reset: 2018-08-30T02:40:00.363679Z
| Endpoint | Bucket | 制限数 | 期間 | 制限単位 |
|---|---|---|---|---|
| * /api/* | アカウントでのアクセス | 300 (Mastodon4.2〜?は1500) | 5分 | アカウント |
| * /api/* | アプリケーションのアクセス (Mastodon4.2〜?) | 300 | 5分 | アプリケーション |
| * /api/* | 認証不要のアクセス | 300 | 5分 | IPアドレス |
| POST /api/v1/statuses | 新規投稿 (Mastodon3.1.3〜) | 300 | 3時間 | アカウント |
| POST /api/v1/media | メディアのアップロード | 30 | 30分 | アカウント |
| DELETE /api/v1/statuses/:id POST /api/v1/statuses/:id/unreblog |
投稿の削除 | 30 | 30分 | アカウント |
| POST /api/v1/accounts/:id/follow | フォロー (Mastodon3.1.3〜) | 400 | 24時間 | アカウント |
| POST /api/v1/reports | 通報 (Mastodon3.1.3〜) | 400 | 24時間 | アカウント |
| POST /api/v1/accounts | アカウント作成 | 5 | 30分 | IPアドレス |
https://サーバー名/users/ユーザー名.json (アカウント情報)
https://サーバー名/users/ユーザー名/following.json?page=1 (フォロー情報)
https://サーバー名/users/ユーザー名/followers.json?page=1 (フォロワー情報)
https://サーバー名/users/ユーザー名/outbox?page=true (タイムライン情報)
https://サーバー名/users/ユーザー名/collections/featured (固定された投稿)
https://サーバー名/users/ユーザー名/collections/tags (注目のハッシュタグ)
https://サーバー名/users/ユーザー名/statuses/投稿ID.json (投稿情報)
https://サーバー名/tags/ハッシュタグ(#は含まない).json (ハッシュタグ検索結果情報)
https://サーバー名/.well-known/host-meta
https://サーバー名/.well-known/webfinger?resource=https://サーバー名/@ユーザー名 (現行のMastodonの指定先)
https://サーバー名/.well-known/webfinger?resource=acct:ユーザー名@サーバー名 (現行のMastodonの指定先)
https://サーバー名/.well-known/nodeinfo
https://サーバー名/nodeinfo/2.0 (現行のMastodonの指定先)
| サービス名 | サービスの概要 | APIの互換性 | "version"の値の例 |
|---|---|---|---|
| Mastodon Glitch Edition (glitch-soc, Glitch) | MastodonのFork。Mastodonに実験的な追加機能を加えている | ◎APIに関する変更点は基本はないので、互換性あり(追加はある) | 4.3.0-alpha.0+glitch |
| hometown | MastodonのFork。Mastodonに最小限の変更のみを加えている | ◎APIに関する変更点はないので、完全互換性あり ※NodeInfoのsoftware.nameは"hometown" |
4.0.2+hometown-1.1.1 |
| Pleroma | Twitterライク。バックエンドとフロントエンドを分離するコンセプトでMastodonクライアントを使うことも想定されている | ◎互換性は高めで、 独自拡張も多い | 2.7.2 (compatible; Pleroma 2.4.0-516-gdc63aaf8) |
| Akkoma | PleromaのFork | ◎互換性は高め ※Pleromaを引き継いでいる |
2.7.2 (compatible; Akkoma 3.5.0-develop) |
| Misskey | Twitterライク | ×独自APIで互換性なし ※Mastodon互換APIは一時期あったが廃止 |
|
| Firefish (Calckey) | MisskeyのFork。 ※以前の名称はCalckey |
△開発は継続中のようです | 3.0.0 (compatible; Firefish 1.0.5-dev12) |
| Iceshrimp | Misskeyの(厳密にはFirefishの)Fork | △開発は継続中のようですが、 Misskey Forkの中では最もMastodon API対応に積極的で進んでいるようです | 3.0.0 (compatible; Iceshrimp 1.0.2) |
| Catodon | Misskeyの(厳密にはFirefishの)Fork ※Iceshrimpにrebase予定 |
△Firefish→Iceshrimpの実装そのままのようです | 3.0.0 (compatible; Firefish 23.12-alpha.3) |
| Threads | Meta社のTwitterライク | ×ActivityPub互換対応のみが言及されており、 クライアントAPIはありません | |
| GoToSocial | Twitterライク。バックエンドのみを提供するコンセプトでMastodonクライアントを使うことも想定されている | △互換性は高いはずですが、GoToSocial自体がまだα版である点に注意 | 3.5.3+0.13.0 |
| Wildebeest | Cloudflare社のTwitterライク。Mastodon互換のサーバーサービスとしている | ○互換性は高いはずですが、不完全なまま ※Wildebeest自体が開発終了となってしまいました |
4.0.2 (compatible; Wildebeest 0.0.1) |
| GNU social | Twitterライク | ×Twitter API互換 | |
| Friendica | Facebookライク | △まだ対応途中のようです | 2.8.0 (compatible; Friendica 2023.01) |
| Pixelfed | Instagramライク | ○基本的には互換性があるものの、アクセストークンなしのアクセスができなかったり、一部独自のAPIもある模様 | 2.7.2 (compatible; Pixelfed 0.11.4) |
| PeerTube | YouTubeライク | ×独自APIで互換性なし | |
| Lemmy | Redditライク | ×独自APIで互換性なし |
GET /api/v1/pleroma/statuses/:id/reactions (投稿に付いた絵文字リアクション一覧)
GET /api/v1/pleroma/statuses/:id/reactions/:emoji (投稿に付いた指定の絵文字リアクションの一覧)
PUT /api/v1/pleroma/statuses/:id/reactions/:emoji (追加)
DELETE /api/v1/pleroma/statuses/:id/reactions/:emoji (削除)
GET /api/v1/statuses/:id/emoji_reactioned_by (投稿に付いた絵文字リアクションの一覧)
PUT /api/v1/statuses/:id/emoji_reactions/:emoji (追加)
DELETE /api/v1/statuses/:id/emoji_reactions/:emoji (削除)
POST /api/v1/statuses/:id/emoji_unreaction (一括削除)
GET /api/v1/emoji_reactions (自分が絵文字リアクションを付けた投稿一覧)
POST /api/v1/statuses/:id/react/:emoji (追加)
POST /api/v1/statuses/:id/unreact/:emoji (削除)
| サービス系統 | Statusの 追加属性 |
Notificationの type属性の値 |
エンドポイント |
|---|---|---|---|
| Pleroma系 (Pleroma, Akkoma) |
pleroma.emoji_reactions | pleroma:emoji_reaction | GET /api/v1/pleroma/statuses/:id/reactions (一覧) GET /api/v1/pleroma/statuses/:id/reactions/:emoji (一覧) PUT /api/v1/pleroma/statuses/:id/reactions/:emoji (追加) DELETE /api/v1/pleroma/statuses/:id/reactions/:emoji (削除) |
| Fedibird系 (Fedibird, kmyblueフォーク) |
emoji_reactions emoji_reactions_count emoji_reactioned |
emoji_reaction | GET /api/v1/statuses/:id/emoji_reactioned_by (一覧) PUT /api/v1/statuses/:id/emoji_reactions/:emoji (追加) DELETE /api/v1/statuses/:id/emoji_reactions/:emoji (削除) POST /api/v1/statuses/:id/emoji_reactions (一括追加) ※kmyblueフォークのみ POST /api/v1/statuses/:id/emoji_unreaction (一括削除) GET /api/v1/emoji_reactions (自分が付けた投稿一覧) |
| glitch-soc系 (glitch-soc, Firefish) |
reactions | reaction | POST /api/v1/statuses/:id/react/:emoji (追加) POST /api/v1/statuses/:id/unreact/:emoji (削除) |
PUT /api/v1/statuses/:id/emoji_reactions/:emoji (追加)
POST /api/v1/statuses/:id/emoji_reactions (一括追加)
GET /api/v1/pleroma/statuses/:id/quotes
GET /api/v1/statuses/:id/referred_by
| サービス系統 | Statusの 追加属性 |
引用した投稿を得るエンドポイント |
|---|---|---|
| 小規模サーバー系 (itabashi.0j0.jp, mstdn.y-zu.org, odakyu.appなど) |
quote | なし |
| Pleroma系 (Pleroma2.6〜) |
pleroma.quote pleroma.quote_id pleroma.quote_url pleroma.quote_visible pleroma.quotes_count (Pleroma2.6.51〜) |
GET /api/v1/statuses/:id/context ※descendants内、返信も含まれる GET /api/v1/pleroma/statuses/:id/quotes (Pleroma2.6.51〜) |
| Akkoma系 (Akkoma) |
quote quote_id |
GET /api/v1/statuses/:id/context ※descendants内、返信も含まれる |
| Fedibird系 (Fedibird, kmyblueフォーク7.0〜) |
quote quote_id ※Fedibirdは値があるときだけ出現 status_referred_by_count ※引用数は参照数に含まれる |
GET /api/v1/statuses/:id/referred_by ※参照も含まれる GET /api/v1/statuses/:id/context?with_reference=1 ※references内、参照も含まれる |
https://サーバー名/users/ユーザー名.rss (投稿)
https://サーバー名/users/ユーザー名/with_replies.rss (投稿と返信)
https://サーバー名/users/ユーザー名/media.rss (メディア付き投稿のみ)
https://サーバー名/users/ユーザー名/tagged/ハッシュタグ(#は含まない).rss (注目のハッシュタグ)
https://サーバー名/tags/ハッシュタグ(#は含まない).rss (ハッシュタグタイムライン)
https://サーバー名/api/oembed.json?url=埋め込みたいページのURL
web+mastodon://share?text=投稿本文 (シェア)
web+mastodon://follow?uri=ユーザー名@サーバー名 (フォロー)
https://サーバー名/share?text=投稿本文 (シェア)
https://サーバー名/authorize_interaction?uri=ユーザー名@サーバー名 (フォロー)
https://サーバー名/interact/投稿ID?type=reply (返信) (〜Mastodon3.5)
https://サーバー名/interact/投稿ID?type=reblog (ブースト) (〜Mastodon3.5)
https://サーバー名/interact/投稿ID?type=favourite (いいね) (〜Mastodon3.5)
https://サーバー名/@ユーザー名@ユーザーのサーバー名/投稿ID (投稿への各操作) (Mastodon4.0〜)
navigator.share({ url: 共有したいURL });
戻る