To create a post through the Bluesky API you write a record of type app.bsky.feed.post into your repository with com.atproto.repo.createRecord, after signing in with com.atproto.server.createSession using an app password. The record carries the text, a creation time and, for anything clickable, facets: marks with byte offsets. This page lists the fields and the rules that make a post come out right, in plain words and without code, and says what a scheduler adds.
The steps
- Sign in. Create an app password in *Settings, Privacy and Security, App Passwords*, then call
createSessionwith your handle and that password. A custom domain handle works the same as a.bsky.socialone. The app password can be revoked on its own and cannot change your account password. - Upload pictures first. Each picture is sent with
uploadBloband returns a reference that the post then embeds. - Create the record with
createRecord, the collectionapp.bsky.feed.postand the fields below.
The fields of a post
| Field | What it holds |
|---|---|
| text | Up to 300 graphemes and 3,000 bytes |
| createdAt | The creation time of the record |
| facets | Links, mentions and hashtags, marked by byte offsets |
| embed | Up to 4 pictures with alt text, or one video, not both |
| reply | For a reply or a thread part: the root and the parent post |
| langs | Optional language tags |
The two rules that surprise people
- Graphemes, not bytes, for the limit. The 300 limit counts what you see as characters, so a flag emoji is one. The 3,000-byte limit applies as well.
- Facets are not automatic. The protocol does not detect links, mentions or hashtags. The tool must mark them with byte offsets, and a text that is posted without facets shows plain text that nobody can tap. The offsets are in bytes of the encoded text, so a non-ASCII character moves them.
A video is one per post, MP4, up to 100 MB and 3 minutes. Editing is not possible, so a post is deleted and made again. The figures are on the Bluesky limits page.
What a scheduler adds
The official app has no scheduler, and the API has no publish-time field, so a scheduler holds the post and runs these calls at the minute you chose. Preflight connects with an app password, marks links, mentions and hashtags, counts the 300 graphemes and keeps threads in order. See scheduling Bluesky posts, scheduling to Bluesky and the Bluesky integration, or send a post with the Preflight API and let it deal with the facets.
Based on the AT Protocol as described on the Bluesky pages of this site, checked 2 November 2026.
Questions people ask
- How do I create a post with the Bluesky API?
- Sign in with createSession using an app password, then call createRecord with the collection app.bsky.feed.post and a record that has the text, createdAt and, for links, mentions and hashtags, facets.
- Why are my Bluesky API links not clickable?
- The protocol does not detect links. You have to add facets that mark the link with byte offsets, otherwise the link shows as plain text.
- How long can a Bluesky post be through the API?
- 300 graphemes and 3,000 bytes. A flag emoji counts as one grapheme.
- How many pictures can a Bluesky post have?
- Four, each with alt text. A video is one per post and cannot be combined with pictures.