Guides & recipes

Build a content scheduler

A content calendar is just a loop that schedules one post per slot. Here's the whole thing, end to end — batch in, queue out.

How it works

Each Create a post call with a schedule_at queues a single publish. PostMyIsh’s once-a-minute publisher ships them at the right time — you don’t run any cron of your own. So a scheduler is: walk your content, compute a time for each item, and queue it.

The full loop

This schedules a batch one per day at 09:00 UTC, starting tomorrow, and prints the queued id for each.

const BASE = "https://postmyish.com/api/v1";
const KEY = process.env.POSTMYISH_KEY!;

async function api(path: string, init?: RequestInit) {
  const res = await fetch(`${BASE}${path}`, {
    ...init,
    headers: {
      Authorization: `Bearer ${KEY}`,
      "Content-Type": "application/json",
      ...init?.headers,
    },
  });
  const json = await res.json();
  if (!res.ok) throw new Error(`${res.status}: ${json.error}`);
  return json;
}

// Your content calendar
const queue = [
  { caption: "Monday: why we built this", platforms: ["x", "linkedin", "bluesky"] },
  { caption: "Tuesday: a customer story", platforms: ["x", "linkedin"] },
  { caption: "Wednesday: behind the scenes", platforms: ["x", "threads", "bluesky"] },
];

// One slot per day at 09:00 UTC, starting tomorrow
const start = new Date();
start.setUTCDate(start.getUTCDate() + 1);
start.setUTCHours(9, 0, 0, 0);

for (let i = 0; i < queue.length; i++) {
  const when = new Date(start);
  when.setUTCDate(start.getUTCDate() + i);
  const post = await api("/posts", {
    method: "POST",
    body: JSON.stringify({ ...queue[i], schedule_at: when.toISOString() }),
  });
  console.log(`Queued ${post.id} for ${when.toISOString()} → ${post.status}`);
}

See what's queued

List scheduled posts any time by filtering List posts to status=scheduled:

curl "https://postmyish.com/api/v1/posts?status=scheduled" \
  -H "Authorization: Bearer $POSTMYISH_KEY"

Reschedule or cancel

To cancel a slot, call Delete or cancel a post with its id. There’s no in-place reschedule endpoint yet, so to move a post you cancel it and queue a new one at the new time.

# Move a post: cancel the old slot, then re-create at the new time
curl -X DELETE https://postmyish.com/api/v1/posts/post_7d1a9c8b \
  -H "Authorization: Bearer $POSTMYISH_KEY"

Idempotency is on you

Re-running the loop queues the batch again — there are no idempotency keys yet. Track which items you’ve already scheduled (by id) so a re-run doesn’t double-book your calendar.
  • Times are absolute — always send a Z or offset. See Scheduling & the queue.
  • Creator plans and above have unlimited posts; the Starter plan caps monthly volume — see limits.