Relaycast gives you one REST endpoint for publishing to X, Instagram, Facebook, LinkedIn, TikTok, YouTube, Threads, Pinterest, Bluesky and Google Business Profile. This guide takes you from an empty project to a post that is live on more than one network, in about ten minutes.
You will:
- Connect social accounts in the dashboard.
- Create an API key.
- Look up the account IDs you want to publish to.
- Send one
POST /v1/postsrequest. - Check the result for each platform.
1. Connect your accounts
Create a free account, then open Integrations in the dashboard and click New integration. Pick a platform and approve access on that platform's own sign-in screen. Relaycast stores the resulting tokens encrypted and refreshes them for you before they expire.
Bluesky is the exception: it does not use OAuth. You connect it with your handle and an app password, either from the dashboard or through the API.
Connect at least two different platforms for this tutorial. Seeing one request produce two independent results is the point of the exercise.
2. Create an API key
Go to API keys and create a key. The full key is only shown once, so copy it somewhere safe. Every request authenticates with the x-access-key header.
In the examples below the key and the API base URL live in environment variables:
export RELAYCAST_API_URL="https://api.your-domain.com"
export RELAYCAST_API_KEY="your-key-here"Never ship the key to a browser or mobile app. Call the API from your server.
3. List your accounts
Each connected account has an ID. You publish to accounts, not to platforms, so this is the ID you will put in targets.
curl "$RELAYCAST_API_URL/v1/accounts" \
-H "x-access-key: $RELAYCAST_API_KEY"const res = await fetch(`${process.env.RELAYCAST_API_URL}/v1/accounts`, {
headers: { "x-access-key": process.env.RELAYCAST_API_KEY! },
});
const { data: accounts } = await res.json();
console.table(accounts.map((a) => ({ id: a.id, platform: a.platform, handle: a.handle, status: a.status })));import os, requests
res = requests.get(
f"{os.environ['RELAYCAST_API_URL']}/v1/accounts",
headers={"x-access-key": os.environ["RELAYCAST_API_KEY"]},
)
for a in res.json()["data"]:
print(a["id"], a["platform"], a["handle"], a["status"])The response is a data array. Each entry has id, platform, handle, displayName, avatarUrl, status and a few more fields. Only accounts with status active can be published to; an account in reconnect_required needs to be reconnected from the dashboard first.
4. Publish
Now the main event. A post has shared content, an optional media array, and one entry in targets per account. Set publishNow: true to publish immediately.
curl -X POST "$RELAYCAST_API_URL/v1/posts" \
-H "x-access-key: $RELAYCAST_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: first-post-001" \
-d '{
"content": "Hello from Relaycast! One request, every network.",
"targets": [
{ "accountId": "BLUESKY_ACCOUNT_ID" },
{ "accountId": "LINKEDIN_ACCOUNT_ID" }
],
"publishNow": true
}'const res = await fetch(`${process.env.RELAYCAST_API_URL}/v1/posts`, {
method: "POST",
headers: {
"x-access-key": process.env.RELAYCAST_API_KEY!,
"Content-Type": "application/json",
"Idempotency-Key": "first-post-001",
},
body: JSON.stringify({
content: "Hello from Relaycast! One request, every network.",
targets: [{ accountId: "BLUESKY_ACCOUNT_ID" }, { accountId: "LINKEDIN_ACCOUNT_ID" }],
publishNow: true,
}),
});
const { data: post } = await res.json();
console.log(post.id, post.status);import os, requests
res = requests.post(
f"{os.environ['RELAYCAST_API_URL']}/v1/posts",
headers={
"x-access-key": os.environ["RELAYCAST_API_KEY"],
"Idempotency-Key": "first-post-001",
},
json={
"content": "Hello from Relaycast! One request, every network.",
"targets": [{"accountId": "BLUESKY_ACCOUNT_ID"}, {"accountId": "LINKEDIN_ACCOUNT_ID"}],
"publishNow": True,
},
)
post = res.json()["data"]
print(post["id"], post["status"])A successful request returns 201 Created with the new post. Behind the scenes, every target becomes its own publish job, so a slow upload to one network never holds up another.
A few things happen before anything is queued:
- Validation per platform. Your content is checked against each target's rules (character limits, media requirements, option values). If any target fails, you get a
400 validation_errorwith the problems grouped by account ID, and nothing is published or charged. - Credits. Each target costs one credit. If you do not have enough, the request returns
402 insufficient_credits. Targets that end up failing are refunded. See pricing for plan details. - Idempotency. The
Idempotency-Keyheader makes retries safe. Sending the same key again returns the original post (with200instead of201) instead of publishing twice.
5. Check the results
Publishing is asynchronous, so fetch the post to see how each target did:
curl "$RELAYCAST_API_URL/v1/posts/POST_ID" \
-H "x-access-key: $RELAYCAST_API_KEY"The post has an overall status (scheduled, publishing, published, partial or failed), and each entry in targets has its own status, externalUrl (a link to the live post), and errorCode / errorMessage if something went wrong. partial means some platforms succeeded and others did not.
You can see the same thing in the dashboard under Posts, including the original request body.
Customise per platform
The same text rarely fits every network. Two tools help:
- Per-target content. Set
contenton a target to replace the shared text for that account only. - Platform options. Set
optionson a target for platform-specific settings, such as a video title and privacy on YouTube or the post type on Instagram. Each platform's keys are listed in the platform guides.
{
"content": "We just shipped dark mode.",
"targets": [
{ "accountId": "BLUESKY_ACCOUNT_ID" },
{
"accountId": "LINKEDIN_ACCOUNT_ID",
"content": "We just shipped dark mode. Here is what we learned building it."
}
],
"publishNow": true
}Prefer clicking first?
The dashboard Playground builds the same request visually. Pick accounts, write your post, attach media and watch live validation for every platform. It shows the equivalent request body, so you can copy it straight into your code once it looks right.
Next steps
- Schedule posts instead of publishing immediately.
- Get told when a post finishes with notifications and webhooks.
- Read the full create post reference.
Ready to build?
Get an access key and publish your first post in minutes.