Create post

Creates a UniPost post resource using the same payload shape as POST/v1/posts/validate. Immediate publish requests are accepted and queued asynchronously; background workers perform the actual platform delivery. Use scheduling or draft mode when you want creation without immediate dispatch.
https://api.unipost.dev
POST/v1/posts
Authorization
In header · Bearer <token>
In header · application/json
Request Body

Authorization

AuthorizationBearer <token>In header
Workspace API key.
Content-Typeapplication/jsonIn header
Request body format.
Idempotency-KeyOptionalstringIn header
Optional alternative to the body field. Max 64 chars, 24 hour replay window.

Request Body

captionOptionalstring
Shared caption sent to every target account. Required unless platform_posts is set.
account_idsOptionalstring[]
Target social account IDs when the same caption/media should fan out everywhere.
platform_postsOptionalarray
Recommended per-account request shape for multi-platform publishing.
media_urlsOptionalstring[]
Public URLs for hosted media. Do not reserve these with POST/v1/media; that endpoint is only for raw file uploads that have a known byte size. Ignored when platform_posts overrides are used.
media_idsOptionalstring[]
Media library IDs returned by POST/v1/media. Use these for local files and larger videos after GET/v1/media/:media_id reports uploaded.
scheduled_atOptionalstring
ISO-8601 timestamp. If present, UniPost stores the post in scheduled state and the scheduler enqueues delivery later. Free workspaces can hold up to 50 undeleted parent posts in scheduled status at once; paid plans do not cap active scheduled backlog.
idempotency_keyOptionalstring
Optional body-level key for scheduled posts. While a matching post is still scheduled, UniPost returns the existing scheduled post for the same payload and returns 409 for a different payload.
statusOptional"draft"
Save without dispatching any platform jobs. Omit the field entirely for immediate publish. Drafts are published later via POST/v1/posts/:post_id/publish.
Valuesdraft

platform_posts[]

platform_posts[].account_idstring
Connected social account to publish to.
platform_posts[].captionOptionalstring
Account-specific caption override.
platform_posts[].media_urlsOptionalstring[]
Account-specific hosted asset URLs. Use this field directly when the asset already has a public URL; size_bytes is only needed for POST/v1/media local-file uploads.
platform_posts[].media_idsOptionalstring[]
Account-specific media library asset IDs. Pending uploads fail pre-publish validation with media_not_uploaded.
platform_posts[].thread_positionOptionalinteger
1-indexed thread slot. Supported for X and Bluesky thread publishing.
platform_posts[].first_commentOptionalstring
Optional first reply/comment after publish. Supported on X, LinkedIn, and Instagram.
platform_posts[].platform_optionsOptionalobject
Platform-specific options such as Instagram media type or YouTube metadata.

Response Body

202
idstring
UniPost post ID.
execution_modestring
Immediate publish enqueues delivery jobs and returns before platform dispatch finishes.
Valuesasync
captionstring | null
Top-level shared caption when one exists.
statusstring
Initial lifecycle state for the accepted post. Immediate creates usually start as queued or publishing, then converge to a final aggregate state.
Valuesqueued | publishing | published | partial | failed | draft | scheduled | cancelled
queued_results_countinteger
How many per-account delivery results were queued for background processing.
active_job_countinteger
How many queue jobs are currently active for this post.
created_atstring
Creation timestamp.
scheduled_atstring | null
Scheduled publish timestamp when queued.
published_atstring | null
Final publish timestamp when at least one result was published.
resultsarray
Initial per-account result rows created at enqueue time.
results[].social_account_idstring
Destination account ID.
results[].platformstring
Normalized platform name.
Valuestwitter | linkedin | instagram | facebook | threads | youtube | tiktok | bluesky | pinterest
results[].statusstring
Initial per-account state. Rows move through in-flight values first, then settle on final result values.
Valuesqueued | publishing | processing | published | failed
results[].external_idstring | null
Platform-native post identifier when available after delivery completes.
results[].error_messagestring | null
Platform-specific failure reason when delivery eventually fails.
request_idstring
Request identifier for debugging and support.
201
idstring
UniPost post ID.
statusstring
Created resource state for non-immediate creates.
Valuesscheduled | draft
created_atstring
Creation timestamp.
scheduled_atstring | null
Scheduled publish time when the post was created as scheduled content.
request_idstring
Request identifier for debugging and support.
400
error.codestring
Machine-readable error code.
error.normalized_codestring
Lowercase compatibility alias for the error code.
error.messagestring
Human-readable error message.
error.issuesOptionalarray
Structured pre-publish validation issues such as media_not_uploaded.
request_idstring
Request identifier for debugging and support.
401
error.codestring
Machine-readable error code.
error.normalized_codestring
Lowercase compatibility alias for the error code.
error.messagestring
Human-readable error message.
error.issuesOptionalarray
Structured pre-publish validation issues such as media_not_uploaded.
request_idstring
Request identifier for debugging and support.
402
error.codestring
Machine-readable error code.
error.normalized_codestring
Lowercase compatibility alias for the error code.
error.messagestring
Human-readable error message.
error.issuesOptionalarray
Structured pre-publish validation issues such as media_not_uploaded.
request_idstring
Request identifier for debugging and support.
422
error.codestring
Machine-readable error code.
error.normalized_codestring
Lowercase compatibility alias for the error code.
error.messagestring
Human-readable error message.
error.issuesOptionalarray
Structured pre-publish validation issues such as media_not_uploaded.
request_idstring
Request identifier for debugging and support.
500
error.codestring
Machine-readable error code.
error.normalized_codestring
Lowercase compatibility alias for the error code.
error.messagestring
Human-readable error message.
error.issuesOptionalarray
Structured pre-publish validation issues such as media_not_uploaded.
request_idstring
Request identifier for debugging and support.

Media Inputs

Hosted URL: if your image or video is already publicly reachable, send it in platform_posts[].media_urls. Do not call POST/v1/media for this path.

Local file bytes: reserve an upload with POST/v1/media, PUT the bytes to the returned upload URL, then publish with platform_posts[].media_ids. size_bytes is optional; UniPost hydrates the actual byte length after upload.

Scheduling Limits

Free active backlog: Free workspaces can keep up to 50 undeleted parent posts in scheduled status. Exceeding that cap returns PLAN_SCHEDULED_POST_LIMIT_EXCEEDED. The existing 100 posts/month quota still applies when posts are created and delivered. Paid plans do not cap active scheduled backlog.

Media retention: scheduled posts keep uploaded media until they reach a final status. After success, failed, partial, or cancellation, UniPost retains media according to the workspace plan before cleanup.

Publishing Result

Poll Model: immediate publish returns 202 after UniPost accepts and queues delivery. Poll GET/v1/posts/:post_id to read the final publishing result.

Failure Model: failed result rows include error_source, error_temporality, provider_error, and retry_policy. Use retry_policy.will_retry for automatic retries and avoid parsing error_message.

Push Model: create a webhook subscription with POST/v1/webhooks to receive final publishing events from UniPost.