Publishing
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"
}'const res = await fetch("https://api.pozy.ai/v1/posts", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.POZY_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
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",
// In a browser: Intl.DateTimeFormat().resolvedOptions().timeZone
timezone: "America/New_York",
}),
});
const data = await res.json();
if (!res.ok) throw new Error(data.error);
console.log(data.post.scheduledFor); // "2026-11-14T14:00:00.000Z"resp = requests.post(
"https://api.pozy.ai/v1/posts",
headers={"Authorization": f"Bearer {os.environ['POZY_API_KEY']}"},
json={
"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",
},
timeout=30,
)
print(resp.json()["post"]["scheduledFor"]) # 2026-11-14T14:00:00.000ZThe 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.
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:
{
"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" }'const res = await fetch("https://api.pozy.ai/v1/posts/6721a8c04e9b2f1d7c3a5e88", {
method: "PUT",
headers: {
Authorization: `Bearer ${process.env.POZY_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ scheduledFor: "2026-11-15T09:00:00", timezone: "America/New_York" }),
});
if (!res.ok) throw new Error((await res.json()).error);requests.put(
"https://api.pozy.ai/v1/posts/6721a8c04e9b2f1d7c3a5e88",
headers={"Authorization": f"Bearer {os.environ['POZY_API_KEY']}"},
json={"scheduledFor": "2026-11-15T09:00:00", "timezone": "America/New_York"},
timeout=30,
).raise_for_status()Things to know when you reschedule:
- Drafts stay drafts. To schedule a draft, send
isDraft: falsetogether with the time. A time alone is saved but the post keepsstatus: "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
409andcode: "queue_slot_conflict". Pick a free time, dropscheduledForto let the queue choose, or sendqueueId: nullto take the post out of the queue. - No new
post.scheduledevent. 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 withisDraft: 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 |