X (Twitter)

Postgale publishes to X with the X API v2: posts, threads, polls, quotes, replies, images, GIFs and videos, with replies, metrics, mentions and direct messages. Everything is available over the REST API (paths relative to https://postgale.com/api/v1) and the MCP server (create_post, list_comments, moderate_comment, get_analytics, send_message, start_conversation, x_engagement, x_search_posts, x_lookup). Each connected X user is one account with platform x.

Connect an account

Ask for a connect link and send the account owner to it. They authorize Postgale on X (OAuth 2.0); tokens are stored encrypted and refreshed automatically.

GET/api/v1/connect/x
curl https://postgale.com/api/v1/connect/x?externalId=cust-1 \
  -H 'Authorization: Bearer sk_…'

# {"authUrl":"https://x.com/i/oauth2/authorize?…","expiresInSeconds":600}

Publish

Text is limited to 280 weighted characters (URLs count 23, emoji and CJK characters 2), or 25,000 for accounts with an X Premium subscription. The limit is checked when the post is created. Videos are processed by X after upload; while that runs the target stays publishing and the worker finishes it.

POST/api/v1/posts
curl -X POST https://postgale.com/api/v1/posts \
  -H 'Authorization: Bearer sk_…' \
  -H 'Content-Type: application/json' \
  -d '{"content":"We just shipped scheduled threads 🧵","platforms":[{"accountId":"acc_x","platformSpecificData":{"threadItems":[{"content":"We just shipped scheduled threads 🧵"},{"content":"Write the thread once, pick a time, done.","mediaUrl":"https://media.postgale.com/demo.png","altText":"Thread editor"}],"replySettings":"following"}}],"publishNow":true}'
POST/api/v1/posts
curl -X POST https://postgale.com/api/v1/posts \
  -H 'Authorization: Bearer sk_…' \
  -H 'Content-Type: application/json' \
  -d '{"content":"Which feature next?","platforms":[{"accountId":"acc_x","platformSpecificData":{"poll":{"options":["Bluesky","LinkedIn","YouTube"],"duration_minutes":1440}}}],"publishNow":true}'
platformSpecificDataWhat it does
customContentText used for X instead of the post content (e.g. a shorter version)
mediaUrl / mediaUrlsPublic https URLs: up to 4 images (5 MB each), or 1 GIF (15 MB), or 1 video (512 MB)
mediaTypetext | image | gif | video (default: from the URL extension)
altText / altTextsImage alt text (≤1000 characters), per image
threadItemsA thread (≤25 posts) published as a reply chain: [{content, mediaUrl?, mediaUrls?, altText?}]; replaces the post content
replyToTweetIdPost id or URL to reply to (see the reply rule below)
quoteTweetIdPost id or URL to quote (not with media or a poll)
replySettingsfollowing | mentionedUsers | subscribers | verified (default: everyone)
poll{options: 2-4 strings ≤25 characters, duration_minutes: 5-10080 (default 1440)}; not with media, threads or quotes
madeWithAi / paidPartnershipDisclosure labels
sensitiveMedia{adultContent?, graphicViolence?, other?}: content warning on the media
geoRestriction{countries: [ISO codes, ≤25]}: only show the media in these countries
longVideoUpload the video as amplify_video (long videos, eligible accounts)

Endpoints

MethodPathWhat it does
POST/postsPublish or schedule (targets with an X accountId and platformSpecificData above)
GET/inbox/comments?accountId=&platformPostId=Replies to a post (last 7 days)
POST/inbox/comments/{id}/replyReply to a reply
POST/inbox/comments/{id}/hideHide or unhide a reply to your post
POST/posts/{id}/editEdit (X Premium, within 1 hour; creates a new post id)
POST/posts/{id}/unpublishDelete from X
GET/analytics/posts/{id}Impressions, likes, replies, reposts, quotes, bookmarks, clicks
GET/accounts/{id}/mentionsPosts mentioning the account
POST / DELETE/x/accounts/{id}/reposts | likes | bookmarks{postId}: repost, like or bookmark, and undo
POST / DELETE/x/accounts/{id}/following{userId | username}: follow and unfollow
GET/x/accounts/{id}/search?query=Recent search (last 7 days)
GET/x/accounts/{id}/posts/{postId}One post
GET/x/accounts/{id}/users/{username}One user (incl. receivesYourDm)
POST/inbox/conversationsStart a DM conversation: {accountId, participantUsername | participantId, text | mediaUrl}
POST/inbox/conversations/{id}/messagesSend a DM in a conversation
POST/inbox/conversations/syncBackfill DM conversations ({accountId})

Direct messages

X has no 24-hour messaging window: you can message anyone whose DM settings accept messages from the account, and only X lets you write first. Start with POST /inbox/conversations, then reply with POST /inbox/conversations/{id}/messages. Encrypted X Chat conversations are not available through the X API.

POST/api/v1/inbox/conversations
curl -X POST https://postgale.com/api/v1/inbox/conversations \
  -H 'Authorization: Bearer sk_…' \
  -H 'Content-Type: application/json' \
  -d '{"accountId":"acc_x","participantUsername":"happy_customer","text":"Thanks for the shoutout! Here is 20% off: THANKS20"}'

Comments, mentions and inbound events

Replies to your posts are listed from X's recent search (the last 7 days). When the instance enables the inbox poll (X_INBOX_POLL_MINUTES), new replies arrive as comment.received, other mentions as mention.received, and DMs as message.received webhooks.

X's rules to know