Docs
Docs/Platforms/Mastodon

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

TypeLimit
Post textVaries by instance (usually 500 characters, some allow 1,000 to 5,000+)
Images per post4
Image formatsJPEG, PNG, GIF, WEBP
Image file sizeVaries by instance (typically 8-16 MB)
Poll options2 to 4
VideoVaries 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.social but 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_text field 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:

VisibilityMeaning
publicVisible on public timelines and to everyone (default)
unlistedVisible to everyone but not on public timelines
privateVisible only to followers
directVisible 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 happenedWhat Octopost reports
Text exceeds instance character limitRejected before sending, with the limit for that instance and your character count
Instance unreachableinstance_unavailable -- includes which instance was unreachable
Token expiredOctopost refreshes automatically. If refresh fails: auth_failed -- user needs to reconnect their account
Poll and media both includedRejected before sending -- Mastodon does not allow both in a single post
Media upload failedmedia_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.