Postpone Logo
Platforms

Bluesky

Schedule posts and threads with media attachments to Bluesky

Mutation

Use the scheduleBlueskyPost mutation to schedule posts to Bluesky:

Mutation
mutation ScheduleBlueskyPost($input: ScheduleBlueskyPostInput!) {
  scheduleBlueskyPost(input: $input) {
    success
    errors {
      field
      message
    }
    post {
      id
      socialAccount {
        id
        username
      }
      publishingStatus
      allowRepliesFrom
      submissions {
        id
        text
        order
        postAt
        contentWarning
        languages
        tags
        gallery {
          id
          galleryMediaSet {
            id
            media {
              id
              url
              mimeType
            }
          }
        }
      }
    }
  }
}

Input Parameters

ScheduleBlueskyPostInput

username
String! required
The username of the connected Bluesky account to post from
postAt
DateTime! required
When to publish the post (must be in the future)
thread
[BlueskyPostSubmissionInputType!]! required
Array of posts that make up the thread (minimum 1 post)
allowRepliesFrom
BlueskyAllowRepliesFromType
Who can reply to the post. Options: EVERYBODY, MENTIONED_USERS, FOLLOWED_USERS, NOBODY
publishingStatus
PublishingStatusType
Publishing status. Options: READY_TO_PUBLISH, DRAFT (default: READY_TO_PUBLISH)
postTags
[ID!]
Array of post tag IDs to organize your content
id
ID
ID of existing post when updating (only for updates)

BlueskyPostSubmissionInputType

Each post in the thread supports these parameters:

text
String! required
The post text content (max 300 characters)
order
Int! required
Position of this post in the thread (0-based)
contentWarning
BlueskyContentWarningType! required
Content warning label. Options: NONE, SUGGESTIVE, NUDITY, PORN
gallery
GalleryInput
Media attachments (images, videos)
languages
[String!]
IETF BCP 47 language codes for the post content
tags
[String!]
Additional hashtags or topic tags for the post
mediaName
String
Name of a file from your Content Library (case-insensitive)
mediaUrl
String
URL of media to upload and attach to the post
repostAtAmount
Int
Number of time units before auto-reposting
repostAtUnit
String
Time unit for auto-repost. Options: hour, day
repostRepeatDays
Int
How many days to repeat the auto-repost (max 365)
repostFromSocialAccount
SocialAccountInputType
Account to repost from (must be connected to your Postpone account)
removeAtAmount
Int
Number of time units before auto-deleting the post
removeAtUnit
String
Time unit for auto-deletion. Options: hour, day
removeMinLikes
Int
Minimum likes required to prevent auto-deletion
final
Boolean
Whether this is the final post in the thread (default: false)
id
ID
ID of existing post when updating (only for updates)

Examples

Simple Post

Schedule a basic post with text only.

{
  "input": {
    "username": "myhandle.bsky.social",
    "postAt": "2025-12-01T15:30:00Z",
    "thread": [
      {
        "text": "Hello Bluesky! This is my first scheduled post 🌤️",
        "order": 0,
        "contentWarning": "NONE"
      }
    ]
  }
}

Post with Media URL

Schedule a post by uploading media from an external URL. The media will be automatically downloaded and added to your Content Library.

{
  "input": {
    "username": "myhandle.bsky.social",
    "postAt": "2025-12-01T15:30:00Z",
    "thread": [
      {
        "text": "Check out this amazing sunset! 🌅",
        "order": 0,
        "contentWarning": "NONE",
        "mediaUrl": "https://picsum.photos/seed/socialmedia/900/1600"
      }
    ]
  }
}

Post with Content Library Media

Schedule a post using media already in your Content Library. The search is case-insensitive and will use the first matching file based on its name.

{
  "input": {
    "username": "myhandle.bsky.social",
    "postAt": "2025-12-01T15:30:00Z",
    "thread": [
      {
        "text": "Sharing our company logo! 🏢",
        "order": 0,
        "contentWarning": "NONE",
        "mediaName": "company-logo.png"
      }
    ]
  }
}

Thread with Multiple Posts

Schedule a multi-post thread with reply restrictions.

{
  "input": {
    "username": "myhandle.bsky.social",
    "postAt": "2025-12-01T15:30:00Z",
    "allowRepliesFrom": "FOLLOWED_USERS",
    "thread": [
      {
        "text": "🧵 Thread about building great APIs (1/3)",
        "order": 0,
        "contentWarning": "NONE"
      },
      {
        "text": "First, always design your API with the developer experience in mind. Clear documentation and consistent patterns make all the difference.",
        "order": 1,
        "contentWarning": "NONE"
      },
      {
        "text": "Second, implement proper error handling and rate limiting. Your API consumers will thank you when things go wrong (and they will).",
        "order": 2,
        "contentWarning": "NONE",
        "final": true
      }
    ]
  }
}

Post with Content Warning

Schedule a post with appropriate content warning labeling.

{
  "input": {
    "username": "myhandle.bsky.social",
    "postAt": "2025-12-01T15:30:00Z",
    "thread": [
      {
        "text": "Artistic photography from my latest shoot 📸",
        "order": 0,
        "contentWarning": "SUGGESTIVE",
        "mediaUrl": "https://picsum.photos/seed/socialmedia/900/1600"
      }
    ]
  }
}

Multi-Language Post

Schedule a post with language tags for better discoverability.

{
  "input": {
    "username": "myhandle.bsky.social",
    "postAt": "2025-12-01T15:30:00Z",
    "thread": [
      {
        "text": "Hello world! / Hola mundo! / Bonjour le monde!",
        "order": 0,
        "contentWarning": "NONE",
        "languages": ["en", "es", "fr"],
        "tags": ["multilingual", "greetings"]
      }
    ]
  }
}

Auto-Repost Configuration

Schedule a post with automatic reposting.

{
  "input": {
    "username": "myhandle.bsky.social",
    "postAt": "2025-12-01T15:30:00Z",
    "thread": [
      {
        "text": "Don't miss our latest blog post about API best practices! 📖",
        "order": 0,
        "contentWarning": "NONE",
        "repostAtAmount": 2,
        "repostAtUnit": "hour",
        "repostRepeatDays": 3,
        "repostFromSocialAccount": {
          "username": "mycompany.bsky.social"
        }
      }
    ]
  }
}

Response Types

Success Response

{
  "data": {
    "scheduleBlueskyPost": {
      "success": true,
      "errors": [],
      "post": {
        "id": "123",
        "socialAccount": {
          "id": "456",
          "username": "myhandle.bsky.social"
        },
        "publishingStatus": "READY_TO_PUBLISH",
        "allowRepliesFrom": "EVERYBODY",
        "submissions": [
          {
            "id": "789",
            "text": "Hello Bluesky! This is my first scheduled post 🌤️",
            "order": 0,
            "postAt": "2025-12-01T15:30:00Z",
            "contentWarning": "NONE",
            "languages": [],
            "tags": [],
            "gallery": null
          }
        ]
      }
    }
  }
}

Error Response

{
  "data": {
    "scheduleBlueskyPost": {
      "success": false,
      "errors": [
        {
          "field": "text",
          "message": "Post text cannot exceed 300 characters."
        }
      ],
      "post": null
    }
  }
}

Updating a Post

To update an existing scheduled post, use the same input type with the corresponding update mutation and include the post id:

Mutation
mutation UpdateScheduledBlueskyPost($input: ScheduleBlueskyPostInput!) {
  updateScheduledBlueskyPost(input: $input) {
    success
    errors {
      field
      message
    }
    post {
      id
    }
  }
}

Pass the id of the post you want to update in the input, along with the fields you want to change:

{
  "input": {
    "id": "12345",
    "username": "myhandle.bsky.social",
    "thread": [{"text": "Updated post text!", "order": 0, "contentWarning": "NONE"}]
  }
}
The update mutation uses the same input type as the create mutation. Include the id field to specify which post to update. Only scheduled posts that have not been published yet can be updated.

Validation Rules

The API enforces Bluesky's content policies and technical limitations:
  • Text Length: Maximum 300 characters per post
  • Media: Supports images and videos with reasonable file size limits
  • Content Warnings: Required field for all posts, use NONE for general audiences
  • Languages: Use standard IETF BCP 47 language codes (e.g., en, es, fr)
  • Threads: No hard limit on thread length
  • Scheduling: Posts must be scheduled for future dates only
  • Account Limits: Respects your plan's monthly post limits

Common Errors