Introduction
Scheduling Posts via API
The Postpone API provides powerful GraphQL mutations to schedule posts across multiple social media platforms. This comprehensive guide will walk you through the process of scheduling posts programmatically.
Overview
Postpone supports scheduling posts to the following platforms through dedicated GraphQL mutations:
Platform-Specific Mutations
Each platform has its own dedicated GraphQL mutation for scheduling posts. Here's a quick reference:
| Platform | Mutation Name | Description |
|---|---|---|
scheduleRedditPost | Schedule posts to multiple subreddits | |
| X/Twitter | scheduleTweet | Schedule tweets and threads |
scheduleInstagramPost | Schedule feed posts, Reels, and Stories posts | |
scheduleFacebookPost | Schedule posts to Pages | |
| Threads | scheduleThreadsPost | Schedule posts to Threads |
| Bluesky | scheduleBlueskyPost | Schedule posts to Bluesky |
| TikTok | scheduleTikTokPost | Schedule video content |
| YouTube Shorts | scheduleYouTubePost | Schedule short-form videos |
scheduleLinkedInPost | Schedule professional posts | |
schedulePinterestPost | Schedule pins to boards | |
| Mastodon | scheduleMastodonPost | Schedule posts to Mastodon |
| Tumblr | scheduleTumblrPost | Schedule posts to Tumblr |
Common Parameters
While each platform has specific requirements, most scheduling mutations share common parameters:
schedulingMode: QUEUE_NEXT.SPECIFIC_TIME, QUEUE_NEXT (default: SPECIFIC_TIME).
Only accepted when scheduling a new post. See Scheduling at the Next Open Slot.media isn't enough.READY_TO_PUBLISH, DRAFT (default: READY_TO_PUBLISH).Scheduling at the Next Open Slot
Instead of working out a time yourself, you can hand that job to Postpone: pass schedulingMode: QUEUE_NEXT, leave postAt out, and the post lands on the next open slot in the account's Account Schedule.
{
"input": {
"username": "myhandle",
"schedulingMode": "QUEUE_NEXT"
}
}
The rest of the input stays exactly as it was — only the date changes hands. Each platform page has a worked example.
A slot counts as taken when a scheduled post falls on it, or within about 30 minutes of it. Queue several posts in a row and they walk down the schedule one open slot at a time rather than piling onto the same time. The queue never fills up either: an account booked solid for months gets the first slot past the end of its queue.
This is the single-request version of querying Next Scheduled Dates and passing the result back as postAt. Prefer it over that two-step approach when you are only placing a post — because the slot is picked and taken in one transaction, two posts queued at the same moment can never be handed the same slot.
Rules
- A schedule is required. The account has to have an Account Schedule set up. Without one the mutation fails with
<username> has no schedule set up. postAtandQUEUE_NEXTare mutually exclusive. Pass one or the other, never both. Sending both fails withPass either a post date or QUEUE_NEXT, not both.- New posts only. Update mutations reject
schedulingModeoutright —QUEUE_NEXTandSPECIFIC_TIMEalike — withschedulingMode is not supported when updating a post.An already-scheduled post occupies a slot, so queueing it again would read that slot as taken and walk the post forward. To move a scheduled post, pass apostAt. - Not for drafts. A draft doesn't hold a slot, so queueing one would hand the same slot to every other queued post. Save the draft without a date (or with a
postAt), then set a date when you promote it topublishingStatus: READY_TO_PUBLISH. - Reddit is not supported.
scheduleRedditPosthas noschedulingModeparameter — Account Schedules don't apply to Reddit. Pass apostAton each submission.
postAt lives inside submissions (Instagram, Facebook, TikTok, YouTube Shorts, LinkedIn, Pinterest, and Tumblr), schedulingMode sits at the top level of the input instead, because it decides one date for the whole post. Every submission of a post shares that date.Drafts without a date
A draft is somewhere to put a post before you've decided when it goes out, so postAt is optional on one:
{
"input": {
"username": "myhandle",
"text": "still thinking about this one",
"publishingStatus": "DRAFT"
}
}
A date is still stored against the post, but it's a placeholder parked about 30 days out, not a time you chose.
Rules
- Drafts only. A post going out as
READY_TO_PUBLISHstill has to say when. LeavingpostAtoff one fails withProvide a post date, or use QUEUE_NEXT. - Promotion needs a date. Promoting a draft to
publishingStatus: READY_TO_PUBLISHwithout apostAtfails withProvide a post date.schedulingModeisn't accepted on an update either, so the date has to be spelled out. - Editing doesn't need one. Updating a draft that stays a draft can leave
postAtout; the draft stays parked. Pass apostAtto give it a real date at any point. - A lapsed date gets re-parked. If a draft's stored date has passed by the time you edit it, a dateless edit pushes the placeholder back out. A date still in the future is never moved by an edit, whether you chose it or we parked it there.
- Reddit is not supported.
scheduleRedditPostrequires apostAton each submission, drafts included.
postAt lives inside submissions, just leave it off the submission entries. publishingStatus sits at the top level of the input either way.Attaching Media
Scheduling mutations take a media parameter: a list of the images, videos, or GIFs to attach to the post. Each item points at a single file, in one of three ways:
Every item must set exactly one of id, name, or url, and no file can be attached to the same post twice. You can mix the three forms freely within one list:
{
"media": [
{ "id": "1001" },
{ "name": "company-logo.png" },
{ "url": "https://example.com/images/hero.jpg" }
]
}
If a file can't be resolved, the whole mutation fails with an error rather than scheduling the post without it. The number of items you can attach depends on the platform, so check the platform-specific docs.
See Uploading Media for how to get files into your Content Library and pick up their id.
media is only supported when scheduling a new post. Update mutations reject it.Deprecated Media Parameters
mediaUrl, mediaUrls, and mediaName are deprecated in favor of media. They still work, but new integrations should use media, and existing ones should migrate:
| Deprecated | Use instead |
|---|---|
"mediaName": "logo.png" | "media": [{ "name": "logo.png" }] |
"mediaUrl": "https://example.com/a.jpg" | "media": [{ "url": "https://example.com/a.jpg" }] |
"mediaUrls": ["https://example.com/a.jpg", "https://example.com/b.jpg"] | "media": [{ "url": "https://example.com/a.jpg" }, { "url": "https://example.com/b.jpg" }] |
Response Format
All scheduling mutations return a consistent response structure:
{
success: Boolean!
errors: [ValidationError]
}
Common Errors
These errors are commonly encountered across multiple platforms when scheduling posts:
The specified username is not connected to your Postpone account. Connect the social media account in your settings first.
The postAt timestamp must be in the future. Check your timezone settings and ensure the date is correct.
A new post going out has to say when: pass a postAt, or pass schedulingMode: QUEUE_NEXT to take the next slot on the account's schedule. Drafts are exempt — see Drafts without a date.
schedulingMode isn't accepted on updates, so a postAt is the only way to say when the post goes out. You'll also see it when promoting a parked draft to publishingStatus: READY_TO_PUBLISH without giving it a date.
postAt and schedulingMode: QUEUE_NEXT are mutually exclusive. Drop the postAt to queue the post, or drop the schedulingMode to keep your own time.
schedulingMode: QUEUE_NEXT needs an Account Schedule on the account you're posting to. Set one up, or pass an explicit postAt.
schedulingMode is only accepted when scheduling a new post. To move a post that is already scheduled, pass a postAt instead.
Drafts don't hold a slot in the queue. Save the draft without a date, then pass a postAt when you update it to publishingStatus: READY_TO_PUBLISH.
Your post content exceeds the platform's character limit. Each platform has different limits - check the platform-specific documentation for details.
You've reached your plan's posting limit for the scheduled month. Upgrade your plan or schedule for a different month.
The media file exceeds the platform's size limits. Each platform has different file size restrictions - optimize your media or check platform limits.
The media format is not supported by the target platform. Check the platform's supported file types and convert if necessary.
Some platforms don't allow combining certain content types (e.g., polls with media, text with links). Choose one content type per post.
Best Practices
When using the scheduling API, keep these best practices in mind:
Each platform has its own rate limits. Space out your API calls appropriately to avoid hitting these limits.
Ensure your postAt timestamps are in the future and properly formatted in ISO 8601 format (e.g., 2025-09-16T14:30:00.000Z). If you're only picking a time to spread posts out, let Postpone pick it for you with schedulingMode: QUEUE_NEXT.
Always check the response for errors and validation issues. Implement proper error handling in your application.
Use the API playground to test your mutations before implementing them in your application.
Getting Started
To begin scheduling posts via the API:
Connect Your Accounts
Ensure you have connected the social media accounts you want to post to in your Postpone dashboard.
Obtain API Credentials
Get your API key from Postpone settings to authenticate your requests.
Choose Your Platform
Select the platform you want to schedule posts for and refer to the platform-specific documentation.
Test Your Integration
Use the API playground to test your mutations before implementing them in production.
Next Steps
Ready to start scheduling posts? Choose a platform from the list above to see detailed examples and platform-specific requirements.