Back to APIs list

Mastodon API examples & templates

Use these vals as a playground to view and fork Mastodon API examples and templates on Val Town. Run any example below or find templates that can be used as a pre-built solution.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { mastodon$sumStats } from "https://esm.town/v/jaandrle/mastodon$sumStats";
import { mastodon$fetchInstanceStats } from "https://esm.town/v/jaandrle/mastodon$fetchInstanceStats";
// https://api.val.town/eval/@jaandrle.mastodon$collectStats(@jaandrle.mastodon$instances_cz, 1)
export async function mastodon$collectStats(instances, weeks = 1) {
const data = await Promise.all(
instances.map(mastodon$fetchInstanceStats)
);
return data
.filter(({ stats }) => Boolean(stats) && Array.isArray(stats))
.map(({ instance, stats }) =>
Object.assign(
{ instance },
mastodon$sumStats(stats.slice(0, weeks + 1))
)
);
}
1
2
3
4
5
6
7
import { fetchJSON } from "https://esm.town/v/stevekrouse/fetchJSON?v=41";
export async function mastodon$fetchInstanceStats(instance) {
const url = "https://" + instance + "/api/v1/instance/activity";
const stats = await fetchJSON(url).catch((e) => e);
return { instance, stats };
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import process from "node:process";
import { postToMastodon } from "https://esm.town/v/sebdd/postToMastodon";
import { newRSSItems } from "https://esm.town/v/stevekrouse/newRSSItems?v=6";
export async function tootLatestPosts({ lastRunAt }: Interval) {
return Promise.all(
(await newRSSItems({
url: "https://sebastiandedeyne.com/index.xml",
lastRunAt,
}))
.slice(0, 2)
.map((item) =>
postToMastodon(
"https://mastodon.social/api/v1",
process.env.mastodonAccessToken,
`${item.title.charAt(0) === "↗" ? "🔗" : "✍️"} ${
item.title.replace("↗ ", "")
} ${item.link}`,
)
),
);
}
1
2
3
4
5
6
7
8
9
import { mastodon$sumStats } from "https://esm.town/v/jaandrle/mastodon$sumStats";
import { mastodon$instances_cz_stats_last_week } from "https://esm.town/v/jaandrle/mastodon$instances_cz_stats_last_week";
/* No. of statuses, login (~active users) and new registrations
for all Czech instances of Mastodon last week. */
export const mastodon$stats_cz_week = mastodon$instances_cz_stats_last_week.reduce(
(acc, stats) => mastodon$sumStats([acc, stats]),
{ statuses: 0, logins: 0, registrations: 0 },
);

WebFinger

This is a not-quite-complete ActivityPub implementation based on my blog post about building an AP implementation. It includes enough to look up bot@tmcw-activitypub.web.val.run on Mastodon and get some basic information.

Readme
Fork
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
export const activitypub = async (req: Request) => {
const { Hono } = await import("npm:hono@3.4.3");
const app = new Hono();
const DOMAIN = "tmcw-activitypub.web.val.run";
const USERS = new Map([
[
`acct:bot@${DOMAIN}`,
{
subject: `acct:bot@${DOMAIN}`,
aliases: [],
links: [
{
rel: "http://webfinger.net/rel/profile-page",
type: "text/html",
href: `https://${DOMAIN}/profile`,
},
{
rel: "self",
type: "application/activity+json",
href: `https://${DOMAIN}/u/bot`,
},
],
},
],
]);
const publicKey = `-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA7LBs3Qyuh93lRboTNXLN
hj4n92oK5Qg4oS8Cc81AXh04hD7nQSSKBhtarbHy2yPXeiKA+H3EGbcflsLvZCo2
B3OPNo2nGTCMyJM8HWDf/7JCOHHcy4tZC1ldjrItkb1YDABWwfoXxyBiGTyTVXjL
sBX5ArTGUPwctMSOdxlJp0ttFn5WDIHiPzxbSaEX/fzTy+HKr9RvYPu/hWWpXA/W
8QQRacZjslweupZFGCGPX1zJ+P0FSe81uV6N5cOPpy+vFkBQrvApwCSIyp/n7Rfq
UtU+zi/ru+wSxyvnoZPZa+zOXst8+pk7lIbmI6dyJ2+wijkykAxKt2DnDXWOSUGM
R+aNjc6tt8xp2MwmhAz91f1rIt2+jOhkPZ0m6aLV3B86J3iI0BIHXzQNydDtz5/P
EOj79vnnDwjCrWmbsfsIVCmECQDS7EW6Lzdc98GyiD/vyA4Epg3QgpeN4r7fELZj
8IfJJ7J8Z8nYewRoCVNnfvXpR26y+CLftMUi9LtPP1N78er1IdvZEer/8RIAc58r
S5VmDYBBfEduxPh/l3tn4A5Ri8smue26yG+wPkBj3CSqaOaNFxxZPgXcbI2OePrH
81goKk17g+5O0sZJGv+EAeFM1OQPXKqyu0DLY6PHJKGSho/B/BNWQ34vZnQhQF1r
++VZAcLEeqny/Cn6CHoeu5cCAwEAAQ==
-----END PUBLIC KEY-----`;
app.get("/u/bot", (ctx) => {
return ctx.json({
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1",
],
id: `https://${DOMAIN}/u/bot`,
type: "Person",
preferredUsername: `bot`,
summary: `Photos from ${DOMAIN}.com`,
inbox: `https://${DOMAIN}/api/inbox`,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { fetch } from "https://esm.town/v/std/fetch";
export function postToMastodon(mastodonApiUrl, mastodonAccessToken, status) {
return fetch(
`${mastodonApiUrl}/statuses?access_token=${mastodonAccessToken}`,
{
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
method: "POST",
body: JSON.stringify({
status,
}),
}
);
}
1
2
3
4
5
6
export function mastodon$sumStats(arr) {
const out = { statuses: 0, logins: 0, registrations: 0 };
for (const key of Object.keys(out))
for (const s of arr) out[key] += Number(s[key]);
return out;
}
1
2
3
4
5
6
import { mastodon$instances_cz } from "https://esm.town/v/jaandrle/mastodon$instances_cz";
import { mastodon$collectStats } from "https://esm.town/v/jaandrle/mastodon$collectStats";
/* No. of statuses, login (~active users) and new registrations
in Czech instances of Mastodon last week. */
export const mastodon$instances_cz_stats_last_week = await mastodon$collectStats(mastodon$instances_cz, 1);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
export const mastodon$instances_cz = [
"mastodonczech.cz",
"mastodon.arch-linux.cz",
"nasface.cz",
"witter.cz",
"cztwitter.cz",
"mastodon.pirati.cz",
"gomastodon.cz",
"f.cz",
"mastodon.macsnet.cz",
"toot.whatever.cz",
"lgbtcz.social",
"kompost.cz",
"boskovice.social",
"propulse.club",
"mastodon.1984.cz",
"mastodon.rozhlas.cz",
"mastodon.queerclub.cz",
"fediverse.cz",
"kocour.club",
"mastodon.urbancloud.cz",
"mastodon.telekomunikace.cz",
"ajtaci.club",
"mastodon.darksheep.social",
"mastodon.posvic.cz",
"social.filik.eu",
"social.meyer.cz",
"mastodon.vyboh.net",
"mastodon.starnet.cz",
"social.gwei.cz",
"blogator.com",
"hatedon.1984.cz",
"spondr.cz",
"mastodon.loutaci.cz",
"social.toxwat.cz",
"mastodon.hinata.cz",
"hlidacstatu.social",
"mastodon.train.cz",
"mastodon.stan.cz",
"mastodon.haxo.cz",
"mastodon.kiklhorn.cz",
"mastodon.skorpil.cz",
"mastodon.starlink.cz",
"kiklhorn.cz",
"social.bobek.cz",
"mutant.cz",
"social.taborsky.cz",
//"petrzprahy.cz", --- 404 Not Found
"social.lukacern.cz",
"mastodon.zs-studanka.cz",
1
Next