Create, schedule, and publish posts to X/Twitter programmatically. Simple REST API with Bearer token auth.
https://opentweet.ioAll endpoints require a Bearer token. Get your API key from .
curl -H "Authorization: Bearer ot_your_api_key" \
https://opentweet.io/api/v1/meRate limit headers included in every response: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset
/api/v1/meVerify your API key works and check your subscription status, daily post limits, and post counts. Call this first before scheduling or publishing.
{
"authenticated": true,
"subscription": {
"has_access": true,
"status": "active",
"is_trialing": false,
"trial_ends_at": null,
"current_period_ends_at": "2026-04-01T00:00:00Z"
},
"limits": {
"can_post": true,
"posts_published_today": 3,
"remaining_posts_today": 17,
"daily_limit": 20
},
"stats": {
"total_posts": 142,
"scheduled_posts": 8,
"posted_posts": 120,
"draft_posts": 14
}
}⚠ If subscription.has_access is false, you cannot schedule or publish posts.
/api/v1/postsRetrieve a paginated list of your posts. Filter by status to see only scheduled, posted, draft, or failed posts.
| Name | Type | Description |
|---|---|---|
| page | integer | Page number (default: 1) |
| limit | integer | Posts per page (default: 20, max: 100) |
| status | string | Filter: "scheduled", "posted", "draft", or "failed" |
{
"posts": [
{
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"category": "General",
"text": "Just shipped a new feature!",
"scheduled_date": "2026-03-01T10:00:00Z",
"posted": false,
"posted_date": null,
"failed": false,
"failed_reason": null,
"is_thread": false,
"thread_tweets": null,
"media_urls": null,
"x_post_id": null,
"review_status": "approved",
"created_at": "2026-02-16T08:30:00Z",
"updated_at": "2026-02-16T08:30:00Z"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 142,
"pages": 8
}
}/api/v1/postsCreate a single post, a thread, or bulk create up to 50 posts at once. Include scheduled_date to schedule immediately (requires subscription).
Including scheduled_date requires an active subscription and counts toward daily limits. Omit it to save as a draft. All dates must be in the future (ISO 8601).
// Single post
{
"text": "Just shipped a new feature!",
"category": "Product",
"scheduled_date": "2026-03-01T10:00:00Z"
}
// Thread
{
"text": "Here's what I learned building a SaaS in 2026:",
"is_thread": true,
"thread_tweets": [
"1/ Start with a problem you have yourself",
"2/ Ship fast, iterate faster",
"3/ Your first 10 users matter more than the next 1000"
],
"scheduled_date": "2026-03-01T10:00:00Z"
}
// Bulk create (up to 50)
{
"posts": [
{ "text": "Monday motivation", "scheduled_date": "2026-03-02T09:00:00Z" },
{ "text": "Tuesday tip", "scheduled_date": "2026-03-03T14:00:00Z" }
]
}{
"success": true,
"count": 1,
"posts": [
{
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"text": "Just shipped a new feature!",
"category": "Product",
"scheduled_date": "2026-03-01T10:00:00Z",
"is_thread": false,
"created_at": "2026-02-16T08:30:00Z"
}
]
}/api/v1/posts/:idRetrieve details of a specific post by its ID.
{
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"category": "General",
"text": "Just shipped a new feature!",
"scheduled_date": "2026-03-01T10:00:00Z",
"posted": false,
"posted_date": null,
"failed": false,
"is_thread": false,
"x_post_id": null,
"review_status": "approved",
"created_at": "2026-02-16T08:30:00Z",
"updated_at": "2026-02-16T08:30:00Z"
}/api/v1/posts/:idUpdate a draft or scheduled post. You cannot update posts that have already been published.
All fields are optional. Only include the fields you want to update.
{
"text": "Updated tweet text",
"category": "Marketing",
"is_thread": false,
"thread_tweets": [],
"media_urls": []
}{
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"text": "Updated tweet text",
"category": "Marketing",
"scheduled_date": "2026-03-01T10:00:00Z",
"is_thread": false,
"updated_at": "2026-02-16T09:00:00Z"
}⚠ Returns 400 if the post has already been published.
/api/v1/posts/:idPermanently delete a post.
{
"success": true,
"message": "Post deleted"
}/api/v1/posts/:id/scheduleSet or update the scheduled publish time for a post. Requires an active subscription.
Date must be in the future. Use ISO 8601 format.
{
"scheduled_date": "2026-03-01T10:00:00Z"
}{
"success": true,
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"text": "Just shipped a new feature!",
"scheduled_date": "2026-03-01T10:00:00Z",
"message": "Post scheduled successfully"
}⚠ Requires active subscription.
⚠ Counts toward daily post limits.
/api/v1/posts/:id/publishPublish a post to X/Twitter right now. No request body needed. Requires an active subscription.
{
"success": true,
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"text": "Just shipped a new feature!",
"x_post_id": "1234567890123456789",
"posted_date": "2026-02-16T10:00:00Z",
"message": "Post published successfully"
}⚠ Requires active subscription.
⚠ Returns 502 if the X/Twitter API fails.
| Code | Meaning |
|---|---|
| 200 | Success |
| 201 | Created (new post) |
| 400 | Bad request (validation error) |
| 401 | Unauthorized (invalid API key) |
| 403 | Forbidden (subscription required) |
| 404 | Post not found |
| 429 | Rate limit or daily post limit exceeded |
| 500 | Server error |
| 502 | X/Twitter API error |
{
"error": "Human-readable error message",
"details": ["Array of specific validation errors (optional)"]
}curl -H "Authorization: Bearer ot_your_key" \
https://opentweet.io/api/v1/meCheck authenticated is true and subscription.has_access is true.
curl -X POST https://opentweet.io/api/v1/posts \
-H "Authorization: Bearer ot_your_key" \
-H "Content-Type: application/json" \
-d '{
"text": "Just shipped a new feature!",
"scheduled_date": "2026-03-01T10:00:00Z"
}'# Step 1: Create a draft
curl -X POST https://opentweet.io/api/v1/posts \
-H "Authorization: Bearer ot_your_key" \
-H "Content-Type: application/json" \
-d '{"text": "Hello from the API!"}'
# Step 2: Publish it (replace POST_ID with the id from step 1)
curl -X POST https://opentweet.io/api/v1/posts/POST_ID/publish \
-H "Authorization: Bearer ot_your_key"curl -X POST https://opentweet.io/api/v1/posts \
-H "Authorization: Bearer ot_your_key" \
-H "Content-Type: application/json" \
-d '{
"posts": [
{"text": "Monday motivation", "scheduled_date": "2026-03-02T09:00:00Z"},
{"text": "Tuesday tip", "scheduled_date": "2026-03-03T14:00:00Z"},
{"text": "Wednesday wins", "scheduled_date": "2026-03-04T11:00:00Z"},
{"text": "Thursday thoughts", "scheduled_date": "2026-03-05T16:00:00Z"},
{"text": "Friday feels", "scheduled_date": "2026-03-06T10:00:00Z"}
]
}'Install the official skill and your agent handles everything above automatically.
clawhub install opentweet/x-poster
export OPENTWEET_API_KEY="ot_your_key"
openclaw "schedule 5 tweets about our launch for this week"Your agent can also read the plain-text API docs directly at /api/v1/docs.
Get your API key and start posting in under 3 minutes.
API included in every plan. No extra charge.