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

# Create Post

> Create a new social media post with content, media, and scheduling options

## Create Post

Creates a new post that can be scheduled or published immediately across multiple social media platforms. The post can include text content, media attachments, and platform-specific settings.

### Request

<ParamField body="workspace_id" type="integer" required>
  The ID of the workspace where the post will be created
</ParamField>

<ParamField body="labels" type="string[]">
  Optional array of label IDs to apply to this post
</ParamField>

<ParamField body="content" type="object[]" required>
  Array of content objects (threads). Each object can contain text and media. At least one content item with text or media is required.

  <Expandable title="Content Object">
    <ParamField body="text" type="string">
      The text content for this post
    </ParamField>

    <ParamField body="media" type="string[]">
      Attachments for this thread. Each item is either a **string** (public HTTPS URL to an image or video) or a (media library `id` from [`POST /media/upload/file`](/api-reference/media/upload-file) or [`POST /media/upload/url`](/api-reference/media/upload-url), same `workspace_id`). You may mix URLs and ids in one array. See [Media overview](/api-reference/media/overview).
    </ParamField>

    <ParamField body="cover_image" type="object">
      Optional cover/thumbnail for video posts. Only the **first** content item's `cover_image` is used when publishing. **Which field you use depends on the target platform** - see [Platform requirements](#platform-requirements-for-cover-images) below.

      <Expandable title="Cover Image Object">
        <ParamField body="thumbnail" type="string">
          **Custom cover image upload** - workspace media library **id** (image only) or public **HTTPS URL** to an image. Upload via [`POST /media/upload/file`](/api-reference/media/upload-file) or [`POST /media/upload/url`](/api-reference/media/upload-url). **Required for YouTube, Instagram, and Facebook video/Reels.** Not used on TikTok.
        </ParamField>

        <ParamField body="video_cover_timestamp_ms" type="integer">
          **Frame selection from the attached video** - timestamp in **milliseconds** (e.g. `2500` = 2.5 seconds). **TikTok only.** Custom thumbnail upload is not supported on TikTok.
        </ParamField>
      </Expandable>
    </ParamField>

    <ParamField body="is_first_comment" type="boolean">
      When `true`, this content item is **not** part of the main post body on platforms that support first comments. After the post publishes successfully, PostSyncer posts this text (and optional media) as the first comment on **Instagram, Facebook, LinkedIn, and YouTube**. Only one content item may set this. You must still include at least one non-first-comment content item for the main post. On other platforms in the same post (e.g. TikTok, Threads), this flag does not schedule a first comment — see [First comments](#first-comments).
    </ParamField>

    <ParamField body="first_comment_delay" type="integer">
      Minutes to wait after publish before posting the first comment. Defaults to `1` when `is_first_comment` is `true`. Max `10080` (7 days).
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="schedule_type" type="string" required>
  Type of scheduling. Must be one of:
  publish\_now, schedule, draft
</ParamField>

<ParamField body="schedule_for" type="object">
  Optional scheduling object used when `schedule_type` is `schedule`. Provide `{"date": "YYYY-MM-DD", "time": "HH:MM", "timezone": "..."}` to schedule for a specific date/time, or omit/leave empty to auto-schedule to the next available time slot

  <Expandable title="Schedule Object">
    <ParamField body="date" type="string" required>
      The date to schedule the post (YYYY-MM-DD format)
    </ParamField>

    <ParamField body="time" type="string" required>
      The time to schedule the post (HH:MM format in 24-hour)
    </ParamField>

    <ParamField body="timezone" type="string">
      Timezone for the scheduled time (defaults to workspace timezone)
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="repeatable" type="boolean">
  Whether the post should be repeated
</ParamField>

<ParamField body="repeatable_times" type="integer">
  Number of times to repeat the post. Required if repeatable is true.
</ParamField>

<ParamField body="repeatable_gap" type="integer">
  Time gap between repeats. Required if repeatable is true.
</ParamField>

<ParamField body="repeatable_gap_unit" type="string">
  The unit for the repeatable gap. Must be one of: `minutes`, `hours`, `days`, `weeks`, `months`. Required if repeatable is true.
</ParamField>

<ParamField body="repeatable_accounts" type="integer[]">
  Optional. Only when `repeatable` is true: account IDs (in this `workspace_id`) to limit repeat scheduling to those accounts. Omit or empty for default behavior. To turn off repeat scheduling, send `repeatable: false` on [update post](/api-reference/posts/update).
</ParamField>

<Note>
  **[Auto plug](/api-reference/posts/auto-plug)**, **[comment moderation](/api-reference/posts/comment-moderation)**, and **[contact collection](/api-reference/posts/contact-collection)** each have a dedicated `PATCH` endpoint. Repeat scheduling uses `repeatable` / `repeatable_accounts` on create and update.
</Note>

<ParamField body="accounts" type="array">
  Array of account objects to publish to

  <Expandable title="Account Object">
    <ParamField body="id" type="integer" required>
      The ID of the social media account
    </ParamField>

    <ParamField body="settings" type="object">
      Platform-specific settings for this post. Optional except for Pinterest which requires a board\_id. The available settings depend on the platform:

      <Expandable title="Twitter/X Settings">
        <ParamField body="for_super_followers_only" type="boolean">
          Whether to restrict the post to super followers only (default: false)
        </ParamField>

        <ParamField body="reply_settings" type="string">
          Who can reply to the post. Options: 'everyone', 'following', 'mentioned\_users' (default: 'everyone')
        </ParamField>

        <ParamField body="quote_tweet_id" type="string">
          ID of the tweet to quote (optional)
        </ParamField>

        <ParamField body="reply" type="object">
          Reply settings object with 'in\_reply\_to\_tweet\_id' (optional)
        </ParamField>

        <ParamField body="community_id" type="string">
          ID of the community to post to (optional)
        </ParamField>

        <ParamField body="share_with_followers" type="boolean">
          Share community post with followers too.
        </ParamField>

        <ParamField body="text" type="string">
          Custom text content for Twitter (optional) - (This allows overriding the platform-specific text content)
        </ParamField>

        <ParamField body="poll" type="object">
          Poll settings with 'enabled', 'duration\_minutes', 'reply\_settings', and 'options' (optional)

          <Expandable title="Poll Settings">
            <ParamField body="enabled" type="boolean" />

            <ParamField body="duration_minutes" type="string" />

            <ParamField body="reply_settings" type="string">
              everyone, following, mentionedUsers
            </ParamField>

            <ParamField body="options" type="array">
              Poll options, array of text
            </ParamField>
          </Expandable>
        </ParamField>
      </Expandable>

      <Expandable title="Instagram Settings">
        <ParamField body="post_type" type="string">
          Type of post. Options: 'REELS', 'STORIES', 'POST' (default: 'REELS') (optional)
        </ParamField>

        <ParamField body="caption" type="string">
          Custom caption for Instagram (optional) - (This allows overriding the platform-specific text content)
        </ParamField>
      </Expandable>

      <Expandable title="Facebook Settings">
        <ParamField body="post_type" type="string">
          Type of post. Options: 'REELS', 'STORIES', 'POST' (default: 'REELS') (optional)
        </ParamField>

        <ParamField body="title" type="string">
          Custom title for the Facebook post (optional) - (This allows overriding the platform-specific text content)
        </ParamField>

        <ParamField body="link" type="string">
          URL to attach to the post (optional)
        </ParamField>
      </Expandable>

      <Expandable title="LinkedIn Settings">
        <ParamField body="visibility" type="string">
          Post visibility. Options: 'PUBLIC', 'CONNECTIONS', 'LOGGED\_IN' (default: 'PUBLIC')
        </ParamField>

        <ParamField body="link" type="string">
          URL to attach to the post (optional)
        </ParamField>

        <ParamField body="title" type="string">
          Custom title for the LinkedIn post (optional) - (This allows overriding the platform-specific text content)
        </ParamField>
      </Expandable>

      <Expandable title="YouTube Settings">
        <ParamField body="video_type" type="string">
          Type of video. Options: 'video', 'short' (default: 'video')
        </ParamField>

        <ParamField body="title" type="string">
          Video title (optional)
        </ParamField>

        <ParamField body="description" type="string">
          Video description (optional) - (This allows overriding the platform-specific text content)
        </ParamField>

        <ParamField body="privacyStatus" type="string">
          Privacy status. Options: 'public', 'private', 'unlisted' (default: 'public')
        </ParamField>

        <ParamField body="tags" type="array">
          Array of tags for the video (optional)
        </ParamField>

        <ParamField body="embeddable" type="boolean">
          Whether the video can be embedded (default: true)
        </ParamField>

        <ParamField body="selfDeclaredMadeForKids" type="boolean">
          Whether the video is made for kids (default: false)
        </ParamField>

        <ParamField body="notifySubscribers" type="boolean">
          Whether to notify subscribers (default: true)
        </ParamField>

        <ParamField body="category_id" type="string">
          YouTube category ID
        </ParamField>
      </Expandable>

      <Expandable title="TikTok Settings">
        <ParamField body="privacy_level" type="string">
          Privacy level for the video (optional) PUBLIC\_TO\_EVERYONE, MUTUAL\_FOLLOW\_FRIENDS, FOLLOWER\_OF\_CREATOR, SELF\_ONLY
        </ParamField>

        <ParamField body="title" type="string">
          Video title (optional)- (This allows overriding the platform-specific text content)
        </ParamField>

        <ParamField body="description" type="string">
          Video description (optional) - (Only available when posting photos)
        </ParamField>

        <ParamField body="disable_comment" type="boolean">
          Whether to disable comments (optional)
        </ParamField>

        <ParamField body="disable_duet" type="boolean">
          Whether to disable duets (optional)
        </ParamField>

        <ParamField body="disable_stitch" type="boolean">
          Whether to disable stitches (optional)
        </ParamField>

        <ParamField body="brand_content_toggle" type="boolean">
          Whether to mark as brand content (optional)
        </ParamField>

        <ParamField body="brand_organic_toggle" type="boolean">
          Whether to mark as organic brand content (optional)
        </ParamField>

        <ParamField body="is_aigc" type="boolean">
          Whether the content is AI-generated (optional)
        </ParamField>

        <ParamField body="auto_add_music" type="boolean">
          Whether to auto-add music (optional)
        </ParamField>

        <ParamField body="post_mode" type="string">
          Enum of (optional):
          DIRECT\_POST: Directly post the content to TikTok account.
          MEDIA\_UPLOAD: Upload content to TikTok to complete the post using TikTok's editing flow. Users will receive an inbox notification.
        </ParamField>
      </Expandable>

      <Expandable title="Pinterest Settings">
        <ParamField body="board_id" type="string" required>
          ID of the board to pin to
        </ParamField>

        <ParamField body="link" type="string">
          URL to attach to the pin (optional)
        </ParamField>

        <ParamField body="title" type="string">
          Pin title (optional)
        </ParamField>

        <ParamField body="description" type="string">
          Pin description (optional) - (This allows overriding the platform-specific text content)
        </ParamField>

        <ParamField body="note" type="string">
          Pin note/description (optional)
        </ParamField>

        <ParamField body="published" type="boolean">
          Whether to publish the pin immediately (default: true)
        </ParamField>
      </Expandable>

      <Expandable title="Threads Settings">
        <ParamField body="title" type="string">
          Custom title for the Threads post (optional) - (This allows overriding the platform-specific text content)
        </ParamField>

        <ParamField body="link_attachment" type="string">
          URL to attach to the post (optional)
        </ParamField>
      </Expandable>

      <Expandable title="Telegram Settings">
        <ParamField body="title" type="string">
          Custom title for the Telegram message (optional) - (This allows overriding the platform-specific text content)
        </ParamField>

        <ParamField body="disable_notification" type="boolean">
          Whether to disable notifications (default: false)
        </ParamField>

        <ParamField body="protect_content" type="boolean">
          Whether to protect the content (default: false)
        </ParamField>
      </Expandable>

      <Expandable title="Bluesky Settings">
        <ParamField body="title" type="string">
          Custom title for the Bluesky post (optional) - (This allows overriding the platform-specific text content)
        </ParamField>

        <ParamField body="website_card" type="object">
          Website card settings with 'uri', 'title', and 'description' (optional)

          <Expandable title="Bluesky Settings Website Card">
            <ParamField body="uri" type="string" />

            <ParamField body="title" type="string" />

            <ParamField body="description" type="string" />
          </Expandable>
        </ParamField>
      </Expandable>
    </ParamField>
  </Expandable>
</ParamField>

<RequestExample>
  ```json theme={null}
  {
      "workspace_id": 12,
      "labels": [
          5
      ],
      "content": [
          {
              "text": "Check out our new reel!",
              "media": [
                  1842
              ],
              "cover_image": {
                  "thumbnail": 1843
              }
          },
          {
              "text": "Full lesson + tabs: https://jamfastguitar.com\n#guitar #practice",
              "is_first_comment": true,
              "first_comment_delay": 1
          }
      ],
      "schedule_type": "schedule",
      "schedule_for": {
          "date": "2025-07-05",
          "time": "23:00",
          "timezone": "Africa/Addis_Ababa"
      },
      "accounts": [
          {
              "id": 136,
              "settings": {
                  "for_super_followers_only": false,
                  "reply_settings": "everyone",
                  "quote_tweet_id": null,
                  "reply": {
                      "in_reply_to_tweet_id": null
                  },
                  "community_id": null,
                  "share_with_followers": true,
                  "text": null
              }
          }
      ]
  }
  ```
</RequestExample>

### Response

<ResponseField name="id" type="integer">
  Unique identifier for the created post
</ResponseField>

<ResponseField name="content" type="array">
  Array of content objects with text, media, optional `cover_image`, and optional first-comment fields (`is_first_comment`, `first_comment_delay`). Platform cover requirements: TikTok - `video_cover_timestamp_ms` only; YouTube, Instagram, Facebook - `thumbnail` only.
</ResponseField>

<ResponseField name="status" type="string">
  Status of the post (draft, scheduled, published, failed)
</ResponseField>

<ResponseField name="posted_on" type="array">
  Array of posted timestamps in workspace timezone
</ResponseField>

<ResponseField name="scheduled_at" type="string">
  Scheduled date and time in workspace timezone
</ResponseField>

<ResponseField name="repeatable" type="boolean">
  Whether the post is set to repeat
</ResponseField>

<ResponseField name="repeatable_times" type="integer">
  Number of times the post will repeat
</ResponseField>

<ResponseField name="repeatable_gap" type="integer">
  Gap between repeats
</ResponseField>

<ResponseField name="repeatable_gap_unit" type="string">
  Unit for the repeat gap (hours, days, weeks, months)
</ResponseField>

<ResponseField name="remaining_posts" type="integer">
  Number of remaining posts in the repeat sequence
</ResponseField>

<ResponseField name="workspace" type="object">
  Information about the post's workspace
</ResponseField>

<ResponseField name="labels" type="array">
  Array of labels attached to the post
</ResponseField>

<ResponseField name="platforms" type="array">
  Array of platform-specific post information
</ResponseField>

<ResponseField name="auto_plug" type="object | null">
  Auto plug configuration when enabled, or `null` when off. Update via [Update post auto plug](/api-reference/posts/auto-plug).
</ResponseField>

<ResponseField name="created_at" type="string">
  Creation timestamp in workspace timezone
</ResponseField>

<ResponseField name="updated_at" type="string">
  Last update timestamp in workspace timezone
</ResponseField>

<ResponseExample>
  ```json theme={null}
  { 
    "id": 749,
    "content": [
        {
            "text": "Post Once. Publissh everywhere",
            "media": [
                {
                    "id": 1672,
                    "name": "banner.png",
                    "url": "https://postsyncer.com/images/og/banner.png?v2",
                    "type": "image/png",
                    "size": 210537
                }
            ]
        }
    ],
    "status": "SCHEDULED",
    "posted_on": [],
    "scheduled_at": "2025-07-05 23:00 PM",
    "repeatable": null,
    "repeatable_times": null,
    "repeatable_gap": null,
    "repeatable_gap_unit": null,
    "remaining_posts": null,
    "created_at": "2025-07-05 17:04 PM",
    "updated_at": "2025-07-05 17:04 PM",
    "workspace": {
        "id": 12,
        "name": "abdulmejidshemsuawel",
        "slug": "abdulmejidshemsuawel",
        "type": "PERSONAL",
        "logo": null,
        "timezone": "Africa/Addis_Ababa",
        "language": "en"
    },
    "labels": [
        {
            "id": 5,
            "name": "ol pasdm",
            "color": "#bf3434"
        }
    ],
    "platforms": [
        {
            "platform": "twitter",
            "posted_on": [],
            "status": "PENDING",
            "settings": {
                "for_super_followers_only": false,
                "reply_settings": "everyone",
                "quote_tweet_id": null,
                "reply": {
                    "in_reply_to_tweet_id": null
                },
                "community_id": null,
                "share_with_followers": true,
                "text": "",
                "poll": {
                    "enabled": false,
                    "duration_minutes": null,
                    "reply_settings": "everyone",
                    "options": null
                }
            }
        }
    ],
    "auto_plug": null 
  }
  ```
</ResponseExample>

### Code Examples

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://postsyncer.com/api/v1/posts" \
    -H "Authorization: Bearer YOUR_API_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "workspace_id": 12,
      "labels": [
        5
      ],
      "content": [
        {
          "text": "Post Once. Publissh everywhere",
          "media": [
            "https://postsyncer.com/images/og/banner.png?v2"
          ]
        }
      ],
      "schedule_type": "schedule",
      "schedule_for": {
        "date": "2025-07-05",
        "time": "23:00",
        "timezone": "Africa/Addis_Ababa"
      },
      "accounts": [
        {
          "id": 136,
          "settings": {
            "for_super_followers_only": false,
            "reply_settings": "everyone",
            "quote_tweet_id": null,
            "reply": {
              "in_reply_to_tweet_id": null
            },
            "community_id": null,
            "share_with_followers": true,
            "text": null
          }
        }
      ]
    }'
  ```

  ```javascript Node.js theme={null}
  const axios = require('axios');

  const createPost = async () => {
    try {
      const response = await axios.post('https://postsyncer.com/api/v1/posts', {
        workspace_id: 12,
        labels: [
          5
        ],
        content: [
          {
            text: 'Post Once. Publissh everywhere',
            media: [
              'https://postsyncer.com/images/og/banner.png?v2'
            ]
          }
        ],
        schedule_type: 'schedule',
        schedule_for: {
          date: '2025-07-05',
          time: '23:00',
          timezone: 'Africa/Addis_Ababa'
        },
        accounts: [
          {
            id: 136,
            settings: {
              for_super_followers_only: false,
              reply_settings: 'everyone',
              quote_tweet_id: null,
              reply: {
                in_reply_to_tweet_id: null
              },
              community_id: null,
              share_with_followers: true,
              text: null
            }
          }
        ]
      }, {
        headers: {
          'Authorization': 'Bearer YOUR_API_TOKEN',
          'Content-Type': 'application/json'
        }
      });
      
      console.log('Post created:', response.data);
    } catch (error) {
      console.error('Error creating post:', error.response?.data || error.message);
    }
  };

  createPost();
  ```

  ```php PHP theme={null}
  <?php

  $data = [
      'workspace_id' => 12,
      'labels' => [
          5
      ],
      'content' => [
          [
              'text' => 'Post Once. Publissh everywhere',
              'media' => [
                  'https://postsyncer.com/images/og/banner.png?v2'
              ]
          ]
      ],
      'schedule_type' => 'schedule',
      'schedule_for' => [
          'date' => '2025-07-05',
          'time' => '23:00',
          'timezone' => 'Africa/Addis_Ababa'
      ],
      'accounts' => [
          [
              'id' => 136,
              'settings' => [
                  'for_super_followers_only' => false,
                  'reply_settings' => 'everyone',
                  'quote_tweet_id' => null,
                  'reply' => [
                      'in_reply_to_tweet_id' => null
                  ],
                  'community_id' => null,
                  'share_with_followers': true,
                  'text' => null
              ]
          ]
      ]
  ];

  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, 'https://postsyncer.com/api/v1/posts');
  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'Authorization: Bearer YOUR_API_TOKEN',
      'Content-Type: application/json'
  ]);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

  $response = curl_exec($ch);
  $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  curl_close($ch);

  if ($httpCode === 201) {
      $post = json_decode($response, true);
      echo "Post created: " . $post['id'];
  } else {
      echo "Error: " . $response;
  }
  ?>
  ```

  ```python Python theme={null}
  import requests
  import json

  data = {
      'workspace_id': 12,
      'labels': [
          5
      ],
      'content': [
          {
              'text': 'Post Once. Publissh everywhere',
              'media': [
                  'https://postsyncer.com/images/og/banner.png?v2'
              ]
          }
      ],
      'schedule_type': 'schedule',
      'schedule_for': {
          'date': '2025-07-05',
          'time': '23:00',
          'timezone': 'Africa/Addis_Ababa'
      },
      'accounts': [
          {
              'id': 136,
              'settings': {
                  'for_super_followers_only': False,
                  'reply_settings': 'everyone',
                  'quote_tweet_id': None,
                  'reply': {
                      'in_reply_to_tweet_id': None
                  },
                  'community_id': None,
                  'share_with_followers': true,
                  'text': None
              }
          }
      ]
  }

  headers = {
      'Authorization': 'Bearer YOUR_API_TOKEN',
      'Content-Type': 'application/json'
  }

  response = requests.post(
      'https://postsyncer.com/api/v1/posts',
      json=data,
      headers=headers
  )

  if response.status_code == 201:
      post = response.json()
      print(f"Post created: {post['id']}")
  else:
      print(f"Error: {response.status_code}")
      print(response.text)
  ```
</CodeGroup>

### Platform-Specific Settings

Each social media platform supports different settings that allow you to customize how your post appears and behaves. These settings are specified in the `settings` object for each account in the `accounts` array.

#### Twitter/X Settings

* **for\_super\_followers\_only**: Restrict post visibility to super followers

* **reply\_settings**: Control who can reply ('everyone', 'following', 'mentioned\_users')

* **quote\_tweet\_id**: Quote an existing tweet

* **reply**: Reply to a specific tweet

* **community\_id**: Post to a specific community

* **share\_with\_followers**: Share community post with followers too

* **text**: Override the main text content for Twitter

* **poll**: Create a poll with options and duration

#### Instagram Settings

* **post\_type**: Choose between 'REELS', 'STORIES', or 'POST'
* **caption**: Custom caption with hashtags and mentions

#### Facebook Settings

* **title**: Custom title for the post
* **link**: Attach a URL to the post

#### LinkedIn Settings

* **visibility**: Control post visibility ('PUBLIC', 'CONNECTIONS', 'LOGGED\_IN')
* **link**: Attach a URL to the post
* **title**: Custom title for the post

#### YouTube Settings

* **video\_type**: Choose between 'video' or 'short'
* **title**: Video title
* **description**: Video description
* **privacyStatus**: Set privacy ('public', 'private', 'unlisted')
* **tags**: Array of tags for better discoverability
* **embeddable**: Allow video embedding
* **selfDeclaredMadeForKids**: Mark as content for children
* **notifySubscribers**: Send notifications to subscribers
* **category\_id**: YouTube category

#### TikTok Settings

* **privacy\_level**: Set video privacy (PUBLIC\_TO\_EVERYONE, MUTUAL\_FOLLOW\_FRIENDS, FOLLOWER\_OF\_CREATOR, SELF\_ONLY)
* **title**: Video title
* **description**: Video description
* **disable\_comment**: Turn off comments
* **disable\_duet**: Disable duet feature
* **disable\_stitch**: Disable stitch feature
* **brand\_content\_toggle**: Mark as brand content
* **brand\_organic\_toggle**: Mark as organic brand content
* **is\_aigc**: Indicate AI-generated content
* **auto\_add\_music**: Automatically add music
* **post\_mode**: Enum: DIRECT\_POST (post directly) | MEDIA\_UPLOAD (upload for user to finish in TikTok)

#### Pinterest Settings

* **board\_id**: Specify which board to pin to
* **link**: Attach a URL to the pin
* **title**: Pin title
* **description**: Pin description
* **note**: Additional pin notes
* **published**: Publish immediately or save as draft

#### Threads Settings

* **title**: Custom title for the post
* **link\_attachment**: Attach a URL to the post

#### Telegram Settings

* **title**: Custom title for the message
* **disable\_notification**: Send silently
* **protect\_content**: Protect from forwarding

#### Bluesky Settings

* **title**: Custom title for the post
* **website\_card**: Add a website card with URI, title, and description

### Media Guidelines

Different social platforms have different requirements for media. PostSyncer will automatically process your media to meet platform requirements, but keep these limitations in mind:

#### First comments

To schedule a first comment (hashtags, link, CTA) the same way the composer does, add a second content item with `is_first_comment: true`. On **Instagram, Facebook, LinkedIn, and YouTube**, that item is excluded from the main caption and posted as a comment after publish.

```json theme={null}
"content": [
  {
    "text": "Clean caption for the post",
    "media": [1842]
  },
  {
    "text": "Read more: https://example.com\n#hashtags",
    "is_first_comment": true,
    "first_comment_delay": 1
  }
]
```

<Note>
  **Supported first-comment platforms only:** Instagram, Facebook, LinkedIn, and YouTube. Other platforms do **not** schedule a first comment from this flag.

  **Multi-platform posts:** If the same post also targets accounts that do not support first comments (for example TikTok or Threads), the `is_first_comment` item is still part of `content`, but those platforms handle it differently — TikTok may fold the text into the caption; Threads / X may treat extra `content` items as a thread. Put anything that must appear on every platform (links, CTAs) in the main caption, or wait for per-platform content if you need different copy per network.
</Note>

<Note>
  On **X/Twitter**, `content` items are published as a native thread. Do **not** set `is_first_comment` for Twitter posts — use a separate comment via [`POST /comments`](/api-reference/comments/create) after publish if you need a reply.
</Note>

#### Video cover images

Set `content[0].cover_image` when creating or updating a video post. Only the first content thread's cover is applied when publishing.

#### Platform requirements for cover images

| Platform                     | Cover method                        | API field                  |
| ---------------------------- | ----------------------------------- | -------------------------- |
| **TikTok**                   | Frame selection from video **only** | `video_cover_timestamp_ms` |
| **YouTube**                  | Custom thumbnail upload **only**    | `thumbnail`                |
| **Instagram** (Reels)        | Custom thumbnail upload **only**    | `thumbnail`                |
| **Facebook** (Reels / video) | Custom thumbnail upload **only**    | `thumbnail`                |

<Note>
  Do **not** send `thumbnail` for TikTok - use `video_cover_timestamp_ms` to pick a frame from the video. Do **not** send `video_cover_timestamp_ms` for YouTube, Instagram, or Facebook - upload a cover image and pass its library `id` (or a public image URL) in `thumbnail`.
</Note>

**TikTok example** - frame at 2.5 seconds:

```json theme={null}
"content": [{
  "text": "New TikTok!",
  "media": [1842],
  "cover_image": {"video_cover_timestamp_ms": 2500}
}]
```

**Instagram / Facebook / YouTube example** - custom cover image:

```json theme={null}
"content": [{
  "text": "New reel!",
  "media": [1842],
  "cover_image": {"thumbnail": 1843}
}]
```

Typical workflow for custom thumbnails: upload the video → upload the cover image → create the post with both ids in `content[0]`.

| Platform  | Max Images | Max Videos | Required Media | Max File Size             |
| --------- | ---------- | ---------- | -------------- | ------------------------- |
| Twitter/X | 4          | 1          | No             | 5MB (img), 512MB (video)  |
| Facebook  | 10         | 1          | No             | 10MB (img), 4GB (video)   |
| Instagram | 10         | 1          | Yes            | 8MB (img), 100MB (video)  |
| TikTok    | 35         | 1          | Yes            | 20MB (img), 4GB (video)   |
| YouTube   | 0          | 1          | Yes            | N/A, 10GB (video)         |
| Pinterest | 5          | 1          | Yes            | 20MB (img), 200MB (video) |
| Threads   | 10         | 10         | No             | 8MB (img), 1GB (video)    |
| Telegram  | 10         | 10         | No             | 5MB (img), 20MB (video)   |
| LinkedIn  | 9          | 1          | No             | 5MB (img), 512MB (video)  |
| Bluesky   | 4          | 1          | No             | 1MB (img), 100MB (video)  |

### Error Codes

<ResponseField name="400" type="Bad Request">
  Validation errors, invalid parameters, or invalid media URLs
</ResponseField>

<ResponseField name="401" type="Unauthorized">
  Missing or invalid API token
</ResponseField>

<ResponseField name="403" type="Forbidden">
  Token does not have 'posts' permission
</ResponseField>

<ResponseField name="404" type="Not Found">
  Workspace, label, or account not found
</ResponseField>

<ResponseField name="422" type="Unprocessable Entity">
  Validation errors in request data
</ResponseField>
