X (Twitter) API: posting reference
X (formerly Twitter) is supported via the X API v2. OmniSocials posts to the account that completed the OAuth flow. Both standard and premium accounts are supported, and the character limit adjusts based on the account's subscription tier. You don't need your own X developer account or API plan: posts without a link cost nothing extra, and posts with a link use credits.
For an overview and use cases, see X API.
Channel ID: x
Supported content types
| Type | Supported |
|---|---|
| Feed post | ✅ |
| Story | - |
| Reel | - |
Minimal example
Terminal
Platform-specific options
| Field | Type | Description |
|---|---|---|
x.reply_settings | string | Who can reply: "" (everyone, default), following, or mentionedUsers |
x.paid_partnership | boolean | Mark as a paid partnership disclosure (default false) |
x.made_with_ai | boolean | Mark as AI-generated content (default false) |
x.poll | object | Attach a poll; the post text is the question. See Polls. |
x.thread_parts | array | Publish as a chained thread instead of a single tweet. See Posting threads. |
JSON
Posting threads
To publish as a thread, pass x.thread_parts instead of relying on content.x. Each part becomes its own tweet, chained via in_reply_to_tweet_id.
JSON
Rules:
-
2 to 25 parts. For a single tweet, omit
thread_partsand usecontent.x(orcontent.default) instead. -
Each
textis required, non-empty, and within the account's character limit (280, or 25,000 on Basic, Premium and Premium+), counted the way X counts. Parts that exceed the limit are rejected with a400. -
media_urlsis optional per part (max 4) and overrides any top-levelmedia_urls.xfor that specific tweet:JSON -
When
content.xis provided alongsidethread_parts,thread_partswins. -
The first tweet's URL becomes
published_urls.xon the post. The full chain is recorded onx.thread_tweets(read back withGET /posts/:id) for analytics. -
reply_settings, the labels and a poll apply to the first tweet.
To convert a thread back into a single tweet on update, send x.thread_parts: null to PATCH /posts/:id.
Polls
Pass x.poll to attach a poll. The post text is the question.
JSON
Rules:
- 2 to 4
options, each up to 25 characters and different from the others. duration_minutes: a whole number from 5 to 10080 (7 days). Leave it out and the poll runs for 1440 minutes (one day). The composer in the OmniSocials dashboard offers 1 hour, 6 hours, 1 day, 3 days and 7 days.- A poll and media do not go together on X: a request with both is refused with
400 validation_error. - On a thread (
thread_parts), the poll goes on the first tweet, which then carries no media. GET /posts/:idreturns the poll underx.poll. OnPATCH /posts/:idthexobject replaces the stored X options as a whole: sendx.poll: null, or leavepollout, to remove it.- Poll results come back in analytics under
metrics.poll.
Character limits
| Account tier | Character limit |
|---|---|
| Standard (free) | 280 |
| Basic | 25,000 |
| Premium (Blue) | 25,000 |
| Premium+ | 25,000 |
OmniSocials detects the connected account's subscription tier and enforces the correct limit at validation time, for single tweets and for every part of a thread sent through the API. The thread composer in the OmniSocials dashboard keeps each part at 280 characters, also on Premium. The tier is read when you connect; reconnect X after upgrading.
Characters are weighted the way X counts them, not by string length. Every link counts as 23 characters no matter how long the URL is, and emoji and CJK characters count as 2 each (an emoji family joined with ZWJ counts as a single 2-weight unit). A 270-character post containing a 10-character link is over the limit. OmniSocials validates with the weighted count, so a rejection at create time means X would have rejected it too; X itself returns an unhelpful generic 403 for over-length posts.
Media requirements
| Media | Requirement |
|---|---|
| Image | JPEG, PNG, or WebP. Max 5 MB. Up to 4 per post. |
| Video | MP4, H.264 codec. Free and Basic accounts: up to 2 minutes 20 seconds, max 512 MB. Premium and Premium+ accounts: up to 125 minutes, max 16 GB (in practice bounded by OmniSocials' own limits: 1 GB for media added by URL, 100 MB for direct file uploads). The tier is detected from your connected X account; reconnect X after upgrading. |
X does not support mixing image and video in the same post. Video posts allow one video. Image posts allow up to four images.
Alt text. Pass a per-image accessibility description by using an object entry instead of a bare string: { "url": "https://example.com/chart.png", "alt": "Bar chart of Q3 signups by week" } in media_urls (or { "id": "...", "alt": "..." } in media_ids, including per-part thread media). It is set via X's v2 media metadata on images only (X does not support alt text on video), clamped to X's 1000-character cap. An alt-text failure at X never fails the publish.
Link posts use credits
X's API bills posts whose text contains a URL at a premium ($0.20 per tweet instead of $0.015). OmniSocials passes that fee through as prepaid credits at X's rate card: 20 credits per URL-containing tweet (credits cost €0.01 each, topped up €5-500 in the dashboard), with threads billed per part that contains a link. Posts without links, analytics and media stay free. X DMs in the inbox are opt-in and use credits too (see Social Inbox).
Only a link written with a scheme (http://... or https://...) counts, because that is what X bills. A www. link, a bare domain (omnisocials.com) and a spelled-out domain ("brand dot com") are free. X still shortens a bare domain to a t.co link, so it counts as 23 characters. Until 2026-10-03 www. links and bare domains used credits too.
When a create targets X and the text contains a URL, the 201 response includes a top-level warnings array (code x_url_post_credits) with credits_required, the current credits_balance, and the enforcement state; see Creating Posts for the full shape. Debiting has been live since 2026-08-14. If the balance can't cover it at publish time, only the X target fails (other platforms publish normally); top up at app.omnisocials.com/credits and retry with POST /posts/:id/retry. Credits are managed in the dashboard; there is no API endpoint for them.
Every company gets 200 starter credits once, when it first connects X.
Scheduled X link posts also reserve their cost until they publish: scheduling or publishing a new one that would push the reserved total past the balance is refused with 402 x_credits_insufficient (see Creating Posts). Drafts are never gated.
Social Inbox
X direct messages can land in the Social Inbox. They are off by default: each workspace opts in from the X DMs card in the Social Inbox, which needs the billing permission and a balance of at least 25 credits. X bills its DM API per use, so each received DM costs 1 credit and each reply 2 credits. At 50 credits left, the people who manage X DMs get one notice in the app and one email a day that X DMs pause soon. At a zero balance the X inbox pauses; after a top-up or an auto-refill it turns back on by itself.
- DMs only. Mentions and replies on X are not part of the inbox.
- Unencrypted DMs only. X does not give apps the messages of an encrypted X Chat conversation.
- No history: DMs arrive from the moment you opt in. Earlier conversations, and DMs sent while the inbox was paused, are not imported.
- Accounts connected before DM support shipped need a one-time reconnect for the DM permissions.
Automations
An automation can answer the DMs your X account gets: a DM with a keyword (or any first message) gets your answer, once per person. Create it with POST /automations and platform: "x".
- DMs only (
trigger.kinds: ["dm"]): X allows an automated DM only after the person wrote first. No comment trigger, no post, no public reply. - X DMs must be on for the workspace (see Social Inbox); otherwise an active automation answers
409 x_dms_off, andstatus: "paused"saves it for later. - Every answer ends with "Reply STOP to stop automatic messages." A person who replies STOP gets no automatic DM from the account again, in any workspace with that account, also after the automation is deleted.
- At most 15 answers per 15 minutes and 450 a day per account; more wait in a queue for up to an hour (also when X answers with its own rate limit). Each answer uses 2 credits, like an inbox reply.
- Encrypted X Chat conversations get no answer: X does not give apps their messages.
Limitations
- No first comment on X. Use a thread instead.
- A poll and media can't go in the same post.
- Quote posts and Communities are not supported.