Skip to content
Rutba Relay
Get started

Social publishing API · team console · agent tools

Publish once. Every platform answers for itself.

Rutba Relay takes one post and a list of destinations, fits the post to each platform’s rules, publishes to all of them in the background, and reports every delivery on its own. Build it into your product with one API, run your team’s calendar in the console, or hand the same tools to an AI agent.

One Rutba account. Connect each platform once; after that, publishing is a single request.

POST/v1/posts202 Accepted

One post · 6 destinations · one delivery each

  • Bluesky

    text trimmed to 300 characters

    published
  • Mastodon

    4 of 6 images; 2 dropped

    published
  • Telegram

    sent as an album

    published
  • Discord

    rate_limited, then published

    published
  • WordPress

    title and tags as terms

    published
  • Reddit

    content_rejected · not retried

    rejected
partial5 of 6 delivered · 1 refused, not retried

An illustration of one post settling, not a live feed.

A drawing of one post card with an arrow into the relay, which fans out along six curved lines to six platform tiles; four tiles carry a tick, one a circling retry arrow and one a cross.

54

destinations in the live catalogue, each with its status

16

adapters written, one a test sandbox

7

open platforms, adapters written, no platform review

8

written and waiting on a platform’s own review

Per-platform adaptation

Write the post once. Each platform gets the version it will accept.

Platforms disagree about almost everything: how long a post may be, how many pictures it can carry, whether it needs a title, where a link goes. Rutba Relay keeps one neutral post and projects it onto each destination’s rules before anything is queued — so a problem is caught at the request, not ten minutes later on one platform.

  • Text trimmed at a word boundary to each platform’s limit, media it will not take dropped, and every change reported as a warning for that platform.
  • Preview runs the same projection the publisher runs, so what you preview is what each platform receives.
  • Strict validation refuses instead of adapting, for a post that must go out exactly as written or not at all.
  • The fields only one platform has — a subreddit, a title — travel as overrides on the same request.
A drawing of one long post with six pictures branching into three versions: at 300 characters it is trimmed with four pictures, at 500 characters two pictures are dropped, and at 4096 characters it goes out as written.

What it does

The hard parts of publishing, handled once

Each of these is something you would otherwise build for every platform, and then maintain as each platform changes its mind.

01

One delivery per destination

A post fans out into deliveries, each with its own job, retry budget and result. A slow platform never holds up the rest, and six of seven is reported as partial — not as a failure, and not as a success.

02

Retries that cannot double-post

Send an Idempotency-Key and a repeated request returns the original response instead of publishing again. Retry one failed destination on its own; the platforms that already took the post are left alone.

03

Failures that say which kind

Every platform’s errors map onto one vocabulary — rate_limited, auth_expired, content_rejected and the rest. Transient failures are retried with backoff. A refused post is not, because the same bytes fail the same way.

04

Scheduling that knows the clock

Schedule to an exact instant, or to a wall-clock time in a named time zone. Daylight-saving gaps and repeats are resolved one documented way and the response says what was chosen.

05

Signed webhooks

Hear when a post publishes, partly publishes or fails, and when each delivery settles. Every event is signed over its timestamp and body, and every endpoint has a test event, a delivery log and secret rotation.

06

Connections without the OAuth work

Each account is authorised once — in the console, or through a hosted connect link you send to whoever owns it. Tokens are encrypted at rest, and a connection that stops working is flagged once instead of failing every post.

How a post travels

From one request to an answer per platform

Nothing about publishing to many platforms is one outcome. So the API does not pretend it is: the request is accepted in one step, and each destination settles in its own.

A drawing of a request accepted with 202 splitting into three delivery lanes: one succeeds, one waits, retries and succeeds, and one is refused and marked not retried; the lanes meet in an outcome box reading partial.
  1. 1

    Accepted

    The post is checked against every destination and the API answers 202 with one delivery per target — before any platform is called.

  2. 2

    Projected

    Each delivery carries that platform’s version of the post, with a warning for everything that had to change.

  3. 3

    Queued

    Every delivery is its own job, so one platform’s outage or rate limit stays in its own lane.

  4. 4

    Published or retried

    Transient failures back off and try again. A refusal stops at once, with the platform’s reason in the result.

  5. 5

    Reported

    The post settles as published, partial or failed, and your webhook hears about the post and each delivery.

For developers and integrators

One API instead of an SDK per platform

Your product publishes on your customers’ behalf without you owning an adapter for every network, the token refresh logic, or the difference between how each one fails.

  • REST, with one success envelope and one error shape across every endpoint
  • Hosted connect links, so your customers authorise their own accounts
  • Your own platform app credentials, where a platform has approved your app
  • An OpenAPI document and a full reference, on this site

API access, webhooks and your own platform apps depend on the plan; the pricing page shows which plans include them.

A drawing of a browser window with an Authorise button, done once, passing an encrypted token into a locked box, after which four API requests each succeed without the browser.

For social teams and agencies

A calendar the whole team can work in

The Relay console is built on the same public API: a composer that previews every platform, a calendar across time zones, reviews before anything goes out, and analytics on what actually landed.

  • Drafts, submitted for review, then approved, sent back or rejected
  • Templates for the posts you write every week
  • A media library whose uploads are checked before they are stored
  • A delivery history for every destination of every post

Approvals and analytics depend on the plan; the pricing page shows which plans include them.

A drawing of an approval flow: a draft is submitted to review, and review either approves it on to scheduled, rejects it, or sends it back to the draft with a request for changes.

For AI agent builders

Tools an agent can use without being trusted blindly

An MCP server gives any MCP client the relay’s tools under your own API key. Creating a post makes a draft unless publishing is asked for, and read-only mode removes the writing tools from the list altogether.

  • Read platforms, connections, posts, metrics and the delivery log
  • preview_post shows each platform’s version without touching a platform
  • create_post, publish_draft and cancel_post are the only tools that write
  • The API key’s own scopes still decide what is allowed

The MCP server works through an API key, so it needs a plan that includes API access.

A drawing of an agent with a read-only switch calling a panel of MCP tools, from list_platforms to publish_draft, which go through the relay to three platform tiles that each carry a tick.

From your side

One request out. One signed event back.

Publish with a single call, receive a signed event when the post settles, and check the signature in a dozen lines of standard library code.

Publish, scheduled for 9 AM London timecurl
curl -X POST https://api.relay.rutba.io/v1/posts \
  -H "Authorization: Bearer $RELAY_API_KEY" \
  -H "Idempotency-Key: launch-2026-09-15" \
  -H "content-type: application/json" \
  -d '{
    "content": {
      "text": "Version 4 is out. Here is what changed.",
      "link": "https://example.com/changelog/4",
      "media": [{ "id": "med_…", "alt": "The new dashboard" }]
    },
    "platforms": ["bluesky", "mastodon", "telegram"],
    "scheduled_at": "2026-09-16T09:00",
    "timezone": "Europe/London"
  }'
The event when it settleswebhook
POST /hooks/relay HTTP/1.1
x-relay-event: post.partial
x-relay-delivery: whd_…
x-relay-signature: t=1757926804,v1=5f0c…

{
  "id": "evt_…",
  "type": "post.partial",
  "created_at": "2026-09-16T08:00:04.512Z",
  "data": {
    "post_id": "…",
    "status": "partial",
    "external_id": "launch-42",
    "succeeded": 2,
    "failed": 1,
    "deliveries": [
      { "platform": "bluesky",  "status": "succeeded", "remote_url": "https://…" },
      { "platform": "mastodon", "status": "succeeded", "remote_url": "https://…" },
      { "platform": "telegram", "status": "failed", "error_code": "rate_limited" }
    ]
  }
}
Check it came from the relaynode
import { createHmac, timingSafeEqual } from 'node:crypto';

// rawBody: the request body exactly as received, before any JSON parsing.
export function isFromRelay(rawBody, header, secret, toleranceSeconds = 300) {
  const parts = Object.fromEntries(
    header.split(',').map((pair) => pair.trim().split('=')),
  );
  const t = Number(parts.t);
  if (!Number.isFinite(t)) return false;
  if (Math.abs(Date.now() / 1000 - t) > toleranceSeconds) return false;

  const expected = createHmac('sha256', secret)
    .update(`${t}.${rawBody}`)
    .digest();
  const given = Buffer.from(parts.v1 ?? '', 'hex');
  return given.length === expected.length && timingSafeEqual(given, expected);
}

The signature covers the timestamp and the exact body, so a captured request cannot be replayed later, and a body re-serialised by your framework will not match — verify the raw bytes.

Security and reliability

Built to be trusted with other people’s accounts

A publishing service holds the keys to somebody’s audience. The controls below are in the product’s code; the security page says how each one works.

Tokens encrypted at rest
Platform credentials are sealed with AES-256-GCM and decrypted in one place, at the moment of publishing.
Keys stored as hashes
An API key is shown once, when it is created. What is stored cannot be turned back into it.
One Rutba sign-in
People sign in with their Rutba account, with two-step verification — there is no separate Relay password to leak.
Organisations kept apart
Every read is scoped to the organisation asking. Another organisation’s post does not exist, as far as the API is concerned.
An audit trail
Every action that touches a credential is recorded, whether a person took it or an API key did.
Kill switches
Publishing can be paused for a platform, an organisation or one connection. Paused deliveries wait; they are not failed.
A drawing of a vault door labelled AES-256-GCM for platform tokens at rest, beside a masked API key turned into a sha-256 hash, an audit trail of people and keys, and a row of kill switches.

Platform status

Where each platform stands, today

Read from the live catalogue on every visit, including the platforms that are not ready yet and what each is waiting on. It is an unusual thing for a product page to lead with; it is also the thing that decides whether this is any use to you.

A drawing of the platform catalogue as three rows of neutral tiles: seven marked with a tick, eight marked as waiting, and ten outlined with dashes for the roadmap, plus one dashed tile set apart for testing.
No platform review needed7

Open APIs, adapters written. Once enabled, each publishes as soon as an account is connected.

  • Bluesky
  • Discord
  • Mastodon
  • Telegram
  • WordPress
  • Reddit
  • Slack
See each one →
Waiting on platform review8

Adapters written; each platform reviews the app before it can post for anyone.

  • Facebook Pages
  • Instagram
  • LinkedIn
  • Pinterest
  • Threads
  • TikTok
  • X / Twitter
  • YouTube
See each one →
On the roadmap or out of reach38

No adapter yet, or no way for anyone to publish there. Each is listed with its reason.

See each one →

Questions

What people ask before they connect an account

Which platforms can I publish to today?

The platforms page lists every destination in the live catalogue with its real status. Platforms with open APIs need no review: once one is enabled, it publishes as soon as you connect an account, and the page marks which are connectable now. For the mainstream networks whose adapters are written, each platform’s own app review still stands between the code and a live post, and the page says what each one is waiting on.

Do I need the console, or can I use only the API?

The API covers publishing, scheduling, previews, media, templates, webhooks and the delivery log. A social account still has to be authorised in a browser once — that is the platform’s rule — which you can do in the console or by sending a hosted connect link to whoever owns the account.

What happens when one platform rejects a post?

That delivery stops and the others carry on. Its result says whether the post was refused (the content breaks a rule, so it is not retried) or failed for a transient reason (retried with backoff), and the post settles as partial rather than as one pass or fail.

Can a retry publish the same post twice?

Not if you send an Idempotency-Key: a repeat of the same request returns the original response instead of publishing again. Retrying one delivery replays only that destination, never the ones that already published.

How do scheduled posts handle time zones?

Send an exact instant, or a wall-clock time with an IANA time zone such as Europe/London. Times that fall in a daylight-saving gap, or happen twice when the clocks go back, are resolved one documented way and the response says which time was used.

Can our team review posts before they go out?

Yes. A post can be submitted for review, then approved, sent back to its author with changes requested, or rejected, and every round stays on the post. A post waiting on review cannot be published. Approvals depend on the plan.

Can we use our own platform app credentials?

Yes. An organisation can register its own app for a platform, and OAuth connections to that platform use it from then on — which matters when a platform has approved your app, or when you publish under your own brand.

How do AI agents use it?

Through an MCP server that exposes ten tools over your own API key: reading platforms, connections, posts, metrics and deliveries; previewing a post; and creating, publishing and cancelling posts. Read-only mode removes the three writing tools entirely, and the key’s scopes apply either way.

Where do the prices come from?

From Rutba’s price list, read live by the pricing page. The site holds no prices of its own, so it cannot quote a figure the checkout will not honour — and if the list cannot be reached, the page says so rather than showing an old number.

How do I remove a connected account or our data?

Disconnecting an account removes its stored credentials. The data deletion page explains how to do that, how to revoke access from the platform’s side, and how to close an organisation entirely.

Publish to every platform from one request

Create your Rutba account, connect an account on an open platform, and send your first post.

One family

The rest of Rutba

One account across all of it. Sign in once and the products know each other.

RELAY-HOME · 1f157db