# Edit, unpublish and delete

Change a post before it publishes, edit published text where the platform allows it, update YouTube video details, take posts down and pin Facebook posts.

What you can change depends on whether the post has gone live. Before publishing, almost everything is editable with one `PUT`. After publishing, you are limited to what each platform allows: some let you edit the text, a few let you delete, and some allow neither.

| You want to | Before it publishes | After it publishes |
| --- | --- | --- |
| Change text, media, accounts or time | `PUT /v1/posts/{postId}` | Text only, on some platforms: `POST /v1/posts/{postId}/edit` |
| Change a YouTube title, description or thumbnail | `PUT` with new `platformSpecificData` | `POST /v1/posts/{postId}/update-metadata` |
| Stop it from going out | `DELETE /v1/posts/{postId}`, or `PUT` with `isDraft: true` | Not applicable |
| Remove it from a platform | Not applicable | `POST /v1/posts/{postId}/unpublish` |
| Pin it on a Facebook Page | Not applicable | `POST /v1/posts/{postId}/pin` |

## Update a post before it publishes

`PUT /v1/posts/{postId}` works on `draft`, `scheduled`, `failed`, `partial` and `cancelled` posts. Send only the fields you want to change:

```bash cURL
curl -X PUT https://api.pozy.ai/v1/posts/6721a8c04e9b2f1d7c3a5e88 \
  -H "Authorization: Bearer $POZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Webinar moved to Thursday 18:00 CET. Same link, new time.",
    "scheduledFor": "2026-11-12T17:00:00Z"
  }'
```
```ts Node
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({
    content: "Webinar moved to Thursday 18:00 CET. Same link, new time.",
    scheduledFor: "2026-11-12T17:00:00Z",
  }),
});
const data = await res.json();
if (!res.ok) throw new Error(data.error);
console.log(data.post.status, data.post.scheduledFor);
```
```python Python
resp = requests.put(
    "https://api.pozy.ai/v1/posts/6721a8c04e9b2f1d7c3a5e88",
    headers={"Authorization": f"Bearer {os.environ['POZY_API_KEY']}"},
    json={
        "content": "Webinar moved to Thursday 18:00 CET. Same link, new time.",
        "scheduledFor": "2026-11-12T17:00:00Z",
    },
    timeout=30,
)
print(resp.json()["post"]["status"])
```

Rules to keep in mind:

- **Full validation runs again.** A non-draft update is checked against every target platform, exactly like a create. If the result breaks a platform rule, you get `400` and nothing changes.
- **Send the full `platforms` list.** When you include `platforms`, list every entry the post should end up with, not only the one you changed.
- **Settings objects are replaced whole.** A `platformSpecificData`, `tiktokSettings` or `facebookSettings` you send overwrites the stored one, so include every key you want to keep.
- **Drafts need `isDraft: false` to schedule.** See [Drafts and approvals](https://pozy.ai/docs/publishing/drafts-approvals).
- **Published posts are read-only,** except for their `recycling` settings.

To publish a scheduled post right away, update it with `publishNow: true`.

## Edit text after publishing

`POST /v1/posts/{postId}/edit` changes the text of a live post on one platform. Pass `accountId` when the post went to more than one account on that platform; without it, the first matching entry is edited.

```bash cURL
curl -X POST https://api.pozy.ai/v1/posts/6721a8c04e9b2f1d7c3a5e88/edit \
  -H "Authorization: Bearer $POZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "platform": "linkedin", "content": "Webinar moved to Thursday 18:00 CET (corrected time). Same link." }'
```
```ts Node
const res = await fetch("https://api.pozy.ai/v1/posts/6721a8c04e9b2f1d7c3a5e88/edit", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.POZY_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ platform: "linkedin", content: "Webinar moved to Thursday 18:00 CET (corrected time). Same link." }),
});
const data = await res.json();
if (!res.ok) throw new Error(data.error);
console.log(data.success, data.url);
```
```python Python
resp = requests.post(
    "https://api.pozy.ai/v1/posts/6721a8c04e9b2f1d7c3a5e88/edit",
    headers={"Authorization": f"Bearer {os.environ['POZY_API_KEY']}"},
    json={"platform": "linkedin", "content": "Webinar moved to Thursday 18:00 CET (corrected time). Same link."},
    timeout=30,
)
print(resp.json())
```

| Platform | Text edits | Notes |
| --- | --- | --- |
| X (`twitter`) | Yes, with limits | The account needs a paid X subscription. Within 1 hour of publishing, up to 5 times, single posts only (not threads). X gives the edited post a new id, returned as `id`. |
| Facebook | Yes | |
| LinkedIn | Yes | |
| YouTube | Yes | Edits the video description. For titles and other details use update-metadata (below). |
| Pinterest | Yes, where Pinterest allows it | Pinterest restricts pin edits to some accounts. |
| Google Business Profile | Yes | |
| Telegram, Discord, Slack | Yes | Edits the message in place. |
| Reddit | Yes | Publishing to Reddit is paused, see [Reddit](https://pozy.ai/docs/platforms/reddit). |
| Instagram, Threads, TikTok, Snapchat, Bluesky, WhatsApp | No | These platforms have no edit API. Unpublish and post again where possible. |

Media cannot be changed after publishing on any platform.

## Update a YouTube video's details

`POST /v1/posts/{postId}/update-metadata` changes a published YouTube video without uploading it again. Send `platform: "youtube"` and at least one of: `title` (100 characters), `description`, `tags`, `categoryId`, `privacyStatus` (`public`, `private`, `unlisted`), `thumbnailUrl`, `madeForKids`, `containsSyntheticMedia` or `playlistId`.

```json
{
  "platform": "youtube",
  "title": "Halving our build times (2026 update)",
  "privacyStatus": "public",
  "thumbnailUrl": "https://pozy.ai/media/temp/1730289600_y9u4_thumb.jpg"
}
```

It also works for videos uploaded outside Pozy: use `_` as the post id and send the YouTube `videoId` and the channel's `accountId` in the body. The response lists `updatedFields`.

## Take a post down

`POST /v1/posts/{postId}/unpublish` deletes the post from one platform. Pozy keeps the record, with its analytics and history.

```bash cURL
curl -X POST https://api.pozy.ai/v1/posts/6721a8c04e9b2f1d7c3a5e88/unpublish \
  -H "Authorization: Bearer $POZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "platform": "twitter", "accountId": "6710c3e2a9f14b0d8e5c7a23" }'
```
```ts Node
const res = await fetch("https://api.pozy.ai/v1/posts/6721a8c04e9b2f1d7c3a5e88/unpublish", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.POZY_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ platform: "twitter", accountId: "6710c3e2a9f14b0d8e5c7a23" }),
});
if (!res.ok) throw new Error((await res.json()).error);
```
```python Python
requests.post(
    "https://api.pozy.ai/v1/posts/6721a8c04e9b2f1d7c3a5e88/unpublish",
    headers={"Authorization": f"Bearer {os.environ['POZY_API_KEY']}"},
    json={"platform": "twitter", "accountId": "6710c3e2a9f14b0d8e5c7a23"},
    timeout=30,
).raise_for_status()
```

| Works on | Does not work on |
| --- | --- |
| Threads, Facebook, X, LinkedIn, YouTube, Pinterest, Bluesky, Google Business Profile, Telegram, Reddit | Instagram, TikTok, Snapchat |

- One call removes one platform. Repeat for each platform you want to clear.
- A thread is removed as a whole: every post of the thread on that platform is deleted.
- **YouTube deletions are permanent.** The video, its views and its comments are gone.
- When every copy is removed the post becomes `cancelled`. Until then it is `partial`.
- For Instagram and TikTok, the owner has to delete the post in the app. Pozy notices within about an hour and sends `post.platform.deleted`.

## Delete a post

`DELETE /v1/posts/{postId}` removes the post from Pozy. Use it to cancel a draft or a scheduled post before it goes out.

- It never touches the platforms. A published post returns `400`; unpublish it first, or keep the record for its analytics.
- It sends no webhook. If your app mirrors posts, remove the record on your side when the call succeeds.
- A post in `publishing` can only be stopped for entries that have not started uploading yet.

## Pin a Facebook post

`POST /v1/posts/{postId}/pin` pins a published post to the top of its Facebook Page, and `POST /v1/posts/{postId}/unpin` removes the pin. Send `platform: "facebook"` and, for posts that went to several Pages, the `accountId`. Other platforms return `400` with `code: "platform_not_supported"`.

## Endpoints

| Endpoint | What it does |
| --- | --- |
| [`PUT /v1/posts/{postId}`](https://pozy.ai/docs/api/updatePost) | Update post |
| [`POST /v1/posts/{postId}/edit`](https://pozy.ai/docs/api/editPost) | Edit published post |
| [`POST /v1/posts/{postId}/update-metadata`](https://pozy.ai/docs/api/updatePostMetadata) | Update post metadata |
| [`POST /v1/posts/{postId}/unpublish`](https://pozy.ai/docs/api/unpublishPost) | Unpublish post |
| [`DELETE /v1/posts/{postId}`](https://pozy.ai/docs/api/deletePost) | Delete post |
| [`POST /v1/posts/{postId}/pin`](https://pozy.ai/docs/api/pinPost) | Pin post |
| [`POST /v1/posts/{postId}/unpin`](https://pozy.ai/docs/api/unpinPost) | Unpin post |

## Webhook events

| Event | When it fires |
| --- | --- |
| [`post.cancelled`](https://pozy.ai/docs/webhooks/events#post-cancelled) | Post cancelled. |
| [`post.platform.deleted`](https://pozy.ai/docs/webhooks/events#post-platform-deleted) | Post platform deleted. |
