Bluesky Upload API
This section details how to create posts (Text, Image, Video) on Bluesky using the API.
Base URL
https://api.multi-upload-tool.com/api/v1
Authentication
All requests require an API Token in the header:
x-api-key: YOUR_API_TOKEN
Validation & Limits
The following limits are enforced by our API when posting to Bluesky. All values align with Bluesky’s official API documentation .
| Constraint | Limit | Notes |
|---|---|---|
| Post Text | 300 characters | Enforced via UTF-8 character count. Rich text (mentions, links, hashtags) automatically parsed and faceted. |
| Post Text | 3000 UTF-8 bytes | Hard limit on bytes; most ASCII/Latin text stays well under 300 chars. |
| Images per Post | 4 maximum | Post fails if more than 4 images provided. |
| Image File Size | 2 MB each | Enforced at upload. Files exceeding 2 MB are rejected. |
| Image Formats | JPG, PNG, GIF, WebP | All formats supported by Bluesky’s blob endpoint. |
| Image Aspect Ratio | Any (1:1 to 21:9) | Bluesky server handles rendering; API does not enforce aspect ratio. |
| Video File Size | 100 MB maximum | Enforced at upload. Larger files are rejected. |
| Video Formats | MP4, MOV, WebM | Common formats supported by Bluesky. |
| Video Duration | Up to 3 minutes | Recommended by Bluesky (not enforced by us—check Bluesky docs for protocol limits). |
| Video Alt Text | 1000 graphemes maximum | Enforced when video is posted with alt text. |
| Content Labels | sexual, nudity, porn, graphic-media, !no-unauthenticated | Self-label values. These flags help users filter content. |
| Languages | ISO 639-1 codes (e.g. en, fr) | Comma-separated list. Used for content discovery; not validated. |
Text-Only & Media Posts
- Text is optional when posting with an image or video.
- Text is required only for text-only posts (no media).
- Rich text parsing: The API automatically detects and facets mentions (
@handle.bsky.social), links (https://...), and hashtags (#tag).
Requirements
Bluesky Text Requirements
- Character Limit: 300 characters.
- Rich Text: Mentions (@handle), links, and hashtags are automatically parsed.
- Text is optional when posting with an image or video. It is only required for text-only posts.
Bluesky Image Requirements
- Max Images: 4 per post.
- Formats: JPG, PNG, GIF, WebP.
- Size: Max 2 MB per image.
- Aspect Ratio: Any aspect ratio supported (Bluesky server handles rendering).
Bluesky Video Requirements
- Formats: MP4, MOV, WebM.
- Duration: Up to 3 minutes (recommended by Bluesky).
- Size: Max 100 MB per video.
- Alt Text: Optional; max 1000 graphemes if provided.
Create Post
Create a new post on Bluesky.
Endpoint
POST /upload
Content-Type
multipart/form-data
Parameters
Common Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
accountId | string/number | Yes | The ID of the connected Bluesky account. |
async | string | No | Default "true". If "false", waits for completion. |
Bluesky Specific Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
description | string | No* | The text content of the post. (*Required for text-only posts, optional when posting with media). |
file / photo | file | No | Image or Video file. Use photo (array) for carousels (max 4). |
bluesky_langs | string | No | Comma-separated language codes (e.g. en,fr) or array. |
bluesky_labels | string | No | Content warnings. Values: sexual, nudity, porn, graphic-media, !no-unauthenticated. |
Examples
1. Text Post
curl -X POST https://api.multi-upload-tool.com/api/v1/upload \
-H "x-api-key: YOUR_KEY" \
-F "accountId=123" \
-F "description=Hello Bluesky! #api" \
-F "bluesky_langs=en"2. Image Post with Content Warning
curl -X POST https://api.multi-upload-tool.com/api/v1/upload \
-H "x-api-key: YOUR_KEY" \
-F "accountId=123" \
-F "file=@image.jpg" \
-F "description=Sensitive content here" \
-F "bluesky_labels=nudity"3. Video Post
curl -X POST https://api.multi-upload-tool.com/api/v1/upload \
-H "x-api-key: YOUR_KEY" \
-F "accountId=123" \
-F "file=@video.mp4" \
-F "description=My video post"Example Response
{
"success": true,
"message": "Upload queued successfully",
"data": {
"uploadId": 789,
"status": "pending",
"jobId": "job_123"
}
}