x-poster
Post to X (Twitter) using the OpenTweet API. Create tweets, schedule posts, publish threads, upload media, access analytics, and manage your X content autonomously.
安装 / 下载方式
TotalClaw CLI推荐
totalclaw install clawskills:clawskills~petricbranko-opentweet-x-postercURL直接下载,无需登录
curl -fsSL https://skills.taituai.com/api/skills/clawskills%3Aclawskills~petricbranko-opentweet-x-poster/file -o petricbranko-opentweet-x-poster.md# OpenTweet X Poster
You can post to X (Twitter) using the OpenTweet REST API. All requests go to `https://opentweet.io` with the user's API key.
## Authentication
Every request needs this header:
```
Authorization: Bearer $OPENTWEET_API_KEY
Content-Type: application/json
```
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 `subscription.has_access` is true and `limits.remaining_posts_today` > 0 before scheduling or publishing.
## 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"]
}
```
### Create a thread with per-tweet media
```
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 to an X Community
```
POST https://opentweet.io/api/v1/posts
Body: {
"text": "Shared with the community!",
"community_id": "1234567890",
"share_with_followers": true
}
```
### Bulk create (up to 50 posts)
```
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" }
]
}
```
### Schedule a post
```
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.
### Publish immediately
```
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).
### Batch schedule (up to 50 posts)
```
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
}
```
### List posts
```
GET https://opentweet.io/api/v1/posts?status=scheduled&page=1&limit=20
```
Status options: `scheduled`, `posted`, `draft`, `failed`
### Get a post
```
GET https://opentweet.io/api/v1/posts/{id}
```
### Update a post
```
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 a post
```
DELETE https://opentweet.io/api/v1/posts/{id}
```
## Media Upload
### Upload an image or video
```
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.
## 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:**
1. `GET /api/v1/me` — check `authenticated` is true, `subscription.has_access` is true
**Post a tweet right now (two steps):**
1. `GET /api/v1/me` — check `limits.can_post` is true
2. Create: `POST /api/v1/posts` with text
3. Publish: `POST /api/v1/posts/{id}/publish`
**Post a tweet right now (one step):**
1. `GET /api/v1/me` — check `limits.can_post` is true
2. `POST /api/v1/posts` with `{ "text": "...", "publish_now": true }`
**Post a tweet with an image:**
1. `GET /api/v1/me` — check limits
2. Upload: `POST /api/v1/upload` with the image file — get back a URL
3. Create: `POST /api/v1/posts` with `{ "text": "...", "media_urls": ["<url>"] }`
4. Publish: `POST /api/v1/posts/{id}/publish`
**Schedule a tweet:**
1. `GET /api/v1/me` — check `limits.remaining_posts_today` > 0
2. Create with date: `POST /api/v1/posts` with text and scheduled_date (done in one step)
**Schedule a week of content:**
1. `GET /api/v1/me` — check remaining limit
2. Bulk create: `POST /api/v1/posts` with `"posts": [...]` array, each with a scheduled_date
**Create a thread with media:**
1. Upload images: `POST /api/v1/upload` for each file
2. 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:**
1. Create drafts: `POST /api/v1/posts` with `"posts": [...]` (no scheduled_date)
2. Schedule all: `POST /api/v1/posts/batch-schedule` with post IDs and dates
**Check analytics before posting:**
1. `GET /api/v1/analytics/best-times` — find optimal posting hours
2. `GET /api/v1/analytics/overview` — check posting streaks and trends
3. 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