# How to Schedule Social Media Posts via API (2026) · PostLake > Markdown version of https://postlake.dev/guides/schedule-posts-api . The canonical page for humans. > PostLake is the social media API for AI agents: https://postlake.dev/llms.txt Schedule social posts with one *API* call. Scheduling is one field on the publish call. Same addressing and media as an immediate post. Pass timezone (IANA) with a naive local time, or send UTC with a trailing Z. Invalid media is refused when you schedule, not at fire time. **In short:** Add scheduledAt (UTC with a trailing Z, or a naive local time plus timezone) to the same /v1/posts body. Credits charge when it fires. Invalid media is refused at create. Edit/cancel while state is scheduled. ## When this guide is for you You want calendar-style publishing from code or automation without a separate scheduler product. ## Before you start Same setup the [docs quickstart](https://docs.postlake.dev/quickstart.md) uses. Do this once: - Sign up at [app.postlake.dev](https://app.postlake.dev) and verify your email (unlocks free credits). - On **Channels**, create a **profile** (e.g. `my-brand`) and connect at least one account. **Bluesky is the fastest first channel**: no app review. Instagram/TikTok/Facebook need each platform's review before API posting. - Account menu → **API Keys** → create a key (`sk_live_…`). It shows once; treat it like a password. ## Schedule a post Same call you'd use to publish now, plus `scheduledAt` (UTC, or a local time with `timezone`): ``` curl -X POST https://api.postlake.dev/v1/posts \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: friday-recap-001" \ -d '{ "text": "Friday recap", "profile": "my-brand", "scheduledAt": "2026-08-13T07:00:00", "timezone": "Europe/London" }' # Response state should be "scheduled" until fire time. ``` ## Step by step 1. Build the same body you'd use to publish now (`text` + `profile` / `accounts`). 1. Add `scheduledAt`. UTC with a trailing `Z`, or a naive local time together with `timezone` (IANA, e.g. `Europe/London`). 1. Call `POST /v1/posts/validate` first for TikTok photo posts (JPEG/WebP, max 1080×1920, PNG rejected). 1. Expect `state: "scheduled"`. At fire time it moves to `processing` then `published` / `partial` / `failed`. 1. Before it fires: `PATCH /v1/posts/{id}` to edit, `DELETE /v1/posts/{id}` to cancel. 1. Subscribe to webhooks (or poll) for fire-time results instead of assuming success at schedule time. ## Read the response (don't skip this) You get one `Post` with an overall `state` and a `targets[]` array. One entry per account. **Always check each target**; partial success is normal. ``` { "id": "post_a1b2c3", "state": "partial", "targets": [ { "platform": "bluesky", "state": "published", "url": "https://bsky.app/…" }, { "platform": "linkedin", "state": "failed", "error": { "type": "invalid_request", "message": "…", "retryable": false } } ] } ``` - `published`: every target succeeded. `partial`: some published, some failed. `failed`: none published. `processing`: still going (async networks like TikTok). - **You're only charged for targets that actually publish.** Failed targets cost nothing. - Send an `Idempotency-Key` header on writes so a retry never double-posts. - Full detail: [Publishing](https://docs.postlake.dev/publishing) · [Errors & retries](https://docs.postlake.dev/errors) ## Where the post goes Same rules as the docs. Pick one addressing style: - **By profile**: `"profile": "my-brand"` posts to every account under that profile (the name on Channels). - **Filter networks**: `"platforms": ["bluesky", "linkedin"]` narrows that set. It is a **filter, not a selector**: if you have two Pinterest boards, both match `pinterest`. - **By account id**: `"accounts": ["acc_…"]` for exact channels (copy an id on Channels, or `GET /v1/social-accounts`). - One profile and you omit `profile`? PostLake uses that profile. Multiple profiles and you omit it? You'll get an error that names them. See [Publishing: where to post](https://docs.postlake.dev/publishing). ## Do more (same API) - **Edit / cancel**: while `state` is `scheduled`: `PATCH /v1/posts/{id}` or `DELETE /v1/posts/{id}`. [Scheduling docs](https://docs.postlake.dev/scheduling). - **Media & overrides**: same as an immediate post: `media`, `textOverrides`, `platformOptions`. - **Notify on fire**: subscribe to [webhooks](https://docs.postlake.dev/webhooks) instead of polling. - **Validate first**: `POST /v1/posts/validate` (free) before you queue a week of content. ## Pitfalls specific to this path - A naive datetime without `timezone` is a 400. Sending local time as UTC (trailing Z, no timezone) still fires at the wrong hour. - Credits charge when it **publishes**, not when you schedule. A cancel before fire costs nothing. - Don't treat schedule-time 200 as "live on social", wait for fire-time target states. Prefer an assistant over Scheduling code? Point it at [MCP](https://docs.postlake.dev/mcp) (`https://api.postlake.dev/mcp`). Prefer the dashboard? Use [Quickstart → No code](https://docs.postlake.dev/quickstart). ## Common questions ### How do I schedule a social media post with an API? POST /v1/posts with scheduledAt. Send UTC with a trailing Z, or a naive local time plus timezone (IANA, e.g. Europe/London). PostLake queues it and publishes at that time. See docs → Scheduling. ### What time format does scheduledAt use? ISO-8601. UTC with a trailing Z, or a naive local time together with timezone. Unparseable values and naive times without a zone get a clear 400. ### Can I cancel or change a scheduled post? Yes, while state is scheduled: PATCH /v1/posts/{id} to edit, DELETE /v1/posts/{id} to cancel. ## Go deeper in the docs These guides stay short on purpose. Canonical behaviour lives here: [Docs ### Quickstart Account, first channel, first post, MCP or API.](https://docs.postlake.dev/quickstart) [Docs ### Publishing Request body, addressing. Partial success, lifecycle.](https://docs.postlake.dev/publishing) [Docs ### Scheduling UTC or local time plus timezone, edit/cancel, fire-time credits.](https://docs.postlake.dev/scheduling) [Docs ### Platforms Limits, media rules, live platformOptions.](https://docs.postlake.dev/platforms) Also: [Media](https://docs.postlake.dev/media) · [Errors](https://docs.postlake.dev/errors) · [MCP](https://docs.postlake.dev/mcp) · [Analytics](https://docs.postlake.dev/analytics) ## Related guides - [Post everywhere at once](https://postlake.dev/guides/post-to-all-social-media-at-once.md) - [Post with n8n](https://postlake.dev/guides/n8n.md) - [Post with Python](https://postlake.dev/guides/python.md) - [Build an AI social agent](https://postlake.dev/guides/ai-social-media-agent.md) [All guides](https://postlake.dev/guides/index.md) · [Full docs](https://docs.postlake.dev/) · [llms.txt](https://postlake.dev/llms.txt) Plain markdown for agents: https://postlake.dev/guides/schedule-posts-api.md · https://postlake.dev/llms.txt