Skip to main content

Bluesky

Using hosted SimplePost? See connection requirements. The credential setup below is for your own SDK, local CLI, or self-hosted integration.

Bluesky supports two credential paths in SimplePost:

  • App password — the simplest for personal or server-owned posting.
  • OAuth tokens — better for user-facing apps and Scheduler-connected accounts.

Content support

Current hosted app and core source

CapabilitySimplePost support
Text / caption (characters)300 text
Media4 items max; 4 images max; 1 video max; No mixed images/video
Image size2 MB maximum
Video size300 MB maximum
Video duration600 seconds maximum
  • Up to 4 images or 1 MP4 video (300 MB, 10 minutes). Video uploads require a verified Bluesky email and available account quota.

These validation limits also match published SDK 1.3.1.

Provider permissions and quotas still apply. SimplePost storage can impose a lower upload limit. MB/GB use decimal bytes; MiB/GiB use binary bytes.

Video uploads require a verified Bluesky email and available account quota. Use MP4 (.mp4 or .m4v); SimplePost does not transcode MOV or WebM. OAuth and app-password connections both support video. Processing must finish before a post is created.

App password setup

  1. Open Bluesky settings.
  2. Create an app password.
  3. Store the app password with the Bluesky handle or DID.

This is the fastest setup for SDK, CLI, and the self-hosted REST server.

OAuth setup

Bluesky OAuth is decentralized and uses a public client metadata document instead of a traditional developer dashboard. For a local CLI OAuth account, host your own metadata document, set its URL as SIMPLE_POST_BLUESKY_CLIENT_ID, then run simplepost account add bluesky. See Bluesky OAuth app setup. For personal local posting, an app password is simpler.

OAuth refresh is DPoP-bound and tokens rotate — see token rotation.

Environment variables

BLUESKY_ACCESS_TOKEN=
BLUESKY_REFRESH_TOKEN=
BLUESKY_DID=
BLUESKY_PDS_URL=

Env-only setup activates when BLUESKY_ACCESS_TOKEN, BLUESKY_DID, and BLUESKY_PDS_URL are all set. BLUESKY_REFRESH_TOKEN is optional for short-lived posting.

For app-password posting, pass credentials directly through SDK options instead:

await post({
content: { text: "Hello Bluesky" },
platforms: ["bluesky"],
options: {
bluesky: {
credentials: {
identifier: "yourbrand.bsky.social",
appPassword: "xxxx-xxxx-xxxx-xxxx",
},
},
},
});

For OAuth tokens, DPoP keys are required. Scheduler stores DPoP keys automatically. If you use the SDK directly, pass the DPoP public and private JWKs in options.bluesky.credentials.

REST server account

Add one of these entries under accounts in the self-hosted REST server's accounts.json.

App password:

{
"id": "bsky-main",
"platform": "bluesky",
"credentials": {
"identifier": "yourbrand.bsky.social",
"appPassword": "xxxx-xxxx-xxxx-xxxx"
}
}

OAuth:

{
"id": "bsky-main",
"platform": "bluesky",
"username": "yourbrand.bsky.social",
"platformAccountId": "did:plc:...",
"credentials": {
"accessToken": "...",
"refreshToken": "...",
"did": "did:plc:...",
"pdsUrl": "https://bsky.social"
}
}