Examples

Copy-paste OpenTweet API recipes for the most common jobs. Every request goes to the REST base https://opentweet.io/api/v1 and carries your key as an Authorization: Bearer ot_your_key header. Get a key in your developer dashboard. New here? Start with the quickstart.

Keep keys secret

Never ship an ot_ key in client-side code or a public repo. Run these examples server-side or from your terminal. In CI, set it as an environment variable.

Verify a key

A quick GET /me confirms the key works before you post anything. A 401 means the key is missing or invalid.

bash
curl https://opentweet.io/api/v1/me \
  -H "Authorization: Bearer ot_your_key"

Publish now

Post immediately with publish_now:

bash
curl -X POST https://opentweet.io/api/v1/posts \
  -H "Authorization: Bearer ot_your_key" \
  -H "Content-Type: application/json" \
  -d '{"text": "Hello from my code.", "publish_now": true}'

Same call in Node:

publish-now.js
const res = await fetch("https://opentweet.io/api/v1/posts", {
  method: "POST",
  headers: {
    Authorization: "Bearer ot_your_key",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ text: "Hello from my code.", publish_now: true }),
});
const data = await res.json();
console.log(data);

Schedule for a time

Pass scheduled_date in ISO 8601. It is mutually exclusive with publish_now, so send one or the other, never both.

bash
curl -X POST https://opentweet.io/api/v1/posts \
  -H "Authorization: Bearer ot_your_key" \
  -H "Content-Type: application/json" \
  -d '{"text": "Launch day.", "scheduled_date": "2026-07-10T09:00:00Z"}'

Batch-schedule a week

Create your posts first, then hand their IDs to POST /posts/batch-schedule with a list of schedules. Up to 50 per call.

bash
curl -X POST https://opentweet.io/api/v1/posts/batch-schedule \
  -H "Authorization: Bearer ot_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "schedules": [
      { "post_id": "POST_ID_1", "scheduled_date": "2026-07-13T09:00:00Z" },
      { "post_id": "POST_ID_2", "scheduled_date": "2026-07-14T09:00:00Z" },
      { "post_id": "POST_ID_3", "scheduled_date": "2026-07-15T09:00:00Z" }
    ]
  }'

Post a thread

Set is_thread and pass thread_tweets. Use thread_media to attach media per tweet, one array per tweet.

bash
curl -X POST https://opentweet.io/api/v1/posts \
  -H "Authorization: Bearer ot_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "is_thread": true,
    "thread_tweets": ["First tweet in the thread.", "Second tweet in the thread."],
    "thread_media": [[], []],
    "publish_now": true
  }'

Same thread in Node:

thread.js
const res = await fetch("https://opentweet.io/api/v1/posts", {
  method: "POST",
  headers: {
    Authorization: "Bearer ot_your_key",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    is_thread: true,
    thread_tweets: ["First tweet in the thread.", "Second tweet in the thread."],
    thread_media: [[], []],
    publish_now: true,
  }),
});
console.log(await res.json());

Attach media

Upload the file to POST /upload first, then pass the returned URL to a post as media_urls.

bash
# Step 1: upload a file, get back a media URL
curl -X POST https://opentweet.io/api/v1/upload \
  -H "Authorization: Bearer ot_your_key" \
  -F "file=@./chart.png"

# Step 2: attach the returned URL to a post via media_urls
curl -X POST https://opentweet.io/api/v1/posts \
  -H "Authorization: Bearer ot_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Ship report.",
    "media_urls": ["https://cdn.opentweet.io/your-uploaded-file.png"],
    "publish_now": true
  }'

Target a specific account

If you manage more than one X account, add x_account_id to the request. Omit it to post from your primary account.

bash
curl -X POST https://opentweet.io/api/v1/posts \
  -H "Authorization: Bearer ot_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Posted from my second account.",
    "publish_now": true,
    "x_account_id": "YOUR_X_ACCOUNT_ID"
  }'

List your accounts to find each id:

bash
curl https://opentweet.io/api/v1/accounts \
  -H "Authorization: Bearer ot_your_key"

Poll status

List posts and filter by status to see what is queued. Use it to confirm a schedule landed.

bash
curl "https://opentweet.io/api/v1/posts?status=scheduled" \
  -H "Authorization: Bearer ot_your_key"

Handling errors and rate limits

Errors come back as JSON like {"error": "...", "code": "..."}. Do not retry permanent 4xx errors, fix the request instead. Only retry 429 Too Many Requests and 5xx responses, and back off exponentially between tries. Per-minute limits are 60 (Pro), 300 (Advanced), and 600 (Agency).

Keep exploring