---
title: Posts
description: Create, list, retrieve, update, and delete scheduled and published social posts.
seo_title: "Posts API: schedule social media posts — Schedule & Chill"
published: 2026-06-07
updated: 2026-09-14
---

# Posts

Create and manage posts. A post targets one or more connected accounts and can be a draft, scheduled for later, or published immediately.

## The post object

| Field            | Type         | Description                                                                                            |
| ---------------- | ------------ | ------------------------------------------------------------------------------------------------------ |
| `id`             | integer      | Unique id.                                                                                             |
| `content`        | string       | Default text for all targeted accounts.                                                                |
| `status`         | string       | `draft`, `scheduled`, `published`, or `failed`.                                                        |
| `scheduled_at`   | string\|null | ISO 8601 publish time.                                                                                 |
| `published_at`   | string\|null | When it was sent.                                                                                      |
| `error_message`  | string\|null | Set when `status` is `failed`.                                                                         |
| `media`          | array        | Attached media objects.                                                                                |
| `socialAccounts` | array        | Targeted accounts, each with a `pivot` delivery record (`status`, `platform_post_id`, `platform_url`, `error_message`). |

Each account's `pivot.status` is one of `pending`, `publishing` (uploading/processing now), `published`, `failed`, or `blocked`. While a post is publishing, its top-level `status` stays `scheduled`; a `published` post that still has a `failed` account is a **partial** publish (partial is derived, not a stored status). Poll until no account is `pending` or `publishing`.

---

## Create a post

```
POST /api/posts
```

### Body parameters

| Parameter            | Type      | Required | Notes                                                             |
| -------------------- | --------- | -------- | ----------------------------------------------------------------- |
| `content`            | string    | yes      | Max 10,000 characters.                                            |
| `social_account_ids` | integer[] | yes      | At least one connected account id.                                |
| `scheduled_at`       | string    | no       | ISO 8601, must be in the future. Omit to publish now.             |
| `publish_now`        | boolean   | no       | Publish immediately instead of scheduling.                        |
| `media_ids`          | integer[] | no       | Media library ids to attach.                                      |
| `platform_content`   | array     | no       | Per-account overrides: `[{ "account_id": 789, "content": "…" }]`. |

### Example

```bash
curl -X POST https://schedulenchill.com/api/posts \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "content": "Big news for builders 🚀",
    "social_account_ids": [789, 790],
    "media_ids": [456],
    "scheduled_at": "2026-06-10T14:00:00Z",
    "platform_content": [
      { "account_id": 790, "content": "Big news for builders. Full thread below 🧵" }
    ]
  }'
```

Returns `201 Created` with the post object.

---

## List posts

```
GET /api/posts
```

Paginated, 20 per page. Optional filters:

| Query param | Description                                            |
| ----------- | ------------------------------------------------------ |
| `status`    | Filter by `draft`, `scheduled`, `published`, `failed`. |
| `from`      | Only posts scheduled on/after this date.               |
| `to`        | Only posts scheduled on/before this date.              |
| `per_page`  | Rows per page, 1–200. Over 200 returns 422.
| `page`      | Page number.                                           |

```bash
curl "https://schedulenchill.com/api/posts?status=scheduled&from=2026-06-01" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"
```

---

## Retrieve a post

```
GET /api/posts/{id}
```

Returns the post with its `media` and `socialAccounts` (including per-account delivery status).

---

## Update a post

```
PUT /api/posts/{id}
```

Only `draft` and `scheduled` posts can be updated. Accepts the same fields as create. Attempting to update a `published` post returns `422`.

---

## Delete a post

```
DELETE /api/posts/{id}
```

Deletes the post. Returns `204 No Content`. This is a **soft delete** — the post is
recoverable with the restore endpoint below.

A `scheduled` post returns `409 post_not_cancelable`: cancel it first, so stopping an
imminent publish is always a deliberate act rather than a side effect of a DELETE.

---

## Cancel a scheduled post

```
POST /api/posts/{id}/cancel
```

Stops a scheduled post before it publishes. Only posts in the `scheduled` state —
anything else returns `409 post_not_cancelable`. Soft delete, so restore undoes it.

---

## Publish now

```
POST /api/posts/{id}/publish-now
```

Publishes a `draft`, `scheduled` or `failed` post immediately. Anything else returns
`409 post_not_publishable`. Returns straight away — publishing runs in the background,
so poll `GET /api/posts/{id}` for the per-channel outcome.

A draft being promoted to live counts against the monthly post limit; a scheduled or
failed post already spent its slot and is not charged again.

---

## Retry the failed channels

```
POST /api/posts/{id}/retry
```

Resends only the channels whose own publish failed, leaving channels that already
published untouched — so a retry cannot double-post. Works on a partial outcome, where
the post reads `published` but at least one channel did not make it.

Returns `409 post_not_retryable` when nothing on the post failed.

---

## Duplicate a post

```
POST /api/posts/{id}/duplicate
```

Copies content, first comment, channels and media into a **new draft**. Nothing is
scheduled or sent. Channels disconnected since the original was written are dropped and
listed in `dropped_account_ids`. Returns `201` with the new post.

---

## Restore a post

```
POST /api/posts/{id}/restore
```

Undoes a cancel or a delete. A post whose scheduled time has already passed comes back
as a **draft** rather than re-armed, so restoring never publishes anything by itself.

Returns `409 post_not_deleted` if the post was never removed.
