Publishing

Scheduling and timezones

Schedule posts at a local wall-clock time with scheduledFor and an IANA timezone, give each platform its own time, and reschedule safely.

To publish later, send scheduledFor. Pozy stores the time as a UTC instant and publishes at that instant. The one thing to get right is how that instant is read from what you send, because a missing timezone is the most common reason a post goes out at the wrong hour.

#Schedule at a local time

Send the wall-clock time the person picked, without an offset, plus their IANA timezone:

curl -X POST https://api.pozy.ai/v1/posts \
  -H "Authorization: Bearer $POZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Doors open at 10. See you there.",
    "platforms": [{ "platform": "instagram", "accountId": "6710c3e2a9f14b0d8e5c7a22" }],
    "mediaItems": [{ "type": "image", "url": "https://pozy.ai/media/temp/1730289600_q8w1_doors.jpg" }],
    "scheduledFor": "2026-11-14T09:00:00",
    "timezone": "America/New_York"
  }'

The response returns status: "scheduled" and scheduledFor in UTC with a trailing Z. Convert it back to local time for display; Pozy never returns local times.

#How scheduledFor is read

You send Pozy reads it as
"2026-11-14T14:00:00Z" That UTC instant. timezone is ignored.
"2026-11-14T15:00:00+01:00" That instant at that offset. timezone is ignored.
"2026-11-14T09:00:00" (no Z, no offset) A wall-clock time in timezone. Without timezone, in UTC.

All three examples above are the same moment when timezone is America/New_York for the last one.

A missing timezone means UTC

If a person in Madrid picks 10:00 and you send only "scheduledFor": "2026-11-14T10:00:00", the post goes out at 10:00 UTC, which is 11:00 in Madrid. Always send timezone with a local time, or convert to UTC yourself and send a Z.

timezone must be a canonical IANA name such as Europe/Madrid, America/Sao_Paulo or Asia/Tokyo. Abbreviations like CET or PST and misspellings are rejected with a 400.

#Give each platform its own time

A scheduledFor on a platforms[] entry overrides the top-level one for that entry. The top-level timezone still applies to it. Here LinkedIn goes out at 08:30 and Instagram at 19:00, both New York time:

Request body
{
  "content": "Our November product update is out.",
  "scheduledFor": "2026-11-05T08:30:00",
  "timezone": "America/New_York",
  "platforms": [
    { "platform": "linkedin", "accountId": "6710c3e2a9f14b0d8e5c7a21" },
    {
      "platform": "instagram",
      "accountId": "6710c3e2a9f14b0d8e5c7a22",
      "scheduledFor": "2026-11-05T19:00:00"
    }
  ]
}

The overall post.scheduledFor shows the top-level time. Each entry's own time is on platforms[].scheduledFor.

#Daylight saving time

Wall-clock times are converted with the offset in force on that date, so a 09:00 New York post is 14:00 UTC in winter and 13:00 UTC in summer. Two hours a year need care:

Case Example (America/New_York) What to do
A time that does not exist (clocks jump forward) 2027-03-14T02:30:00 Pick another time, or send an explicit offset.
A time that happens twice (clocks fall back) 2027-11-07T01:30:00 Send an explicit offset (-04:00 or -05:00) to say which one you mean.

On those two days, sending a Z time or an explicit offset is the only way to be exact. Queue slots follow the wall clock all year: an 18:00 slot stays 18:00 local after the change.

#Times in the past

A scheduledFor that has already passed is not an error. The post publishes during the request, exactly as if you had sent publishNow: true, and the response holds the outcome. If you build a scheduler that might send stale times, check the time yourself before calling.

#Reschedule a post

Change the time with PUT /v1/posts/{postId}. This works for scheduled, draft, failed, partial and cancelled posts:

curl -X PUT https://api.pozy.ai/v1/posts/6721a8c04e9b2f1d7c3a5e88 \
  -H "Authorization: Bearer $POZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "scheduledFor": "2026-11-15T09:00:00", "timezone": "America/New_York" }'

Things to know when you reschedule:

  • Drafts stay drafts. To schedule a draft, send isDraft: false together with the time. A time alone is saved but the post keeps status: "draft".
  • Queued posts keep their queue. If the post came from a queue and the new time is already taken by another post in that queue, the update fails with 409 and code: "queue_slot_conflict". Pick a free time, drop scheduledFor to let the queue choose, or send queueId: null to take the post out of the queue.
  • No new post.scheduled event. Moving a post that is already scheduled does not fire the webhook again. Keep the new time from the update response.
  • Cancel instead of moving. To stop a scheduled post, delete it with DELETE /v1/posts/{postId} or turn it back into a draft with isDraft: true.

#Let Pozy pick the time

Two features choose scheduledFor for you:

  • Queues spread posts over recurring weekly slots per profile. See Queues.
  • Best time to post suggests slots from each account's own engagement history. See Best time to post.

#Endpoints

Endpoint What it does
POST /v1/posts Create post
PUT /v1/posts/{postId} Update post
GET /v1/posts/{postId} Get post
GET /v1/posts List posts