Mastodon
Publishing to Mastodon via the Octopost API
Mastodon
Mastodon supports text posts, images, threads, polls, content warnings, and visibility controls. Because Mastodon is decentralized, each user belongs to a different instance with its own rules and limits. Octopost handles per-instance OAuth registration, character limit detection, media upload API differences, and thread chaining automatically -- you just send us your content.
Content Limits
| Type | Limit |
|---|---|
| Post text | Varies by instance (usually 500 characters, some allow 1,000 to 5,000+) |
| Images per post | 4 |
| Image formats | JPEG, PNG, GIF, WEBP |
| Image file size | Varies by instance (typically 8-16 MB) |
| Poll options | 2 to 4 |
| Video | Varies by instance |
Octopost fetches the actual character limit from each user's instance and validates your content against it before publishing. You do not need to know or track which instance a user is on.
Good to Know
- Character limits are not universal. A 500-character post might work on
mastodon.socialbut a user on a different instance might allow 5,000. Octopost detects the limit for each connected account automatically and validates accordingly. - Alt text is culturally important. The Mastodon community strongly values image descriptions. Posts without alt text may receive negative feedback on some instances. Include alt text when you can.
- Content warnings are a social norm. Many Mastodon communities expect content warnings for certain topics (spoilers, politics, food, etc.). This is a cultural expectation, not a technical requirement. Use the
spoiler_textfield when appropriate. - Federation is not guaranteed. Posts federate to other instances, but some instances block others. A post may succeed on the user's instance but not reach all followers. Octopost reports success based on the user's instance accepting the post.
- Polls and media are mutually exclusive. A post can have a poll or images, but not both. Octopost will reject a request that includes both.
Content Warnings
Set a content warning to hide the post body behind a "Show more" button with your warning text displayed:
{
"content": "The villain was actually the hero's father the whole time.",
"platforms": ["mastodon"],
"platform_options": {
"mastodon": {
"spoiler_text": "Movie spoilers"
}
}
}Visibility Settings
Control who can see your Mastodon post:
| Visibility | Meaning |
|---|---|
public | Visible on public timelines and to everyone (default) |
unlisted | Visible to everyone but not on public timelines |
private | Visible only to followers |
direct | Visible only to mentioned users |
{
"content": "This is just for my followers.",
"platforms": ["mastodon"],
"platform_options": {
"mastodon": {
"visibility": "private"
}
}
}Polls
Create polls with 2 to 4 options:
{
"content": "What's your preferred editor?",
"platforms": ["mastodon"],
"poll": {
"options": ["VS Code", "Neovim", "Zed", "Other"],
"expires_in": 86400,
"multiple": false
}
}Threads
Send a thread by including an array of content items. Octopost publishes them in order, wiring up the in_reply_to_id references so they appear as a connected thread:
{
"platforms": ["mastodon"],
"thread": [
{ "content": "A thought that needs more than one post." },
{ "content": "Here is the second part." },
{ "content": "And the conclusion." }
]
}Rate Limits
Rate limits vary by instance -- there is no universal Mastodon rate limit. Octopost tracks rate limit headers from each instance and backs off automatically when limits are approached.
Error Reporting
| What happened | What Octopost reports |
|---|---|
| Text exceeds instance character limit | Rejected before sending, with the limit for that instance and your character count |
| Instance unreachable | instance_unavailable -- includes which instance was unreachable |
| Token expired | Octopost refreshes automatically. If refresh fails: auth_failed -- user needs to reconnect their account |
| Poll and media both included | Rejected before sending -- Mastodon does not allow both in a single post |
| Media upload failed | media_failed -- with details about which file and why |
Things Octopost Handles for You
You do not need to worry about any of the following, but in case you are curious:
- Per-instance OAuth with dynamic app registration. Because Mastodon is decentralized, there is no single OAuth provider. When a user connects from a new instance, Octopost registers itself as an app on that instance via
POST /api/v1/apps, then runs the standard OAuth flow against that specific instance. Credentials are stored per-instance. - Instance limit detection. Octopost queries each instance's configuration endpoint to fetch the actual character limit, supported media types, and other constraints. This happens automatically so your content is validated against the correct limits.
- Token refresh. Octopost monitors token expiration and refreshes access tokens automatically before they expire.
- Media upload API fallback. Some Mastodon instances use the v2 media upload API, others only support v1. Octopost tries v2 first and falls back to v1 transparently.
- Thread chaining. Each reply in a thread must reference the previous post's ID via
in_reply_to_id. Octopost tracks these across the thread and sets them correctly.
Example
{
"content": "Hello fediverse! Check out what we have been building. https://octopost.ink",
"platforms": ["mastodon"],
"media": {
"images": [
{ "url": "https://example.com/screenshot.png", "alt": "Dashboard overview" }
]
},
"platform_options": {
"mastodon": {
"visibility": "public"
}
}
}That's it. Octopost takes care of the rest.