Posts

Create a post

Create a scheduled or immediate post. Set dry_run: true to validate first. Dry-run returns normalized fields and warnings without creating a post, copying remote media, consuming post-item/storage quota, reserving X quota, emitting webhooks, or enqueueing publication. Authentication bookkeeping, request rate limits, API usage recording, and read-only validation still occur. An Idempotency-Key header is ignored during dry-run. Third-party media is checked but not copied; the response includes remote_media_not_materialized because live create performs storage copy and final byte validation.

For X (platform: twitter):

  • Managed X posting is limited per workspace monthly X posting cycle.
  • URLs are blocked in the caption and any metadata.x_thread_tweets segment, including bare domains like poster.ly.
  • Each X thread segment counts as one managed X post toward the monthly allowance.
  • Call GET /api/v1/x-posting/quota to inspect remaining allowance before scheduling.
  • Articles: pass settings.article ({ title, cover?: "first_image" | "none" }) to publish the caption as an X Article. The caption is the Article body, written as Markdown, and attached images can be placed with ![caption](media:1). The X account needs X Premium. Articles cannot be combined with a poll, thread, paid partnership, video, or GIF, and the 280-character post limit does not apply. An Article counts as one managed X post.

Threads (X / Twitter and Threads / Meta):

  • For X, set post_type: "x_thread" and metadata.x_thread_tweets: string[] (2+ entries).
  • For Threads, set post_type: "threads_thread" and metadata.threads_thread_posts: string[] (2+ entries).
  • The caption stored on the post is always the first array entry; any caption you also pass is ignored.
  • Media (media_url / media_urls) attaches to the first post only.
  • Per-segment length is validated up front: 280 chars for X (4000 verified, 25000 organization), 500 chars for Threads.

Instagram settings:

  • Pass settings.__type: "instagram" or "instagram-standalone".
  • settings.post_type accepts post/feed, story, reel, or carousel.
  • A caption @username is a caption mention only. Use settings.user_tags for native clickable media tags and settings.collaborators for co-author invitations.
  • Native user tags work with eligible direct Instagram and Meta-linked accounts. Collaborators require an eligible Meta-linked Instagram account. GET /api/v1/accounts and the account-specific schema expose both capabilities.
  • Native user tags support feed images, Reels/video, and Stories. Carousel tags are applied to each child item. Collaborators support feed images, Reels, and carousels, but not Stories.
  • Use settings.first_comment, settings.media_accessibility (preferred), settings.media_alt_texts (legacy), settings.reel_cover_url, and settings.reel_thumb_offset for other composer-equivalent controls.
  • Trial Reels can be requested with settings.is_trial_reel: true; settings.graduation_strategy defaults to "MANUAL" and also accepts "SS_PERFORMANCE".
  • Caption add-ons: settings.caption_addon (type poll or comment_prompt), or settings.poll_attachment / settings.is_comment_prompt_used. Facebook Login only. The caption is required and is the poll question or the prompt. Not available on Stories. On a carousel, set the add-on on the parent only. A poll and a comment prompt cannot be combined. is_poll_duration_extended is only valid with a poll. The add-on is written once when the media container is created.
  • Meta controls Trial Reel availability per Instagram account. If the Trial toggle does not appear for that account in Instagram, Meta may reject API publishing.

Other platform settings:

  • YouTube: title/privacy/thumbnail/tags/category.
  • LinkedIn: document title/filename, organization mentions, video thumbnail, media alt text.
  • TikTok: a single video or a photo slideshow of 1 to 35 images. Image media auto-detects as a slideshow, so post_type and media_type are optional for photos and every image is posted; set post_type: "carousel" (2 or more images) or "image" (one), or settings.media_type: "PHOTO", to be explicit. Also supports direct-post privacy, comment/duet/stitch toggles, title, commercial disclosure, and settings.video_cover_timestamp_ms to pick the video frame used as the cover (direct-post videos only; TikTok does not accept custom uploaded covers).
  • Pinterest: board, title, destination link.
  • Google Business Profile: standard/event/offer post type, event schedule, offer details, CTA.
  • Facebook: post/story/reel/cover-photo intent and colored text background preset. Reels through the Graph Reels API must be 90 seconds or shorter; use video for longer clips.
  • X: reply settings, polls, media alt text.
  • Threads: reply controls, long-form text attachments, media alt text.
  • Bluesky: languages and media alt text.
post/api/v1/posts

Request

  • Base URL: https://www.poster.ly
  • URL: https://www.poster.ly/api/v1/posts
  • Auth: HTTP bearer

Headers

Idempotency-Keystring

Optional unique key for safely retrying a create-post request without duplicating the post.

Request body

account_idstring

Social account ID

usernamestring

Alternative account lookup by username + platform

platformstring
captionstring nullable

Post caption. On Instagram, @username creates a caption mention only; it does not create a native media tag or collaborator invitation. For X, URLs are currently blocked in the caption and thread segments.

scheduled_atstring date-time nullable
post_type'text' | 'image' | 'document' | 'video' | 'reel' | 'carousel' | 'story' | 'story_series' | 'x_thread' | 'threads_thread' | 'photo' | 'cover_photo' | 'post' | 'feed' | 'feed-post' | 'cover-photo' | 'photos' | 'stories' | 'reels' nullable

Optional post type. Omit for auto-detection from media. Use x_thread (twitter) or threads_thread (threads) to schedule a multi-post reply chain. photo is normalized for TikTok photo posts; cover_photo is a Facebook-only semantic type.

media_urlstring nullable

Media URL. Posterly media URLs returned by upload endpoints are used as-is. Third-party HTTP(S) URLs are copied into posterly storage before the post is saved, so short-lived signed URLs must still be live when the request runs.

media_urlsstring[] nullable

Media URLs. Posterly media URLs are used as-is; third-party HTTP(S) URLs are copied into posterly storage before the post is saved. For TikTok, 2 or more images auto-create a photo slideshow of up to 35 images and every image is posted.

metadataobject nullable

Platform-specific metadata.

Prefer settings for first-class platform settings such as Instagram collaborators, stories, trial Reels, first comments, alt text, and Reel covers.

For X threads, pass x_thread_tweets as an array of 2+ tweet strings. The first entry leads the thread; the rest are published as replies in order. Each segment must fit the X character limit (280 standard, 4000 verified, 25000 organization) and cannot contain a URL. Each segment counts as one managed X post toward the monthly allowance.

For Threads threads, pass threads_thread_posts as an array of 2+ post strings (each ≤ 500 characters). Same chain semantics: first leads, rest are self-replies.

reel_cover_urlstring nullable

Custom cover image URL for Instagram/Facebook Reels. Also accepted as settings.reel_cover_url for Instagram.

reel_cover_methodstring nullable

Optional source label for the Reel cover, such as api, upload, or frame.

reel_thumb_offsetnumber nullable

Video timestamp offset, in milliseconds, to use as the Reel thumbnail when no cover URL is supplied.

workspace_idstring nullable

Optional workspace to create the post inside. Defaults to the account workspace, then the personal workspace.

dry_runboolean

When true, validates and normalizes the post without creating records, copying remote media, consuming post-item or storage quota, reserving X quota, emitting webhooks, or enqueueing publication. Authentication bookkeeping, request rate limits, API usage recording, and read-only validation still occur. Validate before the first live create.

group_idstring nullable

Optional caller-defined group ID for campaign/batch cleanup. Also accepted as api_group_id or post_group_id.

release_idstring nullable

Optional caller-defined release ID for external repair/relink workflows.

Example request

{
  "account_id": "123",
  "platform": "instagram",
  "caption": "Launching soon",
  "scheduled_at": "2026-03-20T10:00:00.000Z",
  "post_type": "image",
  "media_urls": [
    "https://assets.poster.ly/users/123/post.jpg"
  ],
  "settings": {
    "__type": "instagram",
    "post_type": "post",
    "collaborators": [
      {
        "label": "partner_username"
      }
    ]
  }
}

Response

Dry-run validation result, or an existing post returned for a replayed idempotent request

OR

Example response

{
  "dry_run": true,
  "valid": true,
  "normalized": {
    "account_id": 123,
    "platform": "instagram",
    "post_type": "image",
    "scheduled_at": "2026-08-01T09:00:00.000Z",
    "workspace_id": "2d0a6d4c-9eef-4ee2-9026-2ca0dc29c8d6"
  },
  "warnings": [],
  "would_create": {
    "status": "scheduled"
  }
}

Changes

No recorded changes to this operation across all 1 revision of this API.