yeetpost

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

  1. In yeetpost, click Add connection, then Mastodon.
  2. Type the instance your account is on, for example mastodon.social. Not sure which one? The list at joinmastodon.org/servers will tell you.
  3. 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

ThingValue
Text limitYour instance's own limit, read when you connect. 500 by default
ImagesUp to 4 per post
Image formatsimage/png, image/jpeg, image/gif, image/webp
Alt textYes, sent as each attachment's description
ThreadsYes, up to 24 replies under the head status
First commentNo, LinkedIn only
SchedulingYes
PermalinkWhatever your instance returned, in practice https://<host>/@<handle>/<status id>
Per-post feeNone

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.

CodeStatusWhen
invalid_request400Text over the instance's limit, in the post or in any thread segment
media_unsupported400More than 4 images
shape_unsupported400A firstComment was given. Mastodon has no first comment
unauthorized401The token was revoked on the instance. Connect the account again
platform_rejected422The instance refused the image, is still processing it, or refused the status
internal_server_error500Our 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.

Other platforms