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.

Safety Notice

This listing is from the official public ClawHub registry. Review SKILL.md and referenced scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "x-poster" with this command: npx skills add petricbranko/opentweet-x-poster

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 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

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.

Full API docs

For complete documentation: https://opentweet.io/api/v1/docs

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

Fast Douyin Publish

抖音视频自动发布助手。一键上传视频到抖音,支持自动文案生成和标签优化。

Registry SourceRecently Updated
General

Skills Finder

Intelligent skill matcher that searches multiple skill marketplaces (ClawHub & Skills.sh) in real-time. Supports ANY language for user input, multi-step skil...

Registry SourceRecently Updated
General

Claw Self Improving Plus

Turn raw mistakes, corrections, discoveries, and repeated decisions into structured learnings and promotion candidates. Use when the user wants a conservativ...

Registry SourceRecently Updated