LateLate API
Platforms

Bluesky API

Post to Bluesky with Late API - text posts, images, and videos


Quick Start

Post to Bluesky in under 60 seconds:

curl -X POST https://getlate.dev/api/v1/posts \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Hello from Late API! 🦋",
    "platforms": [
      {"platform": "bluesky", "accountId": "YOUR_ACCOUNT_ID"}
    ],
    "publishNow": true
  }'
const response = await fetch('https://getlate.dev/api/v1/posts', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    content: 'Hello from Late API! 🦋',
    platforms: [
      { platform: 'bluesky', accountId: 'YOUR_ACCOUNT_ID' }
    ],
    publishNow: true
  })
});

const { post } = await response.json();
console.log('Posted to Bluesky!', post._id);
import requests

response = requests.post(
    'https://getlate.dev/api/v1/posts',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
    json={
        'content': 'Hello from Late API! 🦋',
        'platforms': [
            {'platform': 'bluesky', 'accountId': 'YOUR_ACCOUNT_ID'}
        ],
        'publishNow': True
    }
)

post = response.json()
print(f"Posted to Bluesky! {post['_id']}")

Authentication

Bluesky uses App Passwords instead of OAuth. To connect a Bluesky account:

  1. Go to your Bluesky Settings > App Passwords
  2. Create a new App Password
  3. Use the connect endpoint with your handle and app password
curl -X POST https://getlate.dev/api/v1/connect/bluesky \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "profileId": "YOUR_PROFILE_ID",
    "handle": "yourhandle.bsky.social",
    "appPassword": "xxxx-xxxx-xxxx-xxxx"
  }'
const response = await fetch('https://getlate.dev/api/v1/connect/bluesky', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    profileId: 'YOUR_PROFILE_ID',
    handle: 'yourhandle.bsky.social',
    appPassword: 'xxxx-xxxx-xxxx-xxxx'
  })
});

const account = await response.json();
console.log('Connected:', account._id);
response = requests.post(
    'https://getlate.dev/api/v1/connect/bluesky',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
    json={
        'profileId': 'YOUR_PROFILE_ID',
        'handle': 'yourhandle.bsky.social',
        'appPassword': 'xxxx-xxxx-xxxx-xxxx'
    }
)

account = response.json()
print(f"Connected: {account['_id']}")

Image Requirements

PropertyRequirement
Max Images4 per post
FormatsJPEG, PNG, WebP, GIF
Max File Size1 MB per image
Max Dimensions2000 × 2000 px
Recommended1200 × 675 px (16:9)

Aspect Ratios

TypeRatioDimensions
Landscape16:91200 × 675 px
Square1:11000 × 1000 px
Portrait4:5800 × 1000 px

Post with Image

curl -X POST https://getlate.dev/api/v1/posts \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Check out this photo! 📸",
    "mediaItems": [
      {"url": "https://example.com/photo.jpg"}
    ],
    "platforms": [
      {"platform": "bluesky", "accountId": "YOUR_ACCOUNT_ID"}
    ],
    "publishNow": true
  }'
const response = await fetch('https://getlate.dev/api/v1/posts', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    content: 'Check out this photo! 📸',
    mediaItems: [
      { url: 'https://example.com/photo.jpg' }
    ],
    platforms: [
      { platform: 'bluesky', accountId: 'YOUR_ACCOUNT_ID' }
    ],
    publishNow: true
  })
});
response = requests.post(
    'https://getlate.dev/api/v1/posts',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
    json={
        'content': 'Check out this photo! 📸',
        'mediaItems': [
            {'url': 'https://example.com/photo.jpg'}
        ],
        'platforms': [
            {'platform': 'bluesky', 'accountId': 'YOUR_ACCOUNT_ID'}
        ],
        'publishNow': True
    }
)

Video Requirements

PropertyRequirement
Max Videos1 per post
FormatsMP4
Max File Size50 MB
Max Duration60 seconds
Max Dimensions1920 × 1080 px
Frame Rate30 fps recommended
PropertyRecommended
Resolution1280 × 720 px (720p)
Aspect Ratio16:9 (landscape) or 1:1 (square)
Frame Rate30 fps
CodecH.264
AudioAAC

Character Limits

  • Post text: 300 characters
  • Alt text for images: 1000 characters

Bluesky automatically detects and renders:

  • URLs as link cards
  • Mentions (@handle.bsky.social)
  • Hashtags

When your post contains a URL, Bluesky automatically generates a link card preview. For best results:

  • Place the URL at the end of your post
  • Ensure the target page has proper Open Graph meta tags
  • The link card includes title, description, and thumbnail

Common Issues

Image Too Large

Bluesky has a strict 1 MB limit per image. Compress images before upload or Late will attempt automatic compression.

App Password Invalid

  • Ensure you're using an App Password, not your main account password
  • App Passwords are formatted as xxxx-xxxx-xxxx-xxxx
  • Create a new App Password if the current one isn't working

Post Too Long

Bluesky has a 300 character limit. If your post exceeds this, consider:

  • Shortening URLs (Bluesky shows link cards anyway)
  • Splitting into multiple posts
  • Moving detailed content to a linked page