Posts API
Create, schedule, and manage posts across all 10 supported platforms. The Posts API handles single posts, bulk creation, content validation, and retry logic for failed deliveries.
/api/v1/postsCreate or schedule a post/api/v1/posts/bulkCreate multiple posts at once/api/v1/postsList all posts/api/v1/posts/:idGet post details/api/v1/posts/:idUpdate a scheduled or draft post/api/v1/posts/:idCancel or delete a post/api/v1/posts/:id/retryRetry a failed post/api/v1/posts/validateValidate content against platform limitsCreate a post
/api/v1/postsCreate or schedule a postHeaders
| Name | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | Bearer token. Example: Bearer sk_live_abc123... |
Content-Type | string | Required | Must be application/json |
Idempotency-Key | string | Optional | Unique key to prevent duplicate posts. Recommended for all create operations. |
AuthorizationstringRequiredBearer token. Example: Bearer sk_live_abc123...
Content-TypestringRequiredMust be application/json
Idempotency-KeystringOptionalUnique key to prevent duplicate posts. Recommended for all create operations.
Request body
| Name | Type | Required | Description |
|---|---|---|---|
content | string | Optional | Post text content. Character limits vary by platform. Optional for media-only posts. |
platforms | array | Required | Array of platform targets. Each object must include platform and accountId. Optionally include a content field to override the top-level content for that platform. |
mediaItems | array | Optional | Array of media attachments. Each object has type ("image" or "video") and url (publicly accessible URL). |
status | string | Optional | Post status.Default: scheduleddraftscheduledimmediate |
scheduledFor | string | Optional | ISO 8601 date for scheduling. Must be at least 5 minutes in the future and no more than 90 days ahead. |
timezone | string | Optional | IANA timezone string (e.g. "America/New_York"). Used to interpret scheduledFor. |
platformSettings | object | Optional | Platform-specific settings. Keys are platform names, values are setting objects (e.g. instagram.shareToFeed, twitter.replySettings). |
publishNow | boolean | Optional | Set to true to publish immediately, bypassing any schedule.Default: false |
queue | boolean | Optional | Set to true to auto-schedule this post to the next available queue slot. Use instead of scheduledFor.Default: false |
contentstringOptionalPost text content. Character limits vary by platform. Optional for media-only posts.
platformsarrayRequiredArray of platform targets. Each object must include platform and accountId. Optionally include a content field to override the top-level content for that platform.
mediaItemsarrayOptionalArray of media attachments. Each object has type ("image" or "video") and url (publicly accessible URL).
statusstringOptionalPost status.
Default: scheduled
draftscheduledimmediatescheduledForstringOptionalISO 8601 date for scheduling. Must be at least 5 minutes in the future and no more than 90 days ahead.
timezonestringOptionalIANA timezone string (e.g. "America/New_York"). Used to interpret scheduledFor.
platformSettingsobjectOptionalPlatform-specific settings. Keys are platform names, values are setting objects (e.g. instagram.shareToFeed, twitter.replySettings).
publishNowbooleanOptionalSet to true to publish immediately, bypassing any schedule.
Default: false
queuebooleanOptionalSet to true to auto-schedule this post to the next available queue slot. Use instead of scheduledFor.
Default: false
Per-platform content: Each object in the platforms array can include a content field that overrides the top-level content for that specific platform. This lets you tailor messaging per network while creating a single post.
Queue integration: Instead of setting scheduledFor manually, pass "queue": true to automatically schedule the post into the next available queue slot. See the Queues API for details.
TikTok requires a privacy level. When you target tiktok, you must include platformSettings.tiktok.privacy. Valid values are PUBLIC_TO_EVERYONE, MUTUAL_FOLLOW_FRIENDS, FOLLOWER_OF_CREATOR, and SELF_ONLY, and the value must be enabled on the connected account. Posts are rejected at creation rather than published with a guessed privacy level.
# Publish immediatelyschedulala post "Excited to announce our new feature!" --platforms twitter,linkedin,instagram --now# Schedule for laterschedulala post "Excited to announce our new feature!" \--platforms twitter,linkedin,instagram \--schedule "2026-03-15T14:00:00Z"# With mediaschedulala post "Check it out" --platforms instagram \--media "https://example.com/announcement.jpg" --now# Platform-specific contentschedulala post "Default text" --platforms twitter,linkedin \--platform-content '{"linkedin":{"content":"LinkedIn version"}}' --now
{"success": true,"post": {"id": "67abc456def789012345cdef","status": "scheduled","content": "Excited to announce our new feature! Check it out at example.com","scheduledFor": "2026-03-15T14:00:00.000Z","platforms": [{"platform": "twitter","accountId": "67abc123def4567890120001","status": "pending"},{"platform": "linkedin","accountId": "67abc123def4567890120002","status": "pending"},{"platform": "instagram","accountId": "67abc123def4567890120003","status": "pending"}],"createdAt": "2026-03-01T12:00:00.000Z"}}
Bulk create posts
/api/v1/posts/bulkCreate multiple posts at onceCreate up to 25 posts in a single request. Each post in the array follows the same schema as the create post endpoint. The response includes a summary with per-post results so you can identify any failures.
Request body
| Name | Type | Required | Description |
|---|---|---|---|
posts | array | Required | Array of post objects (max 25). Each follows the same schema as POST /api/v1/posts. |
timezone | string | Optional | Default timezone for all posts. Individual posts can override this. |
postsarrayRequiredArray of post objects (max 25). Each follows the same schema as POST /api/v1/posts.
timezonestringOptionalDefault timezone for all posts. Individual posts can override this.
curl -X POST https://schedulala.com/api/v1/posts/bulk \-H "Authorization: Bearer sk_live_abc123..." \-H "Content-Type: application/json" \-H "Idempotency-Key: bulk_$(uuidgen)" \-d '{"timezone": "America/New_York","posts": [{"content": "Monday motivation! Start the week strong.","platforms": [{ "platform": "twitter", "accountId": "67abc123def4567890120001" }],"scheduledFor": "2026-03-16T09:00:00Z"},{"content": "Wednesday tip: consistency beats perfection.","platforms": [{ "platform": "twitter", "accountId": "67abc123def4567890120001" }],"scheduledFor": "2026-03-18T09:00:00Z"}]}'
{"success": true,"results": [{"index": 0,"success": true,"post": {"id": "67abc456def789012345cd01","status": "scheduled","content": "Monday motivation! Start the week strong.","scheduledFor": "2026-03-16T09:00:00.000Z","platforms": [{"platform": "twitter","accountId": "67abc123def4567890120001","status": "pending"}],"createdAt": "2026-03-01T12:00:00.000Z"}},{"index": 1,"success": true,"post": {"id": "67abc456def789012345cd02","status": "scheduled","content": "Wednesday tip: consistency beats perfection.","scheduledFor": "2026-03-18T09:00:00.000Z","platforms": [{"platform": "twitter","accountId": "67abc123def4567890120001","status": "pending"}],"createdAt": "2026-03-01T12:00:00.000Z"}}],"summary": {"total": 2,"succeeded": 2,"failed": 0}}
List posts
/api/v1/postsList all postsRetrieve a paginated list of your posts. Supports filtering by status, platform, profile, and date range. Results are returned in reverse chronological order.
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
status | string | Optional | Filter by post status.draftscheduledimmediatepostedpartially_failedfailedcancelled |
brandId | string | Optional | Filter by brand ID. |
platform | string | Optional | Filter by platform name.twitterinstagramfacebooklinkedintiktokthreadsblueskyyoutubepinteresttelegram |
limit | number | Optional | Number of posts to return.Default: 20 |
page | number | Optional | Page number for offset-based pagination.Default: 1 |
after | string | Optional | Return posts scheduled after this ISO 8601 date. |
before | string | Optional | Return posts scheduled before this ISO 8601 date. |
statusstringOptionalFilter by post status.
draftscheduledimmediatepostedpartially_failedfailedcancelledbrandIdstringOptionalFilter by brand ID.
platformstringOptionalFilter by platform name.
twitterinstagramfacebooklinkedintiktokthreadsblueskyyoutubepinteresttelegramlimitnumberOptionalNumber of posts to return.
Default: 20
pagenumberOptionalPage number for offset-based pagination.
Default: 1
afterstringOptionalReturn posts scheduled after this ISO 8601 date.
beforestringOptionalReturn posts scheduled before this ISO 8601 date.
# List all postsschedulala post:list# Filter by statusschedulala post:list --status scheduled --limit 10
{"success": true,"posts": [{"id": "67abc456def789012345cdef","status": "scheduled","content": "Excited to announce our new feature!","scheduledFor": "2026-03-15T14:00:00.000Z","platforms": [{"platform": "twitter","accountId": "67abc123def4567890120001","status": "pending"}],"createdAt": "2026-03-01T12:00:00.000Z"}],"pagination": {"total": 45,"page": 1,"limit": 10,"pages": 5,"hasMore": true}}
Get post details
/api/v1/posts/:idGet post detailsRetrieve full details for a single post, including per-platform delivery status. After a post is published, each platform entry includes the native postId, postUrl, and postedAt timestamp.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Required | The post ID (e.g. 67abc456def789012345cdef). |
idstringRequiredThe post ID (e.g. 67abc456def789012345cdef).
schedulala post:status 67abc456def789012345cdef# Watch until published or failedschedulala post:status 67abc456def789012345cdef --watch
{"success": true,"post": {"id": "67abc456def789012345cdef","status": "posted","content": "Excited to announce our new feature! Check it out at example.com","scheduledFor": "2026-03-15T14:00:00.000Z","platforms": [{"platform": "twitter","accountId": "67abc123def4567890120001","status": "posted","postId": "1897654321098765432","postUrl": "https://x.com/yourhandle/status/1897654321098765432","postedAt": "2026-03-15T14:00:05.000Z"},{"platform": "linkedin","accountId": "67abc123def4567890120002","status": "posted","postId": "urn:li:share:7654321098765432100","postUrl": "https://www.linkedin.com/feed/update/urn:li:share:7654321098765432100","postedAt": "2026-03-15T14:00:08.000Z"},{"platform": "instagram","accountId": "67abc123def4567890120003","status": "posted","postId": "17890012345678901","postUrl": "https://www.instagram.com/p/ABC123xyz/","postedAt": "2026-03-15T14:00:12.000Z"}],"mediaItems": [{"type": "image","url": "https://example.com/announcement.jpg"}],"createdAt": "2026-03-01T12:00:00.000Z","updatedAt": "2026-03-15T14:00:12.000Z"}}
Update a post
/api/v1/posts/:idUpdate a scheduled or draft postUpdate a post that is in draft or scheduled status. Published, failed, and cancelled posts cannot be updated. Only include the fields you want to change — omitted fields are left unchanged.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Required | The post ID to update. |
idstringRequiredThe post ID to update.
Request body
| Name | Type | Required | Description |
|---|---|---|---|
content | string | Optional | Updated post text content. |
platforms | array | Optional | Updated platform targets. |
mediaItems | array | Optional | Updated media attachments. |
scheduledFor | string | Optional | Updated schedule time (ISO 8601). |
timezone | string | Optional | Updated timezone. |
platformSettings | object | Optional | Updated platform-specific settings. |
status | string | Optional | Change status (e.g. move a draft to scheduled).draftscheduled |
contentstringOptionalUpdated post text content.
platformsarrayOptionalUpdated platform targets.
mediaItemsarrayOptionalUpdated media attachments.
scheduledForstringOptionalUpdated schedule time (ISO 8601).
timezonestringOptionalUpdated timezone.
platformSettingsobjectOptionalUpdated platform-specific settings.
statusstringOptionalChange status (e.g. move a draft to scheduled).
draftscheduledcurl -X PATCH https://schedulala.com/api/v1/posts/67abc456def789012345cdef \-H "Authorization: Bearer sk_live_abc123..." \-H "Content-Type: application/json" \-d '{"content": "Updated announcement! Check out our new feature at example.com","scheduledFor": "2026-03-16T10:00:00Z"}'
{"success": true,"post": {"id": "67abc456def789012345cdef","status": "scheduled","content": "Updated announcement! Check out our new feature at example.com","scheduledFor": "2026-03-16T10:00:00.000Z","platforms": [{"platform": "twitter","accountId": "67abc123def4567890120001","status": "pending"},{"platform": "linkedin","accountId": "67abc123def4567890120002","status": "pending"},{"platform": "instagram","accountId": "67abc123def4567890120003","status": "pending"}],"createdAt": "2026-03-01T12:00:00.000Z","updatedAt": "2026-03-01T13:30:00.000Z"}}
Delete a post
/api/v1/posts/:idCancel or delete a postCancel a scheduled or draft post. The post status is set to cancelled and it will not be published. Already-published posts cannot be deleted through this endpoint.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Required | The post ID to cancel. |
idstringRequiredThe post ID to cancel.
schedulala post:delete 67abc456def789012345cdef
{"success": true,"deleted": true,"id": "67abc456def789012345cdef","method": "cancelled"}
Retry a failed post
/api/v1/posts/:id/retryRetry a failed postRetry delivery for a post with status failed or partially_failed. You can optionally specify which platforms to retry and add a delay before the retry attempt.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Required | The post ID to retry. |
idstringRequiredThe post ID to retry.
Request body
| Name | Type | Required | Description |
|---|---|---|---|
platforms | array | Optional | Array of platform names to retry. If omitted, all failed platforms are retried. |
delay | number | Optional | Seconds to wait before retrying.Default: 0 |
platformsarrayOptionalArray of platform names to retry. If omitted, all failed platforms are retried.
delaynumberOptionalSeconds to wait before retrying.
Default: 0
schedulala post:retry 67abc456def789012345cdef
{"success": true,"post": {"id": "67abc456def789012345cdef","status": "scheduled","content": "Excited to announce our new feature! Check it out at example.com","platforms": [{"platform": "twitter","accountId": "67abc123def4567890120001","status": "posted","postId": "1897654321098765432","postUrl": "https://x.com/yourhandle/status/1897654321098765432","postedAt": "2026-03-15T14:00:05.000Z"},{"platform": "instagram","accountId": "67abc123def4567890120003","status": "pending","previousError": "Media upload timeout"}]},"retriedPlatforms": ["instagram"]}
Validate content
/api/v1/posts/validateValidate content against platform limitsCheck whether your content meets each platform's requirements before creating a post. Returns per-platform validation results including character counts, media compatibility, and any errors.
Request body
| Name | Type | Required | Description |
|---|---|---|---|
content | string | Required | The text content to validate. |
platforms | array | Required | Array of platform name strings to validate against (e.g. ["twitter", "instagram", "tiktok"]). |
mediaItems | array | Optional | Array of media items to validate. Each has type and url. |
contentstringRequiredThe text content to validate.
platformsarrayRequiredArray of platform name strings to validate against (e.g. ["twitter", "instagram", "tiktok"]).
mediaItemsarrayOptionalArray of media items to validate. Each has type and url.
curl -X POST https://schedulala.com/api/v1/posts/validate \-H "Authorization: Bearer sk_live_abc123..." \-H "Content-Type: application/json" \-d '{"content": "Check out our latest product update! We have been working hard to bring you the best experience possible.","platforms": ["twitter", "tiktok", "instagram"],"mediaItems": [{ "type": "image", "url": "https://example.com/product.jpg" }]}'
{"success": true,"validation": {"isValid": false,"platforms": {"twitter": {"valid": true,"contentLength": 42,"maxLength": 280,"remainingCharacters": 238,"mediaValid": true},"tiktok": {"valid": false,"errors": ["TikTok requires a video. Image-only posts are not supported."],"mediaValid": false},"instagram": {"valid": true,"contentLength": 42,"maxLength": 2200,"remainingCharacters": 2158,"mediaValid": true}}}}