RelayAPI

Mastodon API

Connect any safe public Mastodon instance and publish statuses, media, polls, replies, and visibility controls.

Current RelayAPI capability

PropertyRelayAPI behavior
Platform keymastodon
ConnectionPer-instance OAuth app registration and authorization
Text limitAdvertised/enforced by the selected instance
MediaInstance-advertised image/video limits; one video or animated GIF cannot be mixed with other media
Polls2–4 options; cannot be combined with media
Visibilitypublic, unlisted, private, or direct
SchedulingYes, through RelayAPI
Native analytics endpointsNo

Connect an instance

Pass the account's home instance as a bare public HTTPS origin:

curl --get https://api.relayapi.dev/v1/connect/mastodon \
  -H "Authorization: Bearer $RELAY_API_KEY" \
  --data-urlencode "workspace_id=ws_example" \
  --data-urlencode "instance_url=https://mastodon.social"

RelayAPI resolves and validates the origin, reads /.well-known/oauth-authorization-server when the instance provides it, and registers a confidential client with POST /api/v1/apps. Instances older than Mastodon 4.3 can use the documented conventional OAuth endpoints.

Only same-origin authorization, token, registration, and profile endpoints are accepted. The stored instance is immutable connection metadata; there is deliberately no target_options.mastodon.instance_url override because a caller-selected host could receive the account's bearer token.

Reconnect an account that returns MASTODON_RECONNECT_REQUIRED. Legacy records without a validated metadata.instance_url are not allowed to publish.

Publish a status

curl -X POST https://api.relayapi.dev/v1/posts \
  -H "Authorization: Bearer $RELAY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: mastodon-status-20260809" \
  -d '{
    "content": "Hello from RelayAPI!",
    "targets": ["acc_mastodon_example"],
    "scheduled_at": "now",
    "target_options": {
      "mastodon": {
        "visibility": "unlisted",
        "language": "en"
      }
    }
  }'

RelayAPI forwards its operation ID as Mastodon's Idempotency-Key. An acc_... target selects one exact user and instance. The broader mastodon selector is also valid, but it expands to every authorized Mastodon account in the post's workspace boundary; each resolved account still uses its own pinned instance.

Media and alt text

{
  "content": "Four views from the trail",
  "targets": ["acc_mastodon_example"],
  "media": [
    {
      "url": "https://cdn.example.com/trail-1.jpg",
      "type": "image",
      "alt_text": "A rocky trail crossing a green valley"
    }
  ],
  "scheduled_at": "now"
}

Before downloading media, RelayAPI reads the instance configuration from GET /api/v2/instance (with the documented v1 fallback for older servers). It enforces the advertised image size, video size, and maximum attachment count. The documented default is four images when an older compatible response does not advertise max_media_attachments.

  • Images can be uploaded together up to the instance limit.
  • A video or animated GIF must be the only attachment.
  • Generic document attachments are rejected.
  • media[].alt_text is sent as the attachment description.
  • Two uploads run concurrently; asynchronous media processing is polled before the status is created.

Polls

{
  "content": "Which session should we run next?",
  "targets": ["acc_mastodon_example"],
  "scheduled_at": "now",
  "target_options": {
    "mastodon": {
      "poll": {
        "options": ["API design", "Testing", "Operations"],
        "expires_in": 86400,
        "multiple": false,
        "hide_totals": false
      }
    }
  }
}

Polls require 2–4 non-empty options, a positive expires_in value in seconds, and cannot include media.

target_options.mastodon

FieldTypeBehavior
contentstringMastodon-specific content override
mediaarrayMastodon-specific media override
visibilityenumDefaults to public
spoiler_textstringContent warning text
sensitivebooleanMarks attached media sensitive
languagestringStatus language code
in_reply_to_idstringStatus ID to reply to
quoted_status_idstringQuote-post status ID; requires an instance version that supports quote posts
pollobjectoptions, expires_in, optional multiple, and optional hide_totals

Provider capabilities vary across the Fediverse. RelayAPI does not rewrite an unsupported quote, visibility, or server-specific policy into a different operation; the instance response remains authoritative.

Security and lifecycle

  • OAuth credentials are registered for the chosen instance during the connection operation. New connections do not depend on a single hard-coded mastodon.social client.
  • Provider calls carrying the bearer token do not follow redirects and may reach only the validated public instance origin.
  • Mastodon access tokens generally do not expire through a standard refresh lifecycle. If the user revokes the token or the instance removes the app, reconnect.
  • A domain migration or instance move is a new security origin and requires a new connection; it cannot be changed on an existing post.

Official Mastodon references

Found something wrong? Help us improve this page.

On this page