Post to X (Twitter) using the OpenTweet API. Create tweets, schedule posts, publish threads, upload media, access analytics, and manage your X content autonomously.
Instrucciones de origen · Vista previa de solo lectura
name
x-poster
description
Post to X (Twitter) using the OpenTweet API. Create tweets, schedule posts, publish threads, upload media, access analytics, and manage your X content autonomously.
For file uploads, use Content-Type: multipart/form-data instead.
Before You Start
ALWAYS verify the connection first:
GET https://opentweet.io/api/v1/me
This returns subscription status, daily post limits, and post counts. Check is true and > 0 before scheduling or publishing.
subscription.has_access
limits.remaining_posts_today
Post Management
Create a tweet
POST https://opentweet.io/api/v1/posts
Body: { "text": "Your tweet text" }
Optionally add "scheduled_date": "2026-03-01T10:00:00Z" to schedule it (requires active subscription, date must be in the future).
Create and publish immediately (one step)
POST https://opentweet.io/api/v1/posts
Body: { "text": "Hello from the API!", "publish_now": true }
Creates the post AND publishes to X in one request. Cannot combine with scheduled_date or bulk posts. Response includes status: "posted", x_post_id, and url (the real X post URL) on success.
Create a tweet with media
POST https://opentweet.io/api/v1/posts
Body: {
"text": "Check out this screenshot!",
"media_urls": ["https://url-from-upload-endpoint"]
}
Upload media first via POST /api/v1/upload, then pass the returned URL(s) in media_urls.
Create a thread
POST https://opentweet.io/api/v1/posts
Body: {
"text": "First tweet of the thread",
"is_thread": true,
"thread_tweets": ["Second tweet", "Third tweet"]
}
thread_media is an array of arrays. Each inner array contains media URLs for the corresponding tweet in thread_tweets. Use [] for tweets with no media.
Post to an X Community
POST https://opentweet.io/api/v1/posts
Body: {
"text": "Shared with the community!",
"community_id": "1234567890",
"share_with_followers": true
}
Workflow: Upload first, then use the returned URL in media_urls or thread_media when creating/updating posts.
Analytics
Account overview
GET https://opentweet.io/api/v1/analytics/overview
Returns posting stats (total posts, publishing rate, active days, avg posts/week, most active day/hour, threads, media posts), streaks (current, longest), trends (this week vs last, this month vs last, best month), category breakdown, and recent activity (daily counts for last 7 and 30 days).
Tweet engagement metrics (Advanced plan only)
GET https://opentweet.io/api/v1/analytics/tweets?period=30
Returns per-tweet engagement: likes, retweets, replies, quotes, impressions, bookmarks, engagement rate. Also includes top/worst performers, content type stats, engagement timeline, and best hours/days. Period: 7-365 days or "all".
Follower growth
GET https://opentweet.io/api/v1/analytics/followers?days=30
Returns follower snapshots over time, current count, net growth, and growth percentage. Days: 7-365 or "all".
Best posting times
GET https://opentweet.io/api/v1/analytics/best-times
Analyzes your publishing patterns to find optimal hours and days. Requires at least 3 published posts.
Growth velocity and predictions
GET https://opentweet.io/api/v1/analytics/growth
Returns daily/weekly/monthly growth rates, growth acceleration, milestone predictions (estimated dates to reach follower milestones), and posting-activity-to-growth correlation.
Common Workflows
First: verify your connection works:
GET /api/v1/me — check authenticated is true, subscription.has_access is true
Post a tweet right now (two steps):
GET /api/v1/me — check limits.can_post is true
Create: POST /api/v1/posts with text
Publish: POST /api/v1/posts/{id}/publish
Post a tweet right now (one step):
GET /api/v1/me — check limits.can_post is true
POST /api/v1/posts with { "text": "...", "publish_now": true }
Post a tweet with an image:
GET /api/v1/me — check limits
Upload: POST /api/v1/upload with the image file — get back a URL
Create: POST /api/v1/posts with { "text": "...", "media_urls": ["<url>"] }
Publish: POST /api/v1/posts/{id}/publish
Schedule a tweet:
GET /api/v1/me — check limits.remaining_posts_today > 0
Create with date: POST /api/v1/posts with text and scheduled_date (done in one step)
Schedule a week of content:
GET /api/v1/me — check remaining limit
Bulk create: POST /api/v1/posts with "posts": [...] array, each with a scheduled_date
Create a thread with media:
Upload images: POST /api/v1/upload for each file
Create: POST /api/v1/posts with is_thread, thread_tweets, media_urls (for first tweet), and thread_media (for subsequent tweets)
Batch schedule existing drafts:
Create drafts: POST /api/v1/posts with "posts": [...] (no scheduled_date)
Schedule all: POST /api/v1/posts/batch-schedule with post IDs and dates
Check analytics before posting:
GET /api/v1/analytics/best-times — find optimal posting hours
GET /api/v1/analytics/overview — check posting streaks and trends
Schedule posts at the suggested best times
Important Rules
ALWAYS call GET /api/v1/me before scheduling or publishing to check limits
CRITICAL: Always parse and use the ACTUAL JSON response from the API. Never fabricate or assume response values.
Post IDs are always 24-character MongoDB ObjectIds (e.g. "507f1f77bcf86cd799439011"), never short strings.
Every post response includes a status field: "draft", "scheduled", "posted", or "failed".
Published posts include a url field with the real X post URL. Always use this URL — never construct your own.
To verify a post was published, check: status is "posted" AND url is present.
Tweet max length: 280 characters (per tweet in a thread)
Dates must be ISO 8601 and in the future — past dates are rejected
Active subscription required to schedule or publish (creating drafts is free)
Including scheduled_date in POST /api/v1/posts requires a subscription
Upload media before creating posts — use the returned URL in media_urls or thread_media
Media limits: 5MB for images (JPG, PNG, GIF, WebP), 20MB for videos (MP4, MOV)
Tweet engagement analytics require the Advanced plan (returns 403 on Pro)
403 = no subscription, 429 = rate limit or daily post limit hit
Check response status codes: 201=created, 200=success, 4xx=client error, 5xx=server error
Safety Guardrails
Publishing is irreversible — once a tweet is posted to X it cannot be undone via the API.
Confirm before publishing
Before calling /publish or using publish_now: true, always tell the user which post(s) you are about to publish and ask for confirmation.
Show the tweet text (truncated if long) and the post ID so the user can verify.
Scheduled posts ≠ ready to publish
If a post has a scheduled_date in the future, it is meant to be published at that time by the scheduler — not right now.
NEVER call /publish on a post that has a future scheduled_date unless the user explicitly asks you to publish it immediately.
When the user asks to "publish" posts, clarify whether they want to publish NOW or schedule for later. Default to scheduling if dates are provided.
Batch operations — go slow
When creating or scheduling more than 5 posts, summarize the batch (count, date range, first/last tweet previews) and ask the user to confirm before proceeding.
Never bulk-create AND immediately publish in one go. Create as drafts or scheduled posts first, let the user review, then publish only on confirmation.
When using batch-schedule, show the user the list of dates before sending the request.
Don't loop publish calls
Never loop through a list of posts calling /publish on each one without explicit user approval for the full list.
If the user asks to "publish all my drafts" or similar, list them first and get confirmation.