Publishing
Social Accounts
Connect social accounts, find their IDs, and handle accounts that need reconnecting.
A social account is one connected profile, page or channel. Every post targets accounts by their Relaycast id.
Supported platforms
| Platform | platform value | How to connect |
|---|---|---|
| X (Twitter) | twitter | Dashboard (OAuth) |
instagram | Dashboard (OAuth) | |
facebook | Dashboard (OAuth) | |
linkedin | Dashboard (OAuth) | |
| TikTok | tiktok | Dashboard (OAuth) |
| YouTube | youtube | Dashboard (OAuth) |
| Threads | threads | Dashboard (OAuth) |
pinterest | Dashboard (OAuth) | |
| Google Business Profile | google_business | Dashboard (OAuth) |
| Bluesky | bluesky | Dashboard or API (app password) |
Each platform has its own requirements and limits. See the platform guides.
Connect in the dashboard
- Open Integrations at https://social-publish-kappa.vercel.app/dashboard/integrations.
- Click New integration and choose a platform.
- Optionally pick a social group and, if you've added one, your own OAuth app.
- Approve access on the platform's consent screen. You return to the dashboard with the account connected.
Only project owners and admins can connect or disconnect accounts.
Let your users connect with a link
OAuth needs the account owner to approve access in a browser, so the API can't connect an OAuth account on its own. Instead, create a connect link with POST /v1/accounts/connect-links and send your user to it. They approve access on the platform's consent screen, without a Relaycast account, and come back to your redirectUrl with the new account's id:
curl -X POST https://social-publish-api.onrender.com/v1/accounts/connect-links -H "x-access-key: $RELAYCAST_API_KEY" -H "content-type: application/json" -d '{ "platform": "youtube", "redirectUrl": "https://app.example.com/integrations/done" }'Each link works once and expires (60 minutes by default).
Connect Bluesky with the API
Bluesky uses app passwords instead of OAuth, so you can connect it with a request. Create an app password in Bluesky's settings, then send your handle and the app password:
curl -X POST https://social-publish-api.onrender.com/v1/accounts/bluesky \
-H "x-access-key: $RELAYCAST_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "identifier": "yourname.bsky.social", "appPassword": "xxxx-xxxx-xxxx-xxxx" }'const res = await fetch("https://social-publish-api.onrender.com/v1/accounts/bluesky", {
method: "POST",
headers: { "x-access-key": process.env.RELAYCAST_API_KEY!, "Content-Type": "application/json" },
body: JSON.stringify({ identifier: "yourname.bsky.social", appPassword: process.env.BLUESKY_APP_PASSWORD }),
});
const { data: account } = await res.json();res = requests.post(
"https://social-publish-api.onrender.com/v1/accounts/bluesky",
headers={"x-access-key": os.environ["RELAYCAST_API_KEY"]},
json={"identifier": "yourname.bsky.social", "appPassword": os.environ["BLUESKY_APP_PASSWORD"]},
)
account = res.json()["data"]A successful call returns 201 with the account. If Bluesky rejects the credentials you get 400 invalid_credentials. Connecting an account that's already connected updates its credentials and keeps the same id. See Connect Bluesky.
List accounts
GET /v1/accounts returns every account in the project that isn't disconnected:
curl https://social-publish-api.onrender.com/v1/accounts -H "x-access-key: $RELAYCAST_API_KEY"{
"data": [
{
"id": "8f1c2a4e-5b6d-4e7f-9a0b-1c2d3e4f5a6b",
"platform": "instagram",
"handle": "acme.studio",
"displayName": "Acme Studio",
"avatarUrl": "https://...",
"status": "active",
"groupId": "c3d4e5f6-0000-4000-8000-000000000001",
"oauthAppId": null,
"createdAt": "2026-09-30T10:12:00.000Z"
}
]
}| Field | Description |
|---|---|
id | Use this as targets[].accountId. |
platform | One of the values in the table above. |
handle, displayName, avatarUrl | Profile details from the platform at connect time. |
status | active or reconnect_required. |
groupId | The social group, or null for Default. |
oauthAppId | Your own OAuth app used to connect it, or null for the Relaycast app. |
There's no pagination: all accounts are returned in one response. See List accounts.
Reconnecting accounts
If a platform revokes access (the user changed their password, removed the app, or a token can't be refreshed), the failing target gets errorCode: "auth_revoked" and the account's status changes to reconnect_required. The dashboard marks it Reconnect needed.
Posts that target an inactive account are rejected up front:
{
"error": {
"code": "account_inactive",
"message": "Some accounts need reconnecting",
"details": { "accountIds": ["8f1c2a4e-5b6d-4e7f-9a0b-1c2d3e4f5a6b"] }
}
}Reconnect by connecting the same profile again from Integrations. Reconnecting the same platform account keeps its id, so you don't need to update stored IDs.
Disconnecting
Disconnecting an account in the dashboard removes its stored credentials and hides it from GET /v1/accounts. Past posts that used it stay in your history. There's no API endpoint to disconnect an account.
This page is also available as Markdown.