---
title: "List scheduled posts"
method: GET
path: "/api/apps/{app_id}/social-calendar/posts"
---

# List scheduled posts

`GET /api/apps/{app_id}/social-calendar/posts`

<Info>This API is in beta. Endpoints, fields, and behavior may still change, so avoid depending on it in production.</Info>

Lists the app's whole [social calendar](/developers/references/apps-api/sections/virality#social-calendar) in one response, with no paging. It includes every post that hasn't been deleted, earliest scheduled time first, covering the posts [Generate content plan](/api-reference/generate-content-plan) produced alongside the ones you write with [Create scheduled post](/api-reference/create-scheduled-post).

Pass `plan_id`, a [content plan](/developers/references/apps-api/sections/virality#content-plans)'s id from [Get social content state](/api-reference/get-social-content-state)'s `plan.id`, to add that plan's suggested posts to the calendar before listing, and remove any leftover suggestions from a plan you've since regenerated. Anything already approved, edited, or published is left alone. It doesn't filter the response, and only accepts the app's current plan id.

## Path parameters

- `app_id` string, required — ID of the app whose social calendar you want.

## Query parameters

- `plan_id` string, nullable — The app's current content plan id, as returned in `plan.id` by [Get social content state](/api-reference/get-social-content-state). Passing it adds that [content plan](/developers/references/apps-api/sections/virality#content-plans)'s posts to the calendar before listing. It doesn't filter the response.

## Response `200`

The app's social calendar.

- ScheduledPostResponse[]
  - `id` string, required — ID of the post. Pass it as `post_id` to the other social calendar endpoints.
  - `app_id` string, required — ID of the app the post belongs to.
  - `plan_id` string, nullable, required — ID of the content plan the post was generated from, or `null` for a post created through [Create scheduled post](/api-reference/create-scheduled-post).
  - `source_post_id` string, nullable, required — ID this post has inside the content plan it came from, or `null` for a post created through the API.
  - `platform` string, required — Account the post publishes to. Base44 publishes to `instagram`, `linkedin` and `facebook`. A post generated from a content plan can also name `x`, `tiktok` or `reddit`, which Base44 plans for but can't publish, and scheduling such a post fails it.
  - `title` string, required — Title of the post. It labels the post on the calendar and isn't published as text, except on LinkedIn, where a post with an image sends it as the image's title.
  - `body` string, required — Body text of the post. Base44 publishes this followed by `hashtags`, so leave the tags out of it.
  - `hook` string, required — The angle the post leads with. A plan-generated post carries the angle the planner picked, either `pain_point`, `feature_demo`, `social_proof`, `trending_hook`, `user_story`, or `before_after`. A post you create carries whatever you sent, or an empty string.
  - `cover_index` integer, required — Zero-based position of the post in the series its content plan generated, which is how the calendar picks its cover image. Always `0` for a post created through the API.
  - `scheduled_at` string, date-time, required — When the post publishes, always in UTC. A post read back from the calendar carries no offset (`2026-09-15T14:00:00`), while the one [Create scheduled post](/api-reference/create-scheduled-post) returns carries `+00:00`. Read both as UTC.
  - `scheduled_local_at` string, required — The same instant as `scheduled_at`, rendered in `scheduled_timezone` as an ISO 8601 timestamp. Display only.
  - `scheduled_timezone` string, required — IANA timezone `scheduled_local_at` is rendered in. Display only.
  - `best_time_reason` string, required — Why this time was picked, written by the planner for a plan-generated post. Empty unless something set it.
  - `hashtags` string[], required — Hashtags published after `body`, without the leading `#`. A leading `#` you send is stripped before publishing.
  - `image_url` string, nullable, required — HTTPS URL of the image published with the post, or `null` if it has none. An Instagram post needs one to publish.
  - `image_prompt` string, nullable, required — Prompt the post's image was generated from, or `null` if there is none. Kept for reference. This endpoint doesn't generate images from it.
  - `status` string, required — Where the post is in its lifecycle. Either `proposal`, `scheduled`, `publishing`, `posted`, `failed`, `publish_outcome_unknown`, `needs_reconnect`, or `not_materialized_plan_limit`. See [Scheduled posts](/developers/references/apps-api/sections/virality#scheduled-posts) for what each one means.
  - `workflow_id` string, nullable, required — ID of the automation that publishes this post, set once [Start scheduling posts](/api-reference/start-scheduling-posts) hands it over, and `null` before that. Its presence is what tells you the publish time is fixed.

## Other responses

- `401` — Missing or invalid credentials.
- `403` — You don't have editor access to this app, or you used a workspace API key.
- `404` — App not found, `plan_id` isn't the app's current plan, or the social calendar is not enabled for your account.
- `422` — Validation Error
- `429` — Rate limit exceeded (40 requests per minute), shared across every social calendar endpoint except the ones that create, edit, delete, or approve posts. See [Rate limits](/developers/references/apps-api/get-started/rate-limits).

---

[API](https://skmtc.dev/base44/apis/base44-app-management-api.md) · [All operations](https://skmtc.dev/base44/apis/base44-app-management-api/llms.txt) · [OpenAPI document](https://skmtc.dev/base44/apis/base44-app-management-api/revisions/cf164639a9bf?raw)
