---
title: "Edit a draft or scheduled post (only sent fields are touched)"
method: PATCH
path: "/posts/{id}"
tags: ["Posts"]
---

# Edit a draft or scheduled post (only sent fields are touched)

`PATCH /posts/{id}`

## Request

- Base URL: `https://api.posteahora.com/functions/v1/api`
- URL: `https://api.posteahora.com/functions/v1/api/posts/{id}`
- Auth: HTTP bearer
- TypeScript: <https://skmtc.dev/posteahora/apis/posteahora-public-api/docs/posts/:id/patch.ts> (a function with typed inputs; its response is checked against the schema)

## Request body

- UpdatePostRequest: Edit a draft or scheduled post. Only sent fields are touched.
  - `title` string
  - `caption` string
  - `hashtags` string[]
  - `mediaUrls` string[]
  - `mediaType` 'image' | 'video'
  - `postType` 'post' | 'reel' | 'story'
  - `platforms` string[]
  - `connectedAccountId` string
  - `platformOptions` PlatformOptions: Per-network settings, keyed by platform id.
    - `youtube` YouTubeOptions: The video description is the post caption (platformCaptions.youtube, ≤5000 chars). The video title is the required `title` field. There is no "Shorts" flag — a vertical clip ≤3 min is auto-classified as a Short.
      - `title` string, required
      - `categoryId` string, required
      - `madeForKids` boolean, required
      - `privacyStatus` 'public' | 'unlisted' | 'private'
      - `tags` string[]
      - `defaultLanguage` string
      - `containsSyntheticMedia` boolean
      - `embeddable` boolean
      - `publicStatsViewable` boolean
      - `license` 'youtube' | 'creativeCommon'
      - `thumbnailUrl` string, uri
    - `tiktok` TikTokOptions
      - `privacyLevel` 'PUBLIC_TO_EVERYONE' | 'MUTUAL_FOLLOW_FRIENDS' | 'FOLLOWER_OF_CREATOR' | 'SELF_ONLY', required
      - `disableComment` boolean, required
      - `brandContentToggle` boolean, required
      - `brandOrganicToggle` boolean, required
      - `isAigc` boolean, required
      - `postMode` 'DIRECT_POST' | 'MEDIA_UPLOAD'
      - `disableDuet` boolean: video only
      - `disableStitch` boolean: video only
      - `videoCoverTimestampMs` number: video only
      - `autoAddMusic` boolean: photo only
      - `photoCoverIndex` number: photo only
      - `photoTitle` string: photo only
    - `instagram` InstagramOptions: Set postType "reel" (top level) for a Reel, "story" for a Story.
      - `shareToFeed` boolean
      - `coverUrl` string, uri
      - `thumbOffsetMs` number
      - `audioName` string
      - `collaborators` string[]
      - `locationId` string
      - `userTags` object[]
        - `username` string, required
        - `x` number
        - `y` number
      - `altText` string
      - `isAiGenerated` boolean
      - `isTrialReel` boolean: reel only
      - `trialGraduationStrategy` 'MANUAL' | 'SS_PERFORMANCE': reel only
    - `threads` ThreadsOptions
      - `replyControl` 'everyone' | 'accounts_you_follow' | 'mentioned_only' | 'parent_post_author_only' | 'followers_only'
      - `topic` string
      - `altText` string
      - `linkAttachment` string, uri
      - `quotePostId` string
      - `locationId` string
      - `allowlistedCountryCodes` string[]
      - `chainItems` object[]
        - `text` string, required
        - `mediaUrl` string, uri
        - `mediaType` 'image' | 'video'
        - `altText` string
    - `bluesky` BlueskyOptions
      - `langs` string[]
    - `mastodon` MastodonOptions
      - `visibility` 'public' | 'unlisted' | 'private' | 'direct'
      - `spoilerText` string
      - `sensitive` boolean
      - `language` string
    - `telegram` TelegramOptions
      - `disableNotification` boolean
      - `protectContent` boolean
    - `discord` DiscordOptions
      - `channelId` string
    - `pinterest` PinterestOptions: boardId is REQUIRED and validated on create (400 without it). A Pin needs at least one image; 2–5 images make a carousel.
      - `boardId` string, required: Board id from GET /accounts/{id}/boards
      - `boardName` string: Display only
      - `title` string
      - `link` string, uri
      - `altText` string
      - `coverUrl` string, uri: Video Pins: 2:3 cover image URL
      - `thumbOffsetMs` integer: Video Pins: keyframe used as cover when coverUrl is absent (ms)
  - `status` 'draft' | 'scheduled'
  - `scheduledAt` string, date-time

## Response `200`

OK

- object
  - `post` Post
    - `id` string, uuid
    - `title` string, nullable
    - `caption` string, nullable
    - `platforms` string[]
    - `status` 'draft' | 'scheduled' | 'queued' | 'published' | 'partial_published' | 'failed'
    - `scheduled_at` string, date-time, nullable
    - `published_at` string, date-time, nullable
    - `media_urls` string[]
    - `media_type` 'image' | 'video' | 'null', nullable
    - `connected_account_id` string, uuid, nullable
    - `platform_results` PlatformResult[]
      - `platform` string, required
      - `success` boolean, required
      - `error` string
      - `remote_post_id` string
      - `remote_publish_id` string
      - `remote_permalink` string, uri
    - `created_at` string, date-time

## Other responses

- `400`: Invalid request
- `404`: Resource not found (or not in the key's workspace)

---

[API](https://skmtc.dev/posteahora/apis/posteahora-public-api.md) - [All operations](https://skmtc.dev/posteahora/apis/posteahora-public-api/llms.txt) - [OpenAPI document](https://skmtc.dev/posteahora/apis/posteahora-public-api/revisions/552a8eb6c30f?raw)
