DEV Community

Lautner
Lautner

Posted on • Originally published at chirpapi.fun

How to Schedule Tweets with a REST API

How to Schedule Tweets with a REST API

  June 16, 20267 min read

  Scheduling tweets is one of the most common automation use cases. You write your content ahead of time, set a time, and the API posts it for you. No manual action needed. Here's how to build it with ChirpAPI and a few lines of code.

  ## Basic Concept

  The approach is simple: store your tweets with a scheduled time, run a cron job every minute, and post any tweets whose time has arrived. The flow looks like this:


    - You (or your app) save a tweet with a `scheduled_at` timestamp

    - A cron job runs every minute

    - It checks for tweets where `scheduled_at > /var/log/tweet-scheduler.log 2>&1
Enter fullscreen mode Exit fullscreen mode

`plaintext

  ## Node.js Implementation
Enter fullscreen mode Exit fullscreen mode

`
const sqlite3 = require('better-sqlite3');
const fetch = require('node-fetch');

const API_KEY = 'YOUR_CHIRPAPI_KEY';
const db = sqlite3('scheduler.db');

async function postPending() {
const now = new Date().toISOString().slice(0, 19);
const pending = db.prepare(
SELECT id, text FROM tweets WHERE status='pending' AND scheduled_at<=?
).all(now);

for (const {id, text} of pending) {
try {
const res = await fetch('https://api.chirpapi.fun/v1/tweet', {
method: 'POST',
headers: {
'Authorization': Bearer ${API_KEY},
'Content-Type': 'application/json'
},
body: JSON.stringify({text})
});

  if (res.ok) {
    db.prepare(`UPDATE tweets SET status='posted' WHERE id=?`).run(id);
    console.log(`Posted: ${text.slice(0, 50)}...`);
  } else {
    db.prepare(`UPDATE tweets SET status='failed' WHERE id=?`).run(id);
  }
} catch (err) {
  db.prepare(`UPDATE tweets SET status='error' WHERE id=?`).run(id);
}
Enter fullscreen mode Exit fullscreen mode

}
}

postPending();
`plaintext

  ## Timezone Handling

  Always store and compare times in UTC. Convert to the user's timezone only for display:
Enter fullscreen mode Exit fullscreen mode

`
from zoneinfo import ZoneInfo

User says "post at 9 AM Jakarta time"

jakarta = ZoneInfo("Asia/Jakarta")
scheduled = datetime(2026, 6, 17, 9, 0, 0, tzinfo=jakarta)
utc_time = scheduled.astimezone(timezone.utc)

Store utc_time in database

`plaintext

  ## Best Posting Times

  Based on engagement data across multiple accounts:


    - **Weekdays:** 8-10 AM and 12-1 PM (user's timezone)

    - **Weekends:** 10 AM - 12 PM

    - **Avoid:** After 8 PM (lower engagement)

    - **Best days:** Tuesday, Wednesday, Thursday



  ## Error Handling and Retries

  Network requests fail. Add retry logic:
Enter fullscreen mode Exit fullscreen mode

`
import time

def post_with_retry(text, max_retries=3):
for attempt in range(max_retries):
try:
resp = requests.post(API_URL,
headers={"Authorization": f"Bearer {API_KEY}"},
json={"text": text},
timeout=10
)
if resp.status_code == 200:
return resp.json()
if resp.status_code == 429: # Rate limited
time.sleep(60 * (attempt + 1))
continue
return None
except requests.exceptions.Timeout:
time.sleep(5 * (attempt + 1))
return None
`


Originally published at ChirpAPI Blog.

Top comments (0)