Mastodon
#Overview
Post to Mastodon, on whichever instance your account lives on. Mastodon has no central developer app, so yeetpost registers itself on your instance the first time somebody connects an account there, and then sends you to that instance to approve posting.
Mastodon posts are free to send. The account counts as one connected account, like LinkedIn or Bluesky. See pricing.
#How to connect
- In yeetpost, click Add connection, then Mastodon.
- Type the instance your account is on, for example
mastodon.social. Not sure which one? The list at joinmastodon.org/servers will tell you. - Approve the request on your instance. yeetpost asks for three scopes: read your account, write statuses, write media.
The host has to be reachable over https and has to be a public address. Nothing else is
needed from you: no client id, no client secret, no app registration of your own.
Your first Mastodon connection gets the slug mastodon. A second account gets a slug built
from its handle, so alex becomes alex_mastodon. GET /connections describes it as
@[email protected] (Mastodon).
The connection is identified by the instance host and the account id together. Mastodon
tokens do not expire and there is no refresh token, so a connection keeps working until you
revoke it on your instance. A revoked token shows up as a 401 on the next post.
#What works
| Thing | Value |
|---|---|
| Text limit | Your instance's own limit, read when you connect. 500 by default |
| Images | Up to 4 per post |
| Image formats | image/png, image/jpeg, image/gif, image/webp |
| Alt text | Yes, sent as each attachment's description |
| Threads | Yes, up to 24 replies under the head status |
| First comment | No, LinkedIn only |
| Scheduling | Yes |
| Permalink | Whatever your instance returned, in practice https://<host>/@<handle>/<status id> |
| Per-post fee | None |
The character limit is per instance. yeetpost reads
configuration.statuses.max_characters from your instance when you connect and checks
against that number, so an instance that allows 5000 gets 5000. Characters are counted as
code points.
The count is slightly stricter than your instance's own. Mastodon weighs every URL as 23 characters and counts a remote mention by its local part only. yeetpost counts both in full, so a link-heavy post is refused a little sooner than the instance would refuse it. That direction is the safe one: nothing is published and then rejected.
A broken thread is taken back, head included. If a segment is refused, every status
this request published is deleted, newest first, and the item comes back failed with the
instance's own error. If one of those deletes is refused too, what is still up is a shorter
thread and the item comes back sent with threadCount at the replies that survived.
Every segment carries an idempotency key of its own, so a retry inside a thread cannot double-post a reply.
Images ride on the head status. An upload that the instance is still processing is waited on for up to 5 seconds before the item is refused.
#Refusals
Every one of these is a per-item refusal: the other connections on the same post still go out. See the errors reference for the full vocabulary.
| Code | Status | When |
|---|---|---|
invalid_request | 400 | Text over the instance's limit, in the post or in any thread segment |
media_unsupported | 400 | More than 4 images |
shape_unsupported | 400 | A firstComment was given. Mastodon has no first comment |
unauthorized | 401 | The token was revoked on the instance. Connect the account again |
platform_rejected | 422 | The instance refused the image, is still processing it, or refused the status |
internal_server_error | 500 | Our fault. Quote the req_id when you report it |
#Post from curl
curl -X POST https://api.yeetpost.com/api/v2/posts \
-H "x-api-key: $YEETPOST_API_KEY" \
-H "content-type: application/json" \
-d '{
"text": "shipped the new api docs today",
"connectionSlugs": ["mastodon", "bluesky"]
}'#Post from Node
const response = await fetch("https://api.yeetpost.com/api/v2/posts", {
method: "POST",
headers: {
"x-api-key": process.env.YEETPOST_API_KEY,
"content-type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
text: "we rewrote the scheduler last month. three things we got wrong:",
connectionSlugs: ["mastodon"],
thread: [
"1. polling every second. the queue is a table, and postgres is fine with SKIP LOCKED.",
"2. retrying forever. five attempts and a dead letter beats an infinite loop.",
],
}),
});
const data = await response.json();
console.log(data.results[0].status, data.results[0].threadCount);#FAQ
#Which instances work?
Any Mastodon instance yeetpost can reach over https. The app is registered on your instance on demand the first time somebody connects an account there, and reused after that.
#Can I log in to yeetpost with Mastodon?
Not yet. Mastodon is a posting connection only. Log in with LinkedIn, X, Google or email, then connect the account.
#Why was my post refused when it fits my instance's counter?
yeetpost counts URLs in full instead of weighing them as 23 characters, so a post full of links is refused a little sooner than your instance would refuse it. Shorten the text, or move the links into a reply.
#What about content warnings, visibility and polls?
Not supported yet. A post goes out as a plain public status. Content warnings, visibility,
polls and the language field are on the list, not in the product.
#My token stopped working. What do I do?
Mastodon tokens do not expire, so a 401 means the token was revoked on the instance.
Connect the account again in the dashboard.