Requirements
- Target platform
- OpenClaw
- Install method
- Manual import
- Extraction
- Extract archive
- Prerequisites
- OpenClaw
- Primary doc
- SKILL.md
Post to X (Twitter) using the OpenTweet API. Create tweets, schedule posts, publish threads, and manage your X content autonomously.
Post to X (Twitter) using the OpenTweet API. Create tweets, schedule posts, publish threads, and manage your X content autonomously.
Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.
I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete.
I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run.
You can post to X (Twitter) using the OpenTweet REST API. All requests go to https://opentweet.io with the user's API key.
Every request needs this header: Authorization: Bearer $OPENTWEET_API_KEY Content-Type: application/json For file uploads, use Content-Type: multipart/form-data instead.
ALWAYS verify the connection first: GET https://opentweet.io/api/v1/me This returns subscription status, daily post limits, and post counts. Check subscription.has_access is true and limits.remaining_posts_today > 0 before scheduling or publishing.
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).
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.
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.
POST https://opentweet.io/api/v1/posts Body: { "text": "First tweet of the thread", "is_thread": true, "thread_tweets": ["Second tweet", "Third tweet"] }
POST https://opentweet.io/api/v1/posts Body: { "text": "Thread intro with image", "is_thread": true, "thread_tweets": ["Second tweet", "Third tweet"], "media_urls": ["https://intro-image-url"], "thread_media": [["https://img-for-tweet-2"], []] } 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 https://opentweet.io/api/v1/posts Body: { "text": "Shared with the community!", "community_id": "1234567890", "share_with_followers": true }
POST https://opentweet.io/api/v1/posts Body: { "posts": [ { "text": "Tweet 1", "scheduled_date": "2026-03-01T10:00:00Z" }, { "text": "Tweet 2", "scheduled_date": "2026-03-01T14:00:00Z" } ] }
POST https://opentweet.io/api/v1/posts/{id}/schedule Body: { "scheduled_date": "2026-03-01T10:00:00Z" } The date must be in the future. Use ISO 8601 format.
POST https://opentweet.io/api/v1/posts/{id}/publish No body needed. Posts to X right now. Response includes status: "posted", x_post_id, and url (the real X post URL).
POST https://opentweet.io/api/v1/posts/batch-schedule Body: { "schedules": [ { "post_id": "id1", "scheduled_date": "2026-03-02T09:00:00Z" }, { "post_id": "id2", "scheduled_date": "2026-03-03T14:00:00Z" } ], "community_id": "optional-community-id", "share_with_followers": true }
GET https://opentweet.io/api/v1/posts?status=scheduled&page=1&limit=20 Status options: scheduled, posted, draft, failed
GET https://opentweet.io/api/v1/posts/{id}
PUT https://opentweet.io/api/v1/posts/{id} Body: { "text": "Updated text", "media_urls": ["https://..."], "scheduled_date": "2026-03-01T10:00:00Z" } All fields optional. Cannot update already-published posts. Set scheduled_date to null to unschedule (convert back to draft).
DELETE https://opentweet.io/api/v1/posts/{id}
POST https://opentweet.io/api/v1/upload Content-Type: multipart/form-data Body: file=@your-image.png Returns: { "url": "https://..." } Supported formats: JPG, PNG, GIF, WebP (max 5MB), MP4, MOV (max 20MB). Workflow: Upload first, then use the returned URL in media_urls or thread_media when creating/updating posts.
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).
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".
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".
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.
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.
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
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) Bulk limit: 50 posts per request Rate limit: 60 requests/minute, 1,000/day (Pro); 300/min, 10,000/day (Advanced) 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
Publishing is irreversible โ once a tweet is posted to X it cannot be undone via the API.
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.
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.
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.
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.
For complete documentation: https://opentweet.io/api/v1/docs
Code helpers, APIs, CLIs, browser automation, testing, and developer operations.
Largest current source with strong distribution and engagement signals.