Mastodon

Publish statuses, threads and replies with media, alt text, content warnings and visibility to any Mastodon server through the Postgale API and MCP server.

Postgale publishes to Mastodon accounts on any server: statuses with media and alt text, content warnings, visibility, threads and replies, and deletes of what was published. Everything is available over the REST API (paths relative to https://postgale.com/api/v1) and the MCP server (connect_account, create_post, manage_published_post). Each connected account has platform mastodon; its platformAccountId is <account id>@<server>.

Connect an account

Mastodon runs on many independent servers, so connecting starts with yours.

  1. In Postgale open Dashboard → Accounts → Mastodon and enter your server's domain: for @[email protected] that is hachyderm.io.
  2. You are sent to your server's own sign-in and authorization page. Approve Postgale. It asks for Mastodon's standard read, write, follow and push scopes (no admin scopes): read covers your account data, write posting and editing, follow your follows, blocks and mutes, and push push notification subscriptions. Postgale uses them only to read your profile and your server's limits and to upload media, post and delete statuses; it does not follow, block or mute anyone or subscribe to notifications.
  3. Back in Postgale the account is listed as @[email protected].

Or ask for a link from your code (instance is required):

GET /api/v1/connect/mastodon?instance=hachyderm.io
curl https://postgale.com/api/v1/connect/mastodon?instance=hachyderm.io \
  -H 'Authorization: Bearer sk_…'

# {"authUrl":"https://postgale.com/api/oauth/mastodon/consent?state=…","expiresInSeconds":600}

The first time anyone connects an account on a server, Postgale registers itself there as an app; later connections reuse it. Only public domain names are accepted (no IP addresses, ports or local names). A server that is not Mastodon-compatible answers 400. Mastodon access tokens do not expire. If you revoke Postgale under Preferences → Account → Authorized apps, the next call fails: the account becomes needs_reconnect and account.disconnected is sent (reason token_revoked). Connecting again updates the same account. Disconnecting the account in Postgale revokes the token on your server.

Publish

The post content is the status text. The character limit is your server's (500 on most servers, more on some); as on Mastodon, every link counts 23 characters, @[email protected] counts as @user, and a content warning counts toward the limit. Media is uploaded by Postgale, with the alt text you give, and the status is posted once your server has processed it.

POST /api/v1/posts
curl -X POST https://postgale.com/api/v1/posts \
  -H 'Authorization: Bearer sk_…' \
  -H 'Content-Type: application/json' \
  -d '{"content":"Our spring release is out: https://example.com/blog/spring #release","platforms":[{"accountId":"acc_masto","platformSpecificData":{"mediaUrls":["https://media.postgale.com/…/hero.jpg"],"altTexts":["The new dashboard in dark mode"],"visibility":"public","language":"en"}}],"publishNow":true}'
platformSpecificDataWhat it does
mediaUrl / mediaUrlsAttachments: up to your server's maximum (usually 4 images), or one video or audio file. Public https URLs, e.g. an uploaded media publicUrl. Size limits are the server's
altText / altTextsAlt text (description) per attachment, ≤1500 characters
visibilitypublic (default), unlisted, private (followers only) or direct (mentioned people only)
spoilerTextContent warning shown before the text; media is then marked sensitive
sensitiveMark the media sensitive without a content warning
languageISO 639 code of the text, e.g. en
threadItemsA thread: up to 25 statuses of {content, mediaUrl?, mediaUrls?, altText?, altTexts?}, each a reply to the previous one, with the same visibility. Replaces the post text
inReplyToIdReply to an existing status on your server (its id)

Limits are checked when the post is created (with the limits your server reported when you connected) and again when publishing. The target's platformPostId is the status id and url the status link on your server. For a thread they are those of the first status; if a later status fails, the thread stops there and the target gets a warning. Each status is sent with an Idempotency-Key, so a retried request never posts twice.

Delete

MethodPathWhat it does
POST/posts/{id}/unpublishDelete the status (for a thread: the first one)
GET/accounts/{id}/healthWhether the token still works

Deletes are queued for a person while approval applies to the API key, the organization or the account (202 pending_approval; MCP manage_published_post returns the queued action).

Mastodon's rules to know

  • Rate limits: when a server answers 429, Postgale retries after the reset time it gives.
  • Media processing: videos are processed by your server; if that takes longer than two minutes, the post is retried later.
  • Analytics: favourites, boosts and replies are not collected yet, so post and account analytics answer not_supported.

On this page