Accounts
Connect Bluesky
Connect or reconnect a Bluesky account with its handle and an app password.
POST https://social-publish-api.onrender.com/v1/accounts/blueskySigns in to Bluesky with the handle and app password, and saves the account to your project. Bluesky is the only platform you can connect with a single API call; OAuth platforms connect from Integrations in the dashboard, or through a connect link your user opens.
Create an app password in the Bluesky app under Settings → Privacy and security → App passwords. Don't use your main Bluesky password.
Calling this again for the same Bluesky account (same DID) updates its credentials in place and sets it back to active; the account id stays the same. Use this to fix an account in reconnect_required.
Headers
| Header | Required | Description |
|---|---|---|
x-access-key | Yes* | Your API key. *Or send Authorization: Bearer <key>. |
content-type | Yes | application/json |
Body
| Field | Type | Required | Description |
|---|---|---|---|
identifier | string | Yes | Bluesky handle (for example acme.bsky.social) or account email. At least 3 characters. |
appPassword | string | Yes | Bluesky app password. At least 8 characters. |
Request
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": "acme.bsky.social", "appPassword": "abcd-efgh-ijkl-mnop" }'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: "acme.bsky.social",
appPassword: process.env.BLUESKY_APP_PASSWORD!,
}),
});
if (!res.ok) throw new Error((await res.json()).error.message);
const { data: account } = await res.json();import os, requests
res = requests.post(
"https://social-publish-api.onrender.com/v1/accounts/bluesky",
headers={"x-access-key": os.environ["RELAYCAST_API_KEY"]},
json={"identifier": "acme.bsky.social", "appPassword": os.environ["BLUESKY_APP_PASSWORD"]},
)
res.raise_for_status()
account = res.json()["data"]Response
Returns the connected account, with the same fields as List accounts.
{
"data": {
"id": "7c6b5a49-3827-4e1d-8c0b-9a8f7e6d5c4b",
"platform": "bluesky",
"handle": "acme.bsky.social",
"displayName": null,
"avatarUrl": null,
"status": "active",
"groupId": null,
"oauthAppId": null,
"createdAt": "2026-10-05T09:14:03.218Z"
}
}The status is 201 for reconnects too.
Errors
| Status | Code | When |
|---|---|---|
| 400 | invalid_json | The body isn't valid JSON. |
| 400 | validation_error | identifier or appPassword is missing or too short. details lists the issues. |
| 400 | invalid_credentials | Bluesky rejected the handle or app password. |
| 401 | unauthorized | Missing or invalid API key. |
| 429 | rate_limited | Rate limit exceeded for this key. |
{
"error": {
"code": "invalid_credentials",
"message": "Bluesky rejected these credentials"
}
}Accounts are signed in through bsky.social. See the Bluesky guide for what you can post.
This page is also available as Markdown.