> ## Documentation Index
> Fetch the complete documentation index at: https://docs.trypost.it/llms.txt
> Use this file to discover all available pages before exploring further.

# Update post

> Update a post's content, schedule, enabled platforms, or labels — and trigger publishing.

## Request

<ParamField path="post" type="string" required>
  The post ID.
</ParamField>

<ParamField body="status" type="string" required>
  The post status. One of:

  * `draft` — keep as draft
  * `scheduled` — schedule for the time given in `scheduled_at` (must be in the future)
  * `publishing` — **publish immediately**: dispatches the publish job to all enabled platforms

  Cross-validated: `scheduled` requires a `scheduled_at` in the future.
</ParamField>

<ParamField body="content" type="string">
  The post caption/text body.
</ParamField>

<ParamField body="media" type="array">
  Media items to associate with the post. Most callers upload first via [`POST /posts/{post}/media`](/api-reference/endpoint/upload-media) (file) or [`POST /posts/{post}/media/from-url`](/api-reference/endpoint/attach-media-from-url) (URL) and let those endpoints append to `media[]` directly.
</ParamField>

<ParamField body="platforms" type="array">
  An array of platform entries to enable. Any platform NOT listed here will be **disabled**. Pass an empty array to disable all.

  <Expandable>
    <ParamField body="id" type="string" required>
      The post\_platform entry ID (from `GET /posts/{id}` or `GET /posts`).
    </ParamField>

    <ParamField body="content_type" type="string">
      Override the content\_type for this platform (e.g. `linkedin_carousel` instead of the default `linkedin_post`). Use [`GET /content-types`](/api-reference/endpoint/list-content-types) to discover valid values. Cross-validated against the platform of the underlying social account.
    </ParamField>

    <ParamField body="meta" type="object">
      Per-platform settings, **merged** into the platform's existing `meta` (unset a key by sending `null`). Only the keys below are accepted — unknown keys are dropped:

      * **Instagram / Facebook** — `aspect_ratio` (`1:1`, `4:5`, `16:9`, `original`).
      * **Pinterest** — `board_id` (**required to publish**). Fetch board IDs from Pinterest's `/v5/boards` endpoint or pick one in the dashboard's Accounts page.
      * **TikTok** — `privacy_level` (**required to publish**; `PUBLIC_TO_EVERYONE`, `MUTUAL_FOLLOW_FRIENDS`, `FOLLOWER_OF_CREATOR`, `SELF_ONLY`) plus the booleans `allow_comments`, `allow_duet`, `allow_stitch`, `auto_add_music`, `is_aigc`, `disclose`, `brand_content_toggle`, `brand_organic_toggle`.
      * **Discord** — `channel_id` (**required to publish** — the target channel in the server), `channel_name` (display only), `mentions` (array of `{ token, label }`), `embeds` (up to 10 of `{ title, description, url, image, color }`; `color` is a `#RRGGBB` hex).

      Required-to-publish keys are enforced by this endpoint when `status` is `scheduled` or `publishing`: a missing one returns `422` with an error on `platforms.{i}.meta.{field}` (e.g. `platforms.0.meta.channel_id`). Drafts are not checked.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="scheduled_at" type="string">
  ISO 8601 datetime. Required when `status=scheduled`.
</ParamField>

<ParamField body="label_ids" type="array">
  An array of label UUIDs to assign to the post. Replaces existing labels.
</ParamField>

## Response

Returns the updated post. Returns `422` with `{ "message": "Cannot edit a published post." }` if the post has already been published.

<RequestExample>
  ```bash theme={null}
  curl -X PUT https://app.trypost.it/api/posts/9f1a2b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "status": "publishing",
      "content": "Launching now!",
      "platforms": [
        { "id": "a1b2c3d4-e5f6-7a8b-9c0d-1e2f3a4b5c6d", "content_type": "linkedin_post" }
      ],
      "label_ids": ["c3d4e5f6-a7b8-9c0d-1e2f-3a4b5c6d7e8f"]
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json theme={null}
  {
    "id": "9f1a2b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
    "content": "Launching now!",
    "media": [],
    "status": "publishing",
    "scheduled_at": "2025-01-15 10:30:00",
    "published_at": null,
    "platforms": [
      {
        "id": "a1b2c3d4-e5f6-7a8b-9c0d-1e2f3a4b5c6d",
        "platform": "linkedin",
        "content_type": "linkedin_post",
        "status": "publishing",
        "enabled": true,
        "platform_url": null,
        "published_at": null,
        "error_message": null,
        "display_name": "John Doe",
        "display_username": "johndoe",
        "display_avatar": "https://media.licdn.com/.../avatar.jpg",
        "social_account": {
          "id": "b2c3d4e5-f6a7-8b9c-0d1e-2f3a4b5c6d7e",
          "platform": "linkedin",
          "display_name": "John Doe",
          "username": "johndoe",
          "is_active": true,
          "status": "connected"
        }
      }
    ],
    "labels": [
      {
        "id": "c3d4e5f6-a7b8-9c0d-1e2f-3a4b5c6d7e8f",
        "name": "Product Launch",
        "color": "#4f46e5",
        "created_at": "2025-01-10 08:00:00",
        "updated_at": "2025-01-10 08:00:00"
      }
    ],
    "created_at": "2025-01-14 09:00:00",
    "updated_at": "2025-01-14 09:30:00"
  }
  ```
</ResponseExample>

## Tips

* To publish an existing draft, send only `{ "status": "publishing" }` — content/platforms already saved are kept.
* To schedule, send `{ "status": "scheduled", "scheduled_at": "2025-12-31T15:30:00Z" }`.
* To toggle which platforms are active without changing content, send only the `platforms[]` array.
