# Read and manage posts

List, check, edit, reschedule, cancel, and safely retry posts with current tokens.

Use `client.posts` to read and manage posts.

## List posts

```ts
const page = await client.posts.list({
  limit: 25,
  status: "scheduled",
});

if (page.nextCursor) {
  const nextPage = await client.posts.list({
    cursor: page.nextCursor,
    limit: 25,
    status: "scheduled",
  });
}
```

Treat `nextCursor` as opaque text. Keep the same filters when you request the next page.

## Check a plan

```ts
const result = await client.posts.check({
  content: {
    mode: "shared",
    text: "A safe release update.",
    destinations: [{ channelId }],
  },
  publication: { state: "draft" },
});

if (!result.ready) {
  console.log(result.issues);
}
```

The check does not create a post, queue work, contact a provider, or use an approval.

## Use current tokens

Get the post before a command:

```ts
const post = await client.posts.get(postId);
const channel = post.channels.find((item) => item.channelId === channelId);

if (!channel) throw new Error("Channel is not on this post.");
```

Use `post.editToken` for an edit. Use `channel.controlToken` for reschedule, cancel, or retry. Each successful command returns a new token.

## Edit

```ts
const edited = await client.posts.edit(
  postId,
  {
    confirmed: true,
    content: {
      segments: [{ blocks: [{ type: "text", text: "Updated copy." }] }],
    },
    editToken: post.editToken,
  },
  { idempotencyKey: crypto.randomUUID() },
);
```

## Reschedule

```ts
const result = await client.posts.reschedule(
  postId,
  {
    channelId,
    confirmed: true,
    controlToken: channel.controlToken,
    publishAt: "2026-09-04T16:00:00.000Z",
  },
  { idempotencyKey: crypto.randomUUID() },
);
```

## Cancel

```ts
await client.posts.cancel(
  postId,
  {
    channelId,
    confirmed: true,
    controlToken: channel.controlToken,
  },
  { idempotencyKey: crypto.randomUUID() },
);
```

## Retry a failed destination

```ts
if (channel.status === "failed") {
  await client.posts.retry(
    postId,
    {
      channelId,
      confirmed: true,
      controlToken: channel.controlToken,
      publishAt: "2026-09-04T16:05:00.000Z",
    },
    { idempotencyKey: crypto.randomUUID() },
  );
}
```

Beacon rejects retry for `publishing`, `checking`, `delayed`, `reconnect_required`, `partially_published`, and `published` results. The SDK does not retry writes automatically.
