---
title: "Update post"
method: PATCH
path: "/api/v1/posts/{id}"
tags: ["Posts"]
---

# Update post

`PATCH /api/v1/posts/{id}`

## Request

- Base URL: `https://www.poster.ly`
- URL: `https://www.poster.ly/api/v1/posts/{id}`
- Auth: HTTP bearer

Update a draft or scheduled post, including a teammate's post in a shared workspace (per your role there).

Editors may edit a draft; anything already scheduled, paused, or failed needs a publisher, and moving `scheduled_at` always needs a publisher, even on a draft.

If a client has already approved the post, a caption edit reopens caption approval and a media or thumbnail edit reopens asset approval. A reschedule, account change or settings change cannot be attributed to one axis and reopens both.

For X posts, updated content is re-validated against the current URL restriction and monthly X allowance.

## Path parameters

- `id` integer, required

## Request body

- UpdatePostRequest
  - `caption` string, nullable
  - `scheduled_at` string, 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
  - `media_url` string, nullable: Media URL. Posterly storage URLs are used as-is; third-party HTTP(S) URLs are copied into posterly storage before the post is saved.
  - `media_urls` string[], nullable: Media URLs. Posterly storage URLs are used as-is; third-party HTTP(S) URLs are copied into posterly storage before the post is saved.
  - `metadata` object, nullable
  - `settings` union: Platform-specific settings to merge into the post.
    - InstagramPostSettings: Instagram-specific create/update settings. These map to the same Instagram scheduling controls available in the posterly composer.
      - `__type` 'instagram' | 'instagram-standalone': Use `instagram` for Meta/Facebook-linked Instagram accounts and `instagram-standalone` for standalone Instagram accounts.
      - `post_type` 'post' | 'feed' | 'story' | 'reel' | 'carousel': `post`/`feed` publishes a regular feed post. Use `story`, `reel`, or `carousel` for those formats.
      - `is_trial_reel` boolean: Publish a video as an Instagram Trial Reel when supported by the connected account. Requires `post_type: "reel"` or a video feed post that resolves to a Reel. Meta controls account availability; if the Trial toggle does not appear for the account in Instagram, publishing may fail.
      - `graduation_strategy` 'MANUAL' | 'SS_PERFORMANCE': Trial Reel graduation strategy. `MANUAL` keeps promotion to followers inside the Instagram app; `SS_PERFORMANCE` lets Meta auto-share if the trial performs well.
      - `collaborators` union[]: Native co-author invitations, not caption mentions or media tags. Meta-linked Instagram accounts only; up to 3; feed images, Reels, and carousels; not Stories.
        - union
          - string
          - object
            - `label` string, required
      - `user_tags` union[]: Native clickable media tags, not caption @mentions. Supported by eligible direct Instagram and Meta-linked connections; feed images, Reels/video, and Stories. Tags apply to each carousel child and the first Story in a Story Series.
        - union
          - string
          - object
            - `username` string, required
      - `first_comment` string: Optional first comment to post after the Instagram post is published.
      - `media_alt_texts` object: Legacy map of each source media URL to alt text. Still accepted for backwards compatibility.
      - `media_accessibility` object[]: Preferred ordered accessibility metadata. Stable media identity survives platform image preparation.
        - `index` integer, required
        - `asset_id` string
        - `source_url` string, uri
        - `alt_text` string, required
      - `reel_cover_url` string: Custom cover image URL for Instagram Reels.
      - `reel_thumb_offset` number: Video timestamp offset, in milliseconds, to use as the Instagram Reel thumbnail when no cover URL is supplied.
      - `caption_addon` object, nullable: Optional caption add-on. `type` is `none`, `poll`, or `comment_prompt`. A poll needs 2 to 4 `options` of 1 to 25 characters (an emoji counts as one) and the caption is the question. A comment prompt uses the caption as the prompt. Facebook Login only. Not available on Stories. Carousel parent only. At most one add-on. Pass null or `type: "none"` to clear. Write-once when the media container is created.
        - `type` 'none' | 'poll' | 'comment_prompt'
        - `options` string[]
        - `extended_duration` boolean: Longer poll duration. Only valid with type poll.
      - `poll_attachment` object: Poll choices. `option_a` and `option_b` are required. `option_c` and `option_d` are optional, and `option_d` requires `option_c`. Serialised JSON must be 200 characters or fewer. Mutually exclusive with `is_comment_prompt_used`. The caption is the question.
        - `option_a` string
        - `option_b` string
        - `option_c` string
        - `option_d` string
        - `options` string[]
      - `is_comment_prompt_used` boolean: Attach a comment prompt. The caption is the prompt. Mutually exclusive with `poll_attachment`. Facebook Login only. Not available on Stories.
      - `is_poll_duration_extended` boolean: Request the longer poll duration. Only valid together with a poll.
    - union: Platform-specific composer controls. Call list_platforms (view=schema with the selected account_id) before sending settings. Supported platforms are sourced from the public platform registry. Planned possibilities currently tracked: reddit, medium, skool, whop.
      - object
        - `__type` 'instagram' | 'instagram-standalone': Instagram account type hint.
        - `post_type` 'post' | 'feed' | 'story' | 'reel' | 'carousel': Instagram publishing format.
        - `is_trial_reel` boolean: Request an Instagram Trial Reel when the account supports it.
        - `trial_reel` boolean: Request an Instagram Trial Reel when the account supports it. Alias for is_trial_reel.
        - `graduation_strategy` 'MANUAL' | 'SS_PERFORMANCE': Trial Reel graduation strategy.
        - `collaborators` unknown[]: Native co-author invitations. Meta-linked Instagram accounts only; feed images, Reels, and carousels; maximum 3; not Stories.
          - unknown
        - `user_tags` unknown[]: Native clickable media tags, not caption @mentions. Supported by eligible direct Instagram and Meta-linked connections; feed images, Reels/video, and Stories. Tags apply to each carousel child and the first Story in a Story Series.
          - unknown
        - `first_comment` string: First comment to publish after the post.
        - `reel_cover_url` string: Custom Reel cover image URL.
        - `cover_url` string: Custom Reel cover image URL. Alias for reel_cover_url.
        - `reel_thumb_offset` number: Video timestamp, in milliseconds, for a generated Reel thumbnail.
        - `thumb_offset` number: Video timestamp, in milliseconds, for a generated Reel thumbnail. Alias for reel_thumb_offset.
        - `is_ai_generated` boolean: Label the parent media container as AI-generated (is_ai_generated). For carousels, set this on the parent only, never on child slides.
        - `instagram_is_ai_generated` boolean: Label the parent media container as AI-generated (is_ai_generated). For carousels, set this on the parent only, never on child slides. Alias for is_ai_generated.
        - `ai_generated` boolean: Label the parent media container as AI-generated (is_ai_generated). For carousels, set this on the parent only, never on child slides. Alias for is_ai_generated.
        - `audio_id` string: Licensed Instagram audio ID for Reels (audio_configuration.audio_id). Meta-linked Facebook Login accounts only; hidden for Instagram Login.
        - `instagram_audio_id` string: Licensed Instagram audio ID for Reels (audio_configuration.audio_id). Meta-linked Facebook Login accounts only; hidden for Instagram Login. Alias for audio_id.
        - `caption_addon` object: Optional caption add-on. type is none, poll, or comment_prompt. A poll needs 2 to 4 options (1 to 25 characters each; an emoji counts as one) and the caption is the question. A comment prompt uses the caption as the prompt. Facebook Login only. Not Stories. Carousel parent only. At most one add-on. Pass null or type none to clear.
        - `instagram_caption_addon` object: Optional caption add-on. type is none, poll, or comment_prompt. A poll needs 2 to 4 options (1 to 25 characters each; an emoji counts as one) and the caption is the question. A comment prompt uses the caption as the prompt. Facebook Login only. Not Stories. Carousel parent only. At most one add-on. Pass null or type none to clear. Alias for caption_addon.
        - `poll_attachment` object: Poll choices: option_a and option_b required, option_c and option_d optional, option_d requires option_c. Serialised JSON must be 200 characters or fewer. Mutually exclusive with is_comment_prompt_used. The caption is the question.
        - `instagram_poll_attachment` object: Poll choices: option_a and option_b required, option_c and option_d optional, option_d requires option_c. Serialised JSON must be 200 characters or fewer. Mutually exclusive with is_comment_prompt_used. The caption is the question. Alias for poll_attachment.
        - `is_comment_prompt_used` boolean: Attach a comment prompt. The caption is the prompt. Mutually exclusive with poll_attachment. Facebook Login only. Not Stories.
        - `instagram_is_comment_prompt_used` boolean: Attach a comment prompt. The caption is the prompt. Mutually exclusive with poll_attachment. Facebook Login only. Not Stories. Alias for is_comment_prompt_used.
        - `is_poll_duration_extended` boolean: Request the longer poll duration. Only valid together with a poll.
        - `instagram_is_poll_duration_extended` boolean: Request the longer poll duration. Only valid together with a poll. Alias for is_poll_duration_extended.
        - `media_alt_texts` object: Legacy map of source media URLs to alt text. Still accepted for backwards compatibility.
        - `alt_texts` object: Legacy map of source media URLs to alt text. Still accepted for backwards compatibility. Alias for media_alt_texts.
        - `media_accessibility` object[]: Ordered media accessibility entries: { index, asset_id?, source_url?, alt_text }. Preferred because identity survives platform media preparation.
          - `index` integer, required
          - `asset_id` string
          - `source_url` string, uri
          - `alt_text` string, required
      - object
        - `post_type` 'post' | 'feed' | 'story' | 'reel' | 'cover_photo': Facebook publishing format. Reel uses the Graph Reels API and must be 90 seconds or shorter; use video for longer clips. A 90.0 second Reel is allowed.
        - `text_format_preset_id` string: Styled text post background preset.
        - `background_preset_id` string: Styled text post background preset. Alias for text_format_preset_id.
        - `reel_cover_url` string: Custom Reel cover image URL.
        - `cover_url` string: Custom Reel cover image URL. Alias for reel_cover_url.
        - `media_alt_texts` object: Legacy map of source media URLs to alt text. Still accepted for backwards compatibility.
        - `alt_texts` object: Legacy map of source media URLs to alt text. Still accepted for backwards compatibility. Alias for media_alt_texts.
        - `media_accessibility` object[]: Ordered media accessibility entries: { index, asset_id?, source_url?, alt_text }. Preferred because identity survives platform media preparation.
          - `index` integer, required
          - `asset_id` string
          - `source_url` string, uri
          - `alt_text` string, required
      - object
        - `privacy_level` string: TikTok direct-post privacy level from the creator info helper.
        - `allow_comment` boolean: Allow comments when direct posting.
        - `allow_duet` boolean: Allow duets when direct posting.
        - `allow_stitch` boolean: Allow stitches when direct posting.
        - `title` string: For a video, the title is the first line of the caption when the title and the caption both fit within 2,200 characters. For a photo post, it is a 90-character title.
        - `media_type` 'PHOTO': Set to PHOTO for TikTok photo posts or multi-photo slideshows.
        - `photo_cover_index` number: Zero-based cover image index for TikTok photo posts.
        - `video_cover_timestamp_ms` number: Millisecond timestamp of the video frame to use as the cover (direct post only).
        - `cover_timestamp_ms` number: Millisecond timestamp of the video frame to use as the cover (direct post only). Alias for video_cover_timestamp_ms.
        - `auto_add_music` boolean: Ask TikTok to add recommended music to photo posts when direct posting.
        - `is_commercial_content` boolean: TikTok commercial content disclosure.
        - `is_your_brand` boolean: TikTok branded content: your own brand.
        - `is_branded_content` boolean: TikTok branded content: third-party brand.
        - `ai_generated` boolean: Label the post as AI-generated (TikTok is_aigc).
        - `ai_disclosure` boolean: Label the post as AI-generated (TikTok is_aigc). Alias for ai_generated.
      - object
        - `reply_settings` 'everyone' | 'following' | 'mentionedUsers' | 'subscribers' | 'verified': Who can reply to the post.
        - `x_reply_settings` 'everyone' | 'following' | 'mentionedUsers' | 'subscribers' | 'verified': Who can reply to the post. Alias for reply_settings.
        - `poll` object: X poll settings: options and duration_minutes.
        - `x_poll` object: X poll settings: options and duration_minutes. Alias for poll.
        - `article` object: Publish as an X Article: { title, cover?: "first_image" | "none" }. The post caption is the Article body, written as Markdown (headings, bold, italic, lists, quotes, code blocks, tables, dividers). Reference attached images with ![caption](media:1). Needs an X Premium account. Not combinable with poll, thread, paid_partnership or video/GIF. Pass null to turn Article mode off.
        - `x_article` object: Publish as an X Article: { title, cover?: "first_image" | "none" }. The post caption is the Article body, written as Markdown (headings, bold, italic, lists, quotes, code blocks, tables, dividers). Reference attached images with ![caption](media:1). Needs an X Premium account. Not combinable with poll, thread, paid_partnership or video/GIF. Pass null to turn Article mode off. Alias for article.
        - `ai_generated` boolean: Label the post as AI-generated (X made_with_ai).
        - `ai_disclosure` boolean: Label the post as AI-generated (X made_with_ai). Alias for ai_generated.
        - `made_with_ai` boolean: Label the post as AI-generated (X made_with_ai). Alias for ai_generated.
        - `paid_partnership` boolean: Mark the post as a paid partnership (POST /2/tweets paid_partnership). Existing tweet.write.
        - `x_paid_partnership` boolean: Mark the post as a paid partnership (POST /2/tweets paid_partnership). Existing tweet.write. Alias for paid_partnership.
        - `media_alt_texts` object: Legacy map of source media URLs to alt text. Still accepted for backwards compatibility.
        - `alt_texts` object: Legacy map of source media URLs to alt text. Still accepted for backwards compatibility. Alias for media_alt_texts.
        - `media_accessibility` object[]: Ordered media accessibility entries: { index, asset_id?, source_url?, alt_text }. Preferred because identity survives platform media preparation.
          - `index` integer, required
          - `asset_id` string
          - `source_url` string, uri
          - `alt_text` string, required
      - object
        - `document_title` string: Title for a LinkedIn PDF/document post.
        - `linkedin_document_title` string: Title for a LinkedIn PDF/document post. Alias for document_title.
        - `document_filename` string: Filename for a LinkedIn document post.
        - `mentions` unknown[]: LinkedIn organization mention objects.
          - unknown
        - `linkedin_mentions` unknown[]: LinkedIn organization mention objects. Alias for mentions.
          - unknown
        - `poll` object: LinkedIn poll: { question, options (2-4), duration (ONE_DAY|THREE_DAYS|SEVEN_DAYS|FOURTEEN_DAYS) }. Mutually exclusive with media.
        - `linkedin_poll` object: LinkedIn poll: { question, options (2-4), duration (ONE_DAY|THREE_DAYS|SEVEN_DAYS|FOURTEEN_DAYS) }. Mutually exclusive with media. Alias for poll.
        - `thumbnail_url` string: Custom video thumbnail URL.
        - `content_call_to_action_label` 'APPLY' | 'DOWNLOAD' | 'VIEW_QUOTE' | 'LEARN_MORE' | 'SIGN_UP' | 'SUBSCRIBE' | 'REGISTER' | 'JOIN' | 'ATTEND' | 'REQUEST_DEMO' | 'SEE_MORE' | 'BUY_NOW' | 'SHOP_NOW': LinkedIn contentCallToActionLabel, including BUY_NOW and SHOP_NOW (version 202504). Pair with content_landing_page.
        - `cta_label` 'APPLY' | 'DOWNLOAD' | 'VIEW_QUOTE' | 'LEARN_MORE' | 'SIGN_UP' | 'SUBSCRIBE' | 'REGISTER' | 'JOIN' | 'ATTEND' | 'REQUEST_DEMO' | 'SEE_MORE' | 'BUY_NOW' | 'SHOP_NOW': LinkedIn contentCallToActionLabel, including BUY_NOW and SHOP_NOW (version 202504). Pair with content_landing_page. Alias for content_call_to_action_label.
        - `linkedin_cta_label` 'APPLY' | 'DOWNLOAD' | 'VIEW_QUOTE' | 'LEARN_MORE' | 'SIGN_UP' | 'SUBSCRIBE' | 'REGISTER' | 'JOIN' | 'ATTEND' | 'REQUEST_DEMO' | 'SEE_MORE' | 'BUY_NOW' | 'SHOP_NOW': LinkedIn contentCallToActionLabel, including BUY_NOW and SHOP_NOW (version 202504). Pair with content_landing_page. Alias for content_call_to_action_label.
        - `content_landing_page` string: Landing page URL sent as contentLandingPage with the LinkedIn call to action.
        - `cta_url` string: Landing page URL sent as contentLandingPage with the LinkedIn call to action. Alias for content_landing_page.
        - `linkedin_cta_url` string: Landing page URL sent as contentLandingPage with the LinkedIn call to action. Alias for content_landing_page.
        - `media_alt_texts` object: Legacy map of source media URLs to alt text. Still accepted for backwards compatibility.
        - `alt_texts` object: Legacy map of source media URLs to alt text. Still accepted for backwards compatibility. Alias for media_alt_texts.
        - `media_accessibility` object[]: Ordered media accessibility entries: { index, asset_id?, source_url?, alt_text }. Preferred because identity survives platform media preparation.
          - `index` integer, required
          - `asset_id` string
          - `source_url` string, uri
          - `alt_text` string, required
      - object
        - `title` string, required: YouTube video title.
        - `youtube_title` string: YouTube video title. Alias for title.
        - `thumbnail_url` string: Custom YouTube thumbnail URL.
        - `privacy_status` 'public' | 'unlisted' | 'private': YouTube video visibility.
        - `privacy` 'public' | 'unlisted' | 'private': YouTube video visibility. Alias for privacy_status.
        - `made_for_kids` boolean: YouTube made-for-kids declaration.
        - `tags` string[]: YouTube tags.
        - `category_id` string: YouTube category ID.
        - `notify_subscribers` boolean: Notify subscribers when the video publishes (default true).
        - `add_shorts_hashtag` boolean: Append #Shorts to the description for Shorts-feed eligibility (vertical clips).
        - `ai_generated` boolean: Label the video as containing AI/synthetic media (containsSyntheticMedia).
        - `ai_disclosure` boolean: Label the video as containing AI/synthetic media (containsSyntheticMedia). Alias for ai_generated.
        - `brand_partner` string: Optional YouTube brandPartner channel ID (UC…) or handle (@…). Added to videos.insert part=brandPartner when set.
        - `brandPartner` string: Optional YouTube brandPartner channel ID (UC…) or handle (@…). Added to videos.insert part=brandPartner when set. Alias for brand_partner.
      - object
        - `board_id` string, required: Pinterest board ID from the pinterest.boards helper.
        - `pinterest_board_id` string: Pinterest board ID from the pinterest.boards helper. Alias for board_id.
        - `title` string: Pinterest Pin title.
        - `link` string: Destination URL for the Pin.
        - `destination_url` string: Destination URL for the Pin. Alias for link.
        - `cover_image_url` string: Required for video Pins: a stored, probe-verified JPEG or PNG cover URL (20 MiB maximum).
        - `video_cover_url` string: Required for video Pins: a stored, probe-verified JPEG or PNG cover URL (20 MiB maximum). Alias for cover_image_url.
        - `pinterest_cover_image_url` string: Required for video Pins: a stored, probe-verified JPEG or PNG cover URL (20 MiB maximum). Alias for cover_image_url.
        - `ai_generated` boolean: Label the Pin as AI-modified (ai_disclosures).
        - `ai_disclosure` boolean: Label the Pin as AI-modified (ai_disclosures). Alias for ai_generated.
        - `product_tags` unknown[]: Optional product tags on POST /v5/pins (product_id, optional x/y). Existing pins:write. Pin note is not written.
          - unknown
        - `media_alt_texts` object: Legacy map of source media URLs to alt text. Still accepted for backwards compatibility.
        - `alt_texts` object: Legacy map of source media URLs to alt text. Still accepted for backwards compatibility. Alias for media_alt_texts.
        - `media_accessibility` object[]: Ordered media accessibility entries: { index, asset_id?, source_url?, alt_text }. Preferred because identity survives platform media preparation.
          - `index` integer, required
          - `asset_id` string
          - `source_url` string, uri
          - `alt_text` string, required
      - object
        - `reply_control` 'everyone' | 'accounts_you_follow' | 'mentioned_only' | 'followers_only' | 'parent_post_author_only': Threads reply control setting.
        - `threads_reply_control` 'everyone' | 'accounts_you_follow' | 'mentioned_only' | 'followers_only' | 'parent_post_author_only': Threads reply control setting. Alias for reply_control.
        - `poll` object: Threads poll: { options (2-4) }. Text-only, fixed 24h duration.
        - `threads_poll` object: Threads poll: { options (2-4) }. Text-only, fixed 24h duration. Alias for poll.
        - `topic_tag` string: A single Threads topic tag (1-50 chars, no periods/ampersands).
        - `threads_topic_tag` string: A single Threads topic tag (1-50 chars, no periods/ampersands). Alias for topic_tag.
        - `text_attachment` object: Long-form Threads text attachment.
        - `threads_text_attachment` object: Long-form Threads text attachment. Alias for text_attachment.
        - `share_to_instagram` boolean: Also share the published post as a Story to the Instagram account linked to the Threads profile. Requires a linked Instagram account and sharing permission. The Threads post can publish even if Story sharing fails.
        - `threads_share_to_instagram` boolean: Also share the published post as a Story to the Instagram account linked to the Threads profile. Requires a linked Instagram account and sharing permission. The Threads post can publish even if Story sharing fails. Alias for share_to_instagram.
        - `is_ghost_post` boolean: Publish as a Threads ghost post. Text-only.
        - `threads_is_ghost_post` boolean: Publish as a Threads ghost post. Text-only. Alias for is_ghost_post.
        - `is_spoiler` boolean: Mark the Threads post as a spoiler (full-caption text entity and/or is_spoiler_media).
        - `threads_is_spoiler` boolean: Mark the Threads post as a spoiler (full-caption text entity and/or is_spoiler_media). Alias for is_spoiler.
        - `is_spoiler_media` boolean: Set is_spoiler_media on the Threads container when media is attached.
        - `threads_is_spoiler_media` boolean: Set is_spoiler_media on the Threads container when media is attached. Alias for is_spoiler_media.
        - `text_entities` unknown[]: Threads text_entities, for example spoiler ranges with entity_type, offset, and length.
          - unknown
        - `threads_text_entities` unknown[]: Threads text_entities, for example spoiler ranges with entity_type, offset, and length. Alias for text_entities.
          - unknown
        - `enable_reply_approvals` boolean: Require approval before replies appear (enable_reply_approvals).
        - `threads_enable_reply_approvals` boolean: Require approval before replies appear (enable_reply_approvals). Alias for enable_reply_approvals.
        - `gif_attachment` object: GIPHY gif_attachment: { gif_id, provider: "GIPHY" }. Tenor is not supported.
        - `threads_gif_attachment` object: GIPHY gif_attachment: { gif_id, provider: "GIPHY" }. Tenor is not supported. Alias for gif_attachment.
        - `media_alt_texts` object: Legacy map of source media URLs to alt text. Still accepted for backwards compatibility.
        - `alt_texts` object: Legacy map of source media URLs to alt text. Still accepted for backwards compatibility. Alias for media_alt_texts.
        - `media_accessibility` object[]: Ordered media accessibility entries: { index, asset_id?, source_url?, alt_text }. Preferred because identity survives platform media preparation.
          - `index` integer, required
          - `asset_id` string
          - `source_url` string, uri
          - `alt_text` string, required
      - object
        - `post_type` 'STANDARD' | 'EVENT' | 'OFFER': Google Business Profile post type.
        - `topic_type` 'STANDARD' | 'EVENT' | 'OFFER': Google Business Profile post type. Alias for post_type.
        - `event` object: Event title and start/end date/time.
        - `offer` object: Offer coupon, redeem URL, and terms.
        - `cta` object: CTA type and URL.
        - `recurrence` object: EVENT/OFFER recurrenceInfo: { type: DAILY|WEEKLY|MONTHLY, series_end_time? }. Keeps one-off scheduledTime.
        - `recurrenceInfo` object: EVENT/OFFER recurrenceInfo: { type: DAILY|WEEKLY|MONTHLY, series_end_time? }. Keeps one-off scheduledTime. Alias for recurrence.
      - object
        - `parse_mode` 'HTML' | 'MarkdownV2': Telegram caption parse mode when supported.
        - `disable_web_page_preview` boolean: Disable link previews for text posts.
        - `poll` object: Telegram native poll: { question, options (2-10), allows_multiple_answers? }.
        - `telegram_poll` object: Telegram native poll: { question, options (2-10), allows_multiple_answers? }. Alias for poll.
        - `buttons` unknown[]: Inline CTA buttons: [{ text, url }] (up to 3).
          - unknown
        - `telegram_buttons` unknown[]: Inline CTA buttons: [{ text, url }] (up to 3). Alias for buttons.
          - unknown
        - `video_cover_url` string: Cover image URL for sendVideo (Bot API cover).
        - `cover_url` string: Cover image URL for sendVideo (Bot API cover). Alias for video_cover_url.
        - `telegram_video_cover_url` string: Cover image URL for sendVideo (Bot API cover). Alias for video_cover_url.
        - `start_timestamp` number: Video start timestamp in seconds for sendVideo (Bot API start_timestamp).
        - `telegram_start_timestamp` number: Video start timestamp in seconds for sendVideo (Bot API start_timestamp). Alias for start_timestamp.
        - `is_live_photo` boolean: Send as sendLivePhoto when both a still image and a video are attached.
        - `telegram_is_live_photo` boolean: Send as sendLivePhoto when both a still image and a video are attached. Alias for is_live_photo.
      - object
        - `langs` string[]: Language tags for the Bluesky post.
        - `content_label` 'sexual' | 'nudity' | 'porn' | 'graphic-media': Self-applied content warning (tap-to-reveal).
        - `content_warning` 'sexual' | 'nudity' | 'porn' | 'graphic-media': Self-applied content warning (tap-to-reveal). Alias for content_label.
        - `tags` string[]: Up to 8 hidden discovery tags (separate from in-text hashtags).
        - `bluesky_tags` string[]: Up to 8 hidden discovery tags (separate from in-text hashtags). Alias for tags.
        - `quote_url` string: A Bluesky post URL (or AT-URI) to quote.
        - `quote` string: A Bluesky post URL (or AT-URI) to quote. Alias for quote_url.
        - `bluesky_quote_url` string: A Bluesky post URL (or AT-URI) to quote. Alias for quote_url.
        - `disable_quotes` boolean: Prevent others from quote-posting this post (postgate).
        - `media_alt_texts` object: Legacy map of source media URLs to alt text. Still accepted for backwards compatibility.
        - `alt_texts` object: Legacy map of source media URLs to alt text. Still accepted for backwards compatibility. Alias for media_alt_texts.
        - `media_accessibility` object[]: Ordered media accessibility entries: { index, asset_id?, source_url?, alt_text }. Preferred because identity survives platform media preparation.
          - `index` integer, required
          - `asset_id` string
          - `source_url` string, uri
          - `alt_text` string, required
      - object
        - `media_alt_texts` object: Legacy map of source media URLs to alt text. Still accepted for backwards compatibility.
        - `alt_texts` object: Legacy map of source media URLs to alt text. Still accepted for backwards compatibility. Alias for media_alt_texts.
        - `media_accessibility` object[]: Ordered media accessibility entries: { index, asset_id?, source_url?, alt_text }. Preferred because identity survives platform media preparation.
          - `index` integer, required
          - `asset_id` string
          - `source_url` string, uri
          - `alt_text` string, required
      - object
        - `markdown` boolean: Send the caption as a Block Kit markdown block on chat.postMessage.
        - `slack_markdown` boolean: Send the caption as a Block Kit markdown block on chat.postMessage. Alias for markdown.
        - `blocks` unknown[]: Optional Block Kit blocks (markdown, card, or carousel) passed to chat.postMessage. File upload still uses getUploadURLExternal.
          - unknown
        - `slack_blocks` unknown[]: Optional Block Kit blocks (markdown, card, or carousel) passed to chat.postMessage. File upload still uses getUploadURLExternal. Alias for blocks.
          - unknown
      - object
        - `visibility` 'public' | 'unlisted' | 'private': Status visibility (private means followers only).
        - `mastodon_visibility` 'public' | 'unlisted' | 'private': Status visibility (private means followers only). Alias for visibility.
        - `spoiler_text` string: Content warning shown before the post is revealed (marks media sensitive).
        - `content_warning` string: Content warning shown before the post is revealed (marks media sensitive). Alias for spoiler_text.
        - `mastodon_spoiler_text` string: Content warning shown before the post is revealed (marks media sensitive). Alias for spoiler_text.
        - `language` string: ISO 639 language code for the status.
        - `mastodon_language` string: ISO 639 language code for the status. Alias for language.
        - `quoted_status_id` string: Mastodon status ID to quote (4.5+ quoted_status_id).
        - `quote_id` string: Mastodon status ID to quote (4.5+ quoted_status_id). Alias for quoted_status_id.
        - `mastodon_quoted_status_id` string: Mastodon status ID to quote (4.5+ quoted_status_id). Alias for quoted_status_id.
        - `poll` object: Mastodon poll: { options (2-4), expires_in seconds, multiple? }. Media and a poll can be combined on Mastodon 4.6+.
        - `mastodon_poll` object: Mastodon poll: { options (2-4), expires_in seconds, multiple? }. Media and a poll can be combined on Mastodon 4.6+. Alias for poll.
        - `media_alt_texts` object: Legacy map of source media URLs to alt text. Still accepted for backwards compatibility.
        - `alt_texts` object: Legacy map of source media URLs to alt text. Still accepted for backwards compatibility. Alias for media_alt_texts.
        - `media_accessibility` object[]: Ordered media accessibility entries: { index, asset_id?, source_url?, alt_text }. Preferred because identity survives platform media preparation.
          - `index` integer, required
          - `asset_id` string
          - `source_url` string, uri
          - `alt_text` string, required
      - object
        - `title` string: Article title. Falls back to the first line of the caption.
        - `devto_title` string: Article title. Falls back to the first line of the caption. Alias for title.
        - `tags` string[]: Up to 4 tags (lowercase alphanumeric).
        - `devto_tags` string[]: Up to 4 tags (lowercase alphanumeric). Alias for tags.
        - `canonical_url` string: Canonical URL when cross-posting from your own blog.
        - `media_alt_texts` object: Legacy map of source media URLs to alt text. Still accepted for backwards compatibility.
        - `alt_texts` object: Legacy map of source media URLs to alt text. Still accepted for backwards compatibility. Alias for media_alt_texts.
        - `media_accessibility` object[]: Ordered media accessibility entries: { index, asset_id?, source_url?, alt_text }. Preferred because identity survives platform media preparation.
          - `index` integer, required
          - `asset_id` string
          - `source_url` string, uri
          - `alt_text` string, required
      - object
        - `title` string: Post title. Falls back to the first line of the caption.
        - `hashnode_title` string: Post title. Falls back to the first line of the caption. Alias for title.
        - `tags` string[]: Up to 4 tags (lowercase alphanumeric).
        - `hashnode_tags` string[]: Up to 4 tags (lowercase alphanumeric). Alias for tags.
        - `publication_id` string: Target publication. Defaults to the account blog captured at connect time.
        - `media_alt_texts` object: Legacy map of source media URLs to alt text. Still accepted for backwards compatibility.
        - `alt_texts` object: Legacy map of source media URLs to alt text. Still accepted for backwards compatibility. Alias for media_alt_texts.
        - `media_accessibility` object[]: Ordered media accessibility entries: { index, asset_id?, source_url?, alt_text }. Preferred because identity survives platform media preparation.
          - `index` integer, required
          - `asset_id` string
          - `source_url` string, uri
          - `alt_text` string, required
      - object
        - `title` string: Post title. Falls back to the first line of the caption.
        - `wordpress_title` string: Post title. Falls back to the first line of the caption. Alias for title.
        - `media_alt_texts` object: Legacy map of source media URLs to alt text. Still accepted for backwards compatibility.
        - `alt_texts` object: Legacy map of source media URLs to alt text. Still accepted for backwards compatibility. Alias for media_alt_texts.
        - `media_accessibility` object[]: Ordered media accessibility entries: { index, asset_id?, source_url?, alt_text }. Preferred because identity survives platform media preparation.
          - `index` integer, required
          - `asset_id` string
          - `source_url` string, uri
          - `alt_text` string, required
      - object
        - `community` string, required: Target community, e.g. technology or technology@lemmy.world.
        - `lemmy_community` string: Target community, e.g. technology or technology@lemmy.world. Alias for community.
        - `title` string: Post title. Falls back to the first line of the caption.
        - `lemmy_title` string: Post title. Falls back to the first line of the caption. Alias for title.
        - `url` string: Link post URL. Defaults to the first attached image.
        - `lemmy_url` string: Link post URL. Defaults to the first attached image. Alias for url.
        - `nsfw` boolean: Mark the post NSFW.
        - `media_alt_texts` object: Legacy map of source media URLs to alt text. Still accepted for backwards compatibility.
        - `alt_texts` object: Legacy map of source media URLs to alt text. Still accepted for backwards compatibility. Alias for media_alt_texts.
        - `media_accessibility` object[]: Ordered media accessibility entries: { index, asset_id?, source_url?, alt_text }. Preferred because identity survives platform media preparation.
          - `index` integer, required
          - `asset_id` string
          - `source_url` string, uri
          - `alt_text` string, required
  - `reel_cover_url` string, nullable
  - `reel_cover_method` string, nullable
  - `reel_thumb_offset` number, nullable

## Response `200`

Post updated successfully

- PostResponse
  - `post` Post, required
    - `id` integer, required
    - `content` string, nullable
    - `scheduled_at` string, date-time, required
    - `social_account_id` integer, required
    - `media_url` string, nullable
    - `media_urls` string[], nullable
    - `status` string, required
    - `post_type` string, nullable
    - `platform_post_url` string, nullable
    - `published_at` string, date-time, nullable
    - `metadata` object, nullable
    - `reel_cover_url` string, nullable
    - `reel_cover_method` string, nullable
    - `reel_thumb_offset` number, nullable
    - `created_at` string, date-time, required: When the post was created (ISO 8601 with time zone). Read-only.
    - `updated_at` string, date-time, required
    - `created_by` object: Who or what created the post. Read-only. Any field is null when it was never recorded: posts created before the creation channel was tracked have a null source.
      - `user_id` string, uuid, nullable, required: The posterly account the post was created under.
      - `name` string, nullable, required: That account's full name, falling back to its username, then its email address. Filled in by GET /api/v1/posts, GET /api/v1/posts/{id}, and PATCH /api/v1/posts/{id}; null elsewhere or when unknown.
      - `source` string, nullable, required: How the post was created, for example dashboard, api_v1, mcp_http, mcp_stdio, bulk_upload, autopublisher, weekly_pack.
      - `source_label` string, nullable, required: A readable label for source, for example Dashboard, REST API, MCP.
    - `brand_id` string, uuid, nullable: The assigned brand/client, matching the id from GET /api/v1/brands. Read-only.
    - `content_plan_id` string, uuid, nullable: Read-only.
    - `workspace_id` string, uuid, nullable: The workspace this post belongs to. Read-only; null only for legacy posts created before workspaces.
    - `approval` object: Client review status. Cannot be set through POST or PATCH. Change it with POST /api/v1/posts/{id}/approval (workspace owner or admin only).
      - `status` 'none' | 'pending_client' | 'approved' | 'changes_requested' | 'rejected', required
      - `asset_status` 'none' | 'pending_client' | 'approved' | 'changes_requested' | 'rejected', required
      - `caption_status` 'none' | 'pending_client' | 'approved' | 'changes_requested' | 'rejected', required
      - `waiting_on` 'client' | 'team', nullable, required: 'client' when status is pending_client, 'team' when changes_requested or rejected, null otherwise.
      - `pending_client_approval` boolean, required: True only when status is pending_client.
      - `requested_at` string, date-time, nullable, required
      - `completed_at` string, date-time, nullable, required

## Other responses

- `400`: Cannot update current post state
- `401`: Invalid or missing API key
- `404`: Resource not found
- `429`: Too many requests

---

[API](https://skmtc.dev/poster/apis/posterly-api.md) · [All operations](https://skmtc.dev/poster/apis/posterly-api/llms.txt) · [OpenAPI document](https://skmtc.dev/poster/apis/posterly-api/revisions/60be02a61f95?raw)
