# Platform Guides

What Relaycast can post to each social network, how each account connects, and where the per-platform rules live.


Relaycast publishes to ten networks through one request shape. You send one `POST /v1/posts` with shared `content` and `media`, list the accounts in `targets`, and add platform-specific settings in `targets[].options`. Each target is validated against its platform's rules **before** anything is queued, so content a platform would reject comes back as a `400` instead of a failed job.

## Supported platforms

| Platform | ID | Connects with | Text only | Images | Video | Multi-image / carousel | Other formats |
| --- | --- | --- | --- | --- | --- | --- | --- |
| [X (Twitter)](/docs/platforms/twitter) | `twitter` | OAuth 2.0 | Yes | Up to 4 (or 1 GIF) | 1 | Up to 4 images | Threads, polls, quote posts, Communities |
| [Instagram](/docs/platforms/instagram) | `instagram` | OAuth (Instagram Login or Facebook Login) | No | JPEG | 1 (as a Reel) | Carousel of 2–10 | Reels, Stories, trial reels, collaborators |
| [Facebook](/docs/platforms/facebook) | `facebook` | OAuth (Facebook Login) | Yes (optional link card) | Up to 10 | 1 | Up to 10 photos | Reels, Stories, unpublished Page posts |
| [LinkedIn](/docs/platforms/linkedin) | `linkedin` | OAuth 2.0 | Yes (optional article link) | Up to 20 | 1 | Up to 20 images | PDF documents, Company Page mentions |
| [TikTok](/docs/platforms/tiktok) | `tiktok` | OAuth (Login Kit) | No | 1–10 photos | 1 | Photo posts (1–10) | Inbox (draft) mode |
| [YouTube](/docs/platforms/youtube) | `youtube` | Google OAuth | No | No | Exactly 1 | No | First comment, custom thumbnail |
| [Threads](/docs/platforms/threads) | `threads` | OAuth | Yes (optional link card) | Yes | Yes | Carousel up to 20 items | Quote posts, topic tags |
| [Pinterest](/docs/platforms/pinterest) | `pinterest` | OAuth 2.0 | No | 1 | 1 | Carousel of 2–5 images | Board required |
| [Bluesky](/docs/platforms/bluesky) | `bluesky` | App password | Yes (auto link card) | Up to 4 | 1 | Up to 4 images | Quote posts, reply/quote controls, content warnings |
| [Google Business Profile](/docs/platforms/google-business) | `google_business` | Google OAuth | Yes | 1 photo | No | No | Events, offers, call-to-action buttons |

Document (PDF) media (`"type": "document"`) is accepted by **LinkedIn only**. Sending a document to any other account returns a `validation_error` for that account.

## Live streaming

[Live Publish](/docs/live) restreams one source (HLS, MP4, DASH, RTMP, RTSP, SRT or a media library video) to several platforms at once:

| Platform | Live | How |
| --- | --- | --- |
| YouTube | Yes | Connected channel: the broadcast is created, started and completed automatically |
| Facebook | Pages: yes · profiles/groups: stream key | Pages through the API (`publish_video`); profiles and groups as custom RTMP |
| [Twitch](/docs/platforms/twitch) | Yes | Connected channel (live-only: Twitch can't receive posts) |
| Instagram, X, TikTok, LinkedIn | Stream key | Custom RTMP destination with the server URL and key from the platform (each platform decides who gets live access) |
| Kick and any RTMP/RTMPS server | Stream key | Custom RTMP destination |
| Threads, Pinterest, Bluesky, Google Business | No | These platforms have no live streaming |

## Features by platform

| Platform | Scheduling | Post analytics | Comments / inbox |
| --- | --- | --- | --- |
| X (Twitter) | Yes | Impressions, likes, replies, reposts + quotes, bookmarks, clicks (own posts, first 30 days) | No |
| Instagram | Yes | Likes, comments, plus insights (views, reach, shares, saves…) | DM inbox and comment-to-DM automations |
| Facebook | Yes | Reactions, comments, shares; impressions/clicks need `read_insights` | Messenger inbox (opt-in) |
| LinkedIn | Yes | Likes, comments; impressions/clicks need extra LinkedIn access | No |
| TikTok | Yes | Views, likes, comments, shares (needs `video.list`) | No |
| YouTube | Yes | Views, likes, comments | No (a first comment can be posted) |
| Threads | Yes | Views, likes, replies, reposts + quotes + shares | No |
| Pinterest | Yes | Impressions, saves, clicks, reactions, comments (last 90 days) | No |
| Bluesky | Yes | Likes, replies, reposts + quotes, bookmarks | No |
| Google Business Profile | Yes | Not available (Google retired the per-post API) | No |

Scheduling is handled by Relaycast, not by the platform: a scheduled post is held in the queue and sent at `scheduledFor`, so every platform supports it the same way. See [Scheduling](/docs/scheduling).

Analytics are loaded per post from the dashboard (**Posts → Analytics**); see [Analytics](/docs/analytics). The inbox and comment automations are covered in [Inbox & Comment Automation](/docs/inbox).

## How posting works per platform

1. **Validation.** Each target's text (its own `content` override, or the shared `content`), the shared `media`, and its `options` are checked against that platform's rules. Problems are returned per account ID in `error.details`.
2. **Queueing.** One target is created per account and one [credit](/docs/credits) is charged per target.
3. **Publishing.** The worker downloads the media, uploads it to the platform, and records the platform's post ID and URL on the target (`externalPostId`, `externalUrl`). Temporary failures (timeouts, rate limits, 5xx) are retried with exponential backoff. Permanent failures (bad content, revoked access) mark the target `failed` and refund its credit.
4. **Revoked access.** If a platform reports that access was revoked, the account is set to `reconnect_required` and has to be reconnected from **Integrations** before it can be used again.

> [!NOTE]
> Media is shared by all targets in a post. Only the text can be overridden per account (`targets[].content`). To send different media to different platforms, create separate posts.

## Connecting accounts

Every platform except Bluesky connects through OAuth from the dashboard: open **[Integrations](https://social-publish-kappa.vercel.app/dashboard/integrations)**, pick the platform, and approve access on the platform's consent screen. To let your own users connect from your app, use a [connect link](/docs/api/create-connect-link). Bluesky connects with an app password, either in the dashboard or with [`POST /v1/accounts/bluesky`](/docs/api/connect-bluesky).

If you run your own deployment, each OAuth platform needs an app registered with that platform and its client ID and secret set in the environment. The redirect URI to register is:

```text
https://social-publish-kappa.vercel.app/api/integrations/<platform>/callback
```

where `<platform>` is the platform ID from the table above (for example `google_business`). To use a different redirect URI for one platform, for example a public HTTPS tunnel for a platform that rejects `localhost`, set `<PLATFORM>_REDIRECT_URI` (for example `TIKTOK_REDIRECT_URI`). You can also connect accounts through your own platform apps; see [OAuth Apps (BYOK)](/docs/oauth-apps).

| Platform | Environment variables |
| --- | --- |
| X (Twitter) | `TWITTER_CLIENT_ID`, `TWITTER_CLIENT_SECRET` |
| Instagram (Instagram Login) | `INSTAGRAM_APP_ID`, `INSTAGRAM_APP_SECRET` |
| Instagram (Facebook Login) | `FACEBOOK_APP_ID`, `FACEBOOK_APP_SECRET` |
| Facebook | `FACEBOOK_APP_ID`, `FACEBOOK_APP_SECRET` |
| LinkedIn | `LINKEDIN_CLIENT_ID`, `LINKEDIN_CLIENT_SECRET` |
| TikTok | `TIKTOK_CLIENT_KEY`, `TIKTOK_CLIENT_SECRET` |
| YouTube | `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET` |
| Threads | `THREADS_APP_ID`, `THREADS_APP_SECRET` |
| Pinterest | `PINTEREST_APP_ID`, `PINTEREST_APP_SECRET` |
| Google Business Profile | `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET` (same Google client as YouTube) |

`META_GRAPH_VERSION` optionally pins the Graph API version used for Facebook, Instagram and Instagram via Facebook Login.

## Finding account IDs

`targets[].accountId` is the Relaycast account ID, not the platform's user ID. List your connected accounts with [`GET /v1/accounts`](/docs/api/list-accounts):

```bash
curl https://social-publish-api.onrender.com/v1/accounts -H "x-access-key: $RELAYCAST_API_KEY"
```

## Platform options

Each platform page has an **Options** section with a table generated from the same definitions the API validates against, plus a complete request example. The generic rules for `targets[].options` are in [Platform Options](/docs/platform-options).
