# X (Twitter) (/docs/platforms/twitter)




What you can post [#what-you-can-post]

| Type      | Supported | Max media | Notes                                                     |
| --------- | --------- | --------- | --------------------------------------------------------- |
| Text only | ✅         | 0         | 280 characters (free) or 25,000 (Premium)                 |
| Photos    | ✅         | 4         | JPEG, PNG, WebP. Max 5 MB each                            |
| Video     | ✅         | 1         | MP4, MOV. Max 512 MB, 0.5–140 seconds                     |
| GIF       | ✅         | 1         | Max 15 MB                                                 |
| Poll      | ✅         | 0         | 2–4 options, 5 min to 7 days. No media allowed with polls |

<Callout title="Limitations" type="warn">
  * **Media types are exclusive.** A post can have up to 4 photos OR 1 video OR 1 GIF — you cannot mix them.
  * **Polls are exclusive.** A post with a poll cannot have media or a quote tweet.
  * **Quote tweets are exclusive.** A post with a quote tweet cannot have media or a poll.
  * **Character counting uses weighted rules.** Emojis and CJK characters count as 2. URLs always count as 23 characters regardless of length.
  * **Rate limit: 200 posts per 15 minutes**, 300 per 3 hours (shared with retweets).
</Callout>

<Callout title="Posting to X alongside other platforms" type="info">
  X has a **280-character limit** (25,000 for Premium), but platforms like Facebook or LinkedIn allow much longer content. Use `postOverrides` on the X account entry to provide shorter content just for X while keeping the full text for other platforms.

  ```json
  {
    "content": "Your long-form content for Facebook, LinkedIn, etc...",
    "accounts": [
      { "accountId": "facebook-account-id" },
      { "accountId": "linkedin-account-id" },
      {
        "accountId": "twitter-account-id",
        "postOverrides": {
          "content": "Short version for X 🐦"
        }
      }
    ],
    "publishNow": true
  }
  ```
</Callout>

Quick start [#quick-start]

Post text [#post-text]

<Tabs items="['cURL']">
  <Tab value="cURL">
    ```bash
    curl -X POST https://publishq.com/api/v1/posts \
      -H "Authorization: Bearer pq_live_..." \
      -H "Content-Type: application/json" \
      -d '{
        "content": "Hello from the PublishQ API! 🚀",
        "accounts": [
          { "accountId": "your-twitter-account-id" }
        ],
        "publishNow": true
      }'
    ```
  </Tab>
</Tabs>

Post with photos, video, or GIF [#post-with-photos-video-or-gif]

Up to 4 photos, 1 video, or 1 GIF per post. These are mutually exclusive — you cannot mix them.

<div className="fd-steps">
  <div className="fd-step">
    Get your media ready [#1-get-your-media-ready]

    <Tabs items="['Upload new media', 'Use existing media']">
      <Tab value="Upload new media">
        ```bash
        curl -X POST https://publishq.com/api/v1/media \
          -H "Authorization: Bearer pq_live_..." \
          -F "file=@photo.jpg"
        ```
      </Tab>

      <Tab value="Use existing media">
        ```bash
        curl https://publishq.com/api/v1/media \
          -H "Authorization: Bearer pq_live_..."
        ```

        Pick the `id` of the media you want to use.
      </Tab>
    </Tabs>
  </div>

  <div className="fd-step">
    Create the post [#2-create-the-post]

    ```bash
    curl -X POST https://publishq.com/api/v1/posts \
      -H "Authorization: Bearer pq_live_..." \
      -H "Content-Type: application/json" \
      -d '{
        "content": "Photo dump 📸",
        "mediaIds": ["media-id-1", "media-id-2"],
        "accounts": [
          { "accountId": "your-twitter-account-id" }
        ],
        "publishNow": true
      }'
    ```
  </div>
</div>

Post with a poll [#post-with-a-poll]

Polls cannot have media or a quote tweet attached.

```bash
curl -X POST https://publishq.com/api/v1/posts \
  -H "Authorization: Bearer pq_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "content": "What should we build next?",
    "accounts": [
      {
        "accountId": "your-twitter-account-id",
        "platformSpecificSettings": {
          "poll": {
            "options": ["Feature A", "Feature B", "Feature C"],
            "durationMinutes": 1440
          }
        }
      }
    ],
    "publishNow": true
  }'
```

Reply to a tweet [#reply-to-a-tweet]

```bash
curl -X POST https://publishq.com/api/v1/posts \
  -H "Authorization: Bearer pq_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Great point! Here are my thoughts...",
    "accounts": [
      {
        "accountId": "your-twitter-account-id",
        "platformSpecificSettings": {
          "replyToTweetId": "1346889436626259968"
        }
      }
    ],
    "publishNow": true
  }'
```

Quote a tweet [#quote-a-tweet]

Quote tweets cannot have media or a poll.

```bash
curl -X POST https://publishq.com/api/v1/posts \
  -H "Authorization: Bearer pq_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "content": "This is worth reading 👇",
    "accounts": [
      {
        "accountId": "your-twitter-account-id",
        "platformSpecificSettings": {
          "quoteTweetId": "1346889436626259968"
        }
      }
    ],
    "publishNow": true
  }'
```

Post to a community [#post-to-a-community]

```bash
curl -X POST https://publishq.com/api/v1/posts \
  -H "Authorization: Bearer pq_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Discussion topic for the community",
    "accounts": [
      {
        "accountId": "your-twitter-account-id",
        "platformSpecificSettings": {
          "communityId": "1146654567674912769",
          "shareWithFollowers": true
        }
      }
    ],
    "publishNow": true
  }'
```

Platform settings [#platform-settings]

<PlatformSettingsTable platform="TWITTER" />

Poll object [#poll-object]

The `poll` field inside `platformSpecificSettings` accepts the following:

| Field             | Type       | Required | Description                                                       |
| ----------------- | ---------- | -------- | ----------------------------------------------------------------- |
| `options`         | `string[]` | Yes      | 2–4 poll choices. Each option max 25 characters.                  |
| `durationMinutes` | `number`   | Yes      | How long the poll stays open. Min 5 minutes, max 10,080 (7 days). |

<small>
  Full schema: 

  [TwitterPlatformSpecificSettings](/docs-scalar#model/TwitterPlatformSpecificSettings)
</small>

Media specs [#media-specs]

Photos [#photos]

| Spec          | Value                       |
| ------------- | --------------------------- |
| Formats       | JPEG, PNG, WebP             |
| Max file size | 5 MB                        |
| Max per post  | 4 (alone — no video or GIF) |

Videos [#videos]

| Spec          | Value                                                       |
| ------------- | ----------------------------------------------------------- |
| Formats       | MP4, MOV                                                    |
| Max file size | 512 MB                                                      |
| Duration      | 0.5–140 seconds                                             |
| Max per post  | 1 (alone — no photos or GIF)                                |
| Codec         | H.264 High Profile recommended                              |
| Resolution    | 1280x720 (landscape), 720x1280 (portrait), 720x720 (square) |
| Frame rate    | 30 or 60 FPS                                                |
| Aspect ratio  | Between 1:3 and 3:1                                         |

GIFs [#gifs]

| Spec           | Value                          |
| -------------- | ------------------------------ |
| Max file size  | 15 MB                          |
| Max per post   | 1 (alone — no photos or video) |
| Max resolution | 1280x1080                      |
| Max frames     | 350                            |

Not yet supported [#not-yet-supported]

* **Threads** — Posting a chain of replies as a thread (coming soon)
* **Video subtitles**
* **Location / geo tagging**
