Create a post
Create a new post to publish or schedule across multiple social media platforms simultaneously.
Create a new post to publish or schedule across multiple social media platforms simultaneously. A post might mean something different depending on the context and the platform - for example, a single X post, a multi-thread X post, a LinkedIn post, or an Instagram Reel or Story. Posts use a container model where each container holds content for one segment (e.g., individual tweets in an X thread, or carousel items). Specify target platforms via the accounts array, referencing each connected account by its id from GET /v1/social-accounts (preferred) or its exact username - network names (e.g. x, linkedin) and nicknames are not identifiers and do not resolve. The request is rejected with 400 only when none of the supplied identifiers resolve, so an entry matching nothing alongside one that matches is dropped silently. Provide the post body either as a single content string or as a containers array of { content, media } objects - one of the two is required. Attach media by adding media objects to a container, each { url, filename } where url is the publicly accessible URL returned by the confirm-upload step (see Media API); media is not referenced by id. Include scheduledAt (ISO 8601 format, e.g. 2025-06-01T12:00:00Z) to schedule the post for future publishing, or omit it to publish immediately. Platform-specific options (e.g., TikTok privacy settings, YouTube categories, Pinterest board IDs) are provided as top-level keys named after the network (tiktok, youtube, instagram, threads, google_business, pinterest, linkedin, facebook, vimeo, reddit) - not nested under any wrapper object. The response echoes these back nested under networkOverrideConfiguration (e.g. tiktokConfiguration), so the request and response shapes for platform config differ by design. Unrecognised top-level keys are ignored and reported in the response warnings array. Managed-key YouTube uploads are admitted at execution time from a shared paced daily pool; scheduling never reserves capacity. A denied YouTube destination fails independently and its existing error string (also in webhook results) contains a stable reason code (release_pending, org_limit_reached, daily_limit_reached, provider_quota_exhausted, or quota_unavailable) and an ISO 8601 retryAt when known. retryAt estimates earliest eligibility for a capacity release, organization-cap relaxation, or next Pacific quota day; it is not a reservation. Retry manually. If another destination already published, create a new YouTube-only post targeting the failed account because partially published posts cannot be edited or rescheduled. BYOK bypasses the shared pool; dispatched attempts are not refunded on failure.
/v1/postsHeader Parameters
Optional client-generated key (a UUID v4 is ideal, max 255 printable ASCII characters) that makes this create safe to retry. Retrying with the same key and the same request body returns the original response together with an Idempotency-Replayed: true header, instead of creating a second post. Keys are scoped to your organization and to this endpoint, and are remembered for 24 hours.
length <= 255Array of post containers. Each container represents a combo for the post content with its own text and media. Use this if you want to create a post with an automated reply to the root container. Otherwise, use the 'content' field.
Simple text content for the post. Use this for single-container posts. Either 'content' or 'containers' must be provided. If you use 'containers', the first container will be the root container and the rest will be published as replies to the root container. Threads rejects content longer than 500 characters, so a post targeting a Threads account (including when cross-posting alongside other networks) is rejected with 400 if it exceeds that - unless threads.content supplies a Threads-only body, which is what gets checked instead. To publish different text on one network, put content inside that network's block (e.g. linkedin.content); this field is then the fallback for every network without one.
Array of social media account identifiers where this post will be published. Each entry is either the account's id as returned by GET /v1/social-accounts (preferred) or the account's exact username. Network names (e.g. 'x', 'linkedin') and nicknames are NOT identifiers and will not resolve. Account ids are opaque - pass back exactly what the API returned and never construct one. A username is matched by exact equality with no network or active-account filter, so a username shared across networks publishes to every account that carries it. The request is rejected with 400 only when NONE of the supplied identifiers resolve; if at least one resolves, the unresolved entries are silently ignored, so compare the returned socialAccounts against what you sent.
1 <= itemsISO 8601 timestamp for when the post should be automatically published. If not provided, the post will be published immediately (unless it's a draft). If a time in the past is provided, the post will be published immediately. The maximum time in the future is 30d - a later timestamp is rejected with 400 and no post is created.
date-timeCustom and override configuration for Threads content. Not to be confused with threaded content or anything other than the Threads By Instagram - the social network.
Custom and override configuration for Instagram content.
Custom and override configuration for YouTube content.
Custom and override configuration for TikTok content.
Custom and override configuration for Google Business Profile content.
Custom configuration for Pinterest content. board_id is required when publishing to Pinterest.
Vimeo-specific video configuration
Custom configuration for LinkedIn content.
Custom configuration for Facebook content.
Custom configuration for Reddit content. subreddit and title are required when publishing to Reddit. Only text (self) and link posts are supported - media containers are rejected.
Custom configuration for X content. Currently only the per-network content override.
Custom configuration for Bluesky content. Currently only the per-network content override.
Opt in to automatic video processing. When true, video media is inspected and re-encoded to each target network's requirements (container, codec, resolution, frame rate and file size) before publishing, and the correct rendition is sent to each network. Leave unset to publish the file exactly as supplied. Billed per rendition produced, by output duration in 10-second blocks (rounded up, minimum one block per rendition); validation and inspection are always free. Has no effect on posts without video media.
Response Body
const body = JSON.stringify({ "accounts": [ "Kx7vQ", "Tm2bN" ]})fetch("https://api.outstand.so/v1/posts", { method: "POST", headers: { "Content-Type": "application/json", "Idempotency-Key": "b1f6c3f4-8f0e-4a5b-9c2d-7e1a0b3c4d5e" }, body}){
"success": true,
"warnings": [
"Ignored unrecognised key 'post_mode' in 'tiktok'. Did you mean 'postMode'?"
],
"post": {
"id": "9dyJS",
"orgId": "abc123",
"publishedAt": null,
"scheduledAt": "2025-09-20T14:00:00Z",
"isDraft": false,
"createdAt": "2025-01-15T10:30:00Z",
"scheduled": true,
"socialAccounts": [
{
"id": "Kx7vQ",
"nickname": "My Company",
"network": "x",
"username": "mycompany"
}
],
"containers": [
{
"id": "8xKmL",
"content": "Check out our new product launch! #excited",
"media": [
{
"id": 123,
"url": "https://media.yoursite.com/images/launch.jpg",
"filename": "launch-photo.jpg"
}
]
}
]
}
}{
"success": true,
"warnings": [
"Ignored unrecognised key 'post_mode' in 'tiktok'. Did you mean 'postMode'?"
],
"post": {
"id": "9dyJS",
"orgId": "abc123",
"publishedAt": null,
"scheduledAt": "2025-09-20T14:00:00Z",
"isDraft": false,
"createdAt": "2025-01-15T10:30:00Z",
"scheduled": true,
"socialAccounts": [
{
"id": "Kx7vQ",
"nickname": "My Company",
"network": "x",
"username": "mycompany"
}
],
"containers": [
{
"id": "8xKmL",
"content": "Check out our new product launch! #excited",
"media": [
{
"id": 123,
"url": "https://media.yoursite.com/images/launch.jpg",
"filename": "launch-photo.jpg"
}
]
}
]
}
}{
"success": false,
"error": "Invalid payload",
"code": "idempotency_key_reuse",
"details": {
"content": {
"_errors": [
"Required"
]
}
}
}{
"success": false,
"error": "Invalid payload",
"code": "idempotency_key_reuse",
"details": {
"content": {
"_errors": [
"Required"
]
}
}
}{
"success": false,
"error": "Invalid payload",
"code": "idempotency_key_reuse",
"details": {
"content": {
"_errors": [
"Required"
]
}
}
}{
"success": false,
"error": "Internal server error",
"code": "idempotency_recovery_failed",
"message": "Database connection failed"
}