> ## Documentation Index
> Fetch the complete documentation index at: https://docs.postclean.com.br/llms.txt
> Use this file to discover all available pages before exploring further.

# Publicação

> Crie, agende e publique posts pela API: destinos, configurações por rede, modos de agendamento, respostas em fio e limites de conteúdo.

Este guia acompanha um post do começo ao fim: encontrar o canal, conferir o que a rede dele exige, criar o post e depois agendá-lo, colocá-lo na fila ou publicá-lo na hora. Todos os exemplos rodam em `https://post.chatclean.com.br/api` com uma [chave de API do workspace](https://docs.postclean.com.br/api-reference/introduction.md).

**1. Liste as contas sociais**

Encontre o canal em que vai publicar e veja os limites dele.

**2. Confira os tipos de conteúdo**

Escolha um formato e preencha as configurações que a rede exige.

**3. Crie o post**

Um post por canal, ou uma chamada para vários canais.

**4. Agende, coloque na fila ou publique**

Num horário definido, na fila do canal ou agora.

## 1. Liste as contas sociais

[Listar contas sociais](https://docs.postclean.com.br/api-reference/social-accounts/list-social-accounts.md) devolve os canais conectados ao workspace. Os canais são conectados e removidos no app; a API só os lê.

```bash theme={null}
curl https://post.chatclean.com.br/api/social-accounts \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"
```

```json theme={null}
{
  "data": [
    {
      "id": "9c8b7a65-4d3e-4f2a-8b1c-0d9e8f7a6b54",
      "platform": "x",
      "display_name": "PostClean",
      "username": "postclean",
      "status": "connected",
      "has_posting_schedule": true,
      "timezone": "America/Sao_Paulo",
      "posting_goal": 5,
      "max_content_length": 280,
      "long_posts": false,
      "verified_badge": null
    }
  ],
  "links": { "...": "..." },
  "meta": { "...": "..." }
}
```

Os campos que importam para publicar:

| Campo | Uso |
| - | - |
| `id` | O `social_account_id` do post |
| `platform` | A rede, que define os tipos de conteúdo e as configurações abaixo |
| `status` | Só contas `connected` publicam. Contas `disconnected` e `token_expired` precisam ser reconectadas no app |
| `max_content_length` | O limite de texto desta conta. Contas do X com posts longos (`long_posts: true`) têm 25000 em vez de 280 |
| `has_posting_schedule` | Se o canal tem horários de publicação, que a fila precisa |
| `timezone` | O fuso horário do canal. Os horários da fila e as recorrências seguem esse fuso |

## 2. Confira os tipos de conteúdo

[Listar tipos de conteúdo](https://docs.postclean.com.br/api-reference/platform/list-content-types.md) descreve cada rede: seus tipos de conteúdo, limites de texto e de hashtags, as configurações obrigatórias e a mídia que cada formato aceita.

```bash theme={null}
curl https://post.chatclean.com.br/api/content-types \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"
```

Leia estes campos antes de montar um post:

| Campo | Significado |
| - | - |
| `default_content_type` | O formato usado quando você omite `content_type` |
| `content_types[].value` | O valor a enviar em `content_type`, por exemplo `instagram_reel` |
| `required_meta` | Configurações que precisam estar em `meta` antes de o post poder ser agendado ou publicado |
| `max_content_length` | O limite de texto da rede. O que vale é o limite da própria conta (`max_content_length` na conta social) |
| `max_hashtags` | Limite de hashtags: `5` no Instagram, `null` nas demais redes |
| `content_types[].captionless` | `true` quando o formato não envia texto (Stories do Instagram e do Facebook) |
| `content_types[].supports_thread_replies` | `true` quando o formato aceita respostas em fio (X, Bluesky e Mastodon), com `max_thread_replies` (24) |
| `content_types[].requires_media`, `min_media_count`, `max_media_count` | A mídia que o formato exige |

Quando você omite `content_type`, ele é escolhido como no app: no Pinterest, um vídeo vira `pinterest_video_pin` e várias imagens viram `pinterest_carousel`; no TikTok, só imagens viram `tiktok_photo`; as outras redes usam o formato padrão.

### Configurações obrigatórias

O post leva as configurações da rede em `meta`. Um rascunho pode ser salvo sem elas; agendar ou publicar exige que estejam preenchidas:

| Rede | Obrigatório em `meta` | Onde conseguir o valor |
| - | - | - |
| TikTok | `privacy_level`: `PUBLIC_TO_EVERYONE`, `MUTUAL_FOLLOW_FRIENDS`, `FOLLOWER_OF_CREATOR` ou `SELF_ONLY` | [Ver dados de criador do TikTok](https://docs.postclean.com.br/api-reference/social-accounts/get-tiktok-creator-info.md) lista os níveis que a conta permite |
| Pinterest | `board_id` | [Listar pastas do Pinterest](https://docs.postclean.com.br/api-reference/social-accounts/list-pinterest-boards.md) ou [Criar pasta do Pinterest](https://docs.postclean.com.br/api-reference/social-accounts/create-pinterest-board.md) |
| Discord | `channel_id` | [Listar canais do Discord](https://docs.postclean.com.br/api-reference/social-accounts/list-discord-channels.md) |
| YouTube | Um título: `title`, ou a primeira linha do texto | Até 100 caracteres, sem `<` nem `>` |
| Google Business | `event` com `title`, `start_date` e `end_date` quando `topic_type` é `EVENT` ou `OFFER`; um `call_to_action` precisa de `url`, a menos que o `action_type` seja `NONE` ou `CALL` | Definido por você |

As demais configurações são opcionais: prévias de links, rótulos de conteúdo gerado por IA, privacidade e categoria no YouTube, avisos de conteúdo no Mastodon, tópicos no Threads e outras. A lista completa por rede está em `meta` em [Criar post](https://docs.postclean.com.br/api-reference/posts/create-post.md). Chaves que o PostClean não conhece são descartadas; configurações de outra rede são aceitas, mas não são usadas.

## 3. Crie o post

[Criar post](https://docs.postclean.com.br/api-reference/posts/create-post.md) cria um post em **um** canal: envie em `platforms` uma lista com exatamente um item, com o `social_account_id` do canal e, ao lado dele, o `content_type` e o `meta`. Sem `status`, o post é salvo como rascunho.

```bash theme={null}
curl -X POST https://post.chatclean.com.br/api/posts \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Our autumn collection is live.",
    "media": [
      { "url": "https://example.com/autumn.jpg", "alt": "Three jackets on a rail" }
    ],
    "platforms": [
      {
        "social_account_id": "2b7e4c19-8f3a-4d6b-9c1e-5a0f7d2b8e63",
        "content_type": "pinterest_pin",
        "meta": {
          "board_id": "1084231546543210987",
          "link": "https://example.com/autumn"
        }
      }
    ]
  }'
```

A resposta é o post (`201`), com `status: "draft"` e o canal em `platforms`: cada item traz `id`, `platform`, `content_type`, `meta`, `status` (o andamento na rede, começando em `pending`) e `social_account`. A mídia pode vir de uma URL, de um upload anterior ou de outro post; veja [Envio de mídia](https://docs.postclean.com.br/api-reference/guides/media-uploads.md).

### Vários canais de uma vez

Para enviar o mesmo post a vários canais, use [Criar posts em lote](https://docs.postclean.com.br/api-reference/posts/create-posts-in-batch.md). Ele cria um post independente por destino, todos com o mesmo `post_group_id`, igual a selecionar vários canais no app. Cada destino pode sobrescrever o `content`, a `media`, o `content_type` e o `meta` compartilhados. Aqui o `status` é obrigatório.

```bash theme={null}
curl -X POST https://post.chatclean.com.br/api/posts/batch \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "scheduled",
    "scheduled_at": "2026-10-12T14:00:00Z",
    "content": "Our autumn collection is live.",
    "media": [{ "url": "https://example.com/autumn.jpg" }],
    "destinations": [
      { "social_account_id": "9c8b7a65-4d3e-4f2a-8b1c-0d9e8f7a6b54" },
      {
        "social_account_id": "5d1f8a27-3c6e-4b9d-a2f0-7e4c1b8d6a35",
        "content_type": "tiktok_photo",
        "meta": { "privacy_level": "PUBLIC_TO_EVERYONE" }
      }
    ]
  }'
```

A resposta é `{ "posts": [...] }`, um post por destino. Um erro de validação interrompe a chamada inteira; os erros indicam o destino, por exemplo `destinations.1.meta.privacy_level`.

## 4. Agende, coloque na fila ou publique

O `status` decide o que acontece com o post. Envie-o na criação ou depois, com [Atualizar post](https://docs.postclean.com.br/api-reference/posts/update-post.md):

| `status` | Resultado |
| - | - |
| `draft` | Salvo e editável. Numa atualização, desfaz o agendamento de um post agendado (o último `scheduled_at` continua no rascunho) |
| `scheduled` | Publicado no `scheduled_at`, ou na fila do canal com `queue` / `queue_slot` |
| `publishing` | Publicado agora |

### Num horário definido

Envie `status: scheduled` com `scheduled_at`, um instante no futuro e antes de `2038-01-19`. Informe-o em UTC (`Z`) ou com fuso.

```json theme={null}
{
  "status": "scheduled",
  "scheduled_at": "2026-10-12T14:00:00Z"
}
```

### Na fila do canal

Quando o canal tem horários de publicação (`has_posting_schedule: true`), envie `queue` no lugar de `scheduled_at`:

* `next` pega o primeiro horário livre do canal.
* `top` pega o primeiro horário que não esteja ocupado por um post com horário definido e passa os posts da fila que estão atrás dele para o próximo horário livre.

```json theme={null}
{
  "status": "scheduled",
  "queue": "next"
}
```

Para ocupar um horário exato, envie `queue_slot` com um instante tirado de [Listar horários livres da fila](https://docs.postclean.com.br/api-reference/channels/list-free-queue-slots.md). Isso só funciona em [Criar post](https://docs.postclean.com.br/api-reference/posts/create-post.md) e falha com `422` quando o horário foi ocupado nesse meio-tempo. `queue` não pode ser combinado com `scheduled_at` nem com `queue_slot`. Quando você envia `queue_slot`, é ele que define o horário; não envie `scheduled_at` junto.

Um post na fila mantém o horário dele. Para mudar a ordem, use [Reordenar a fila](https://docs.postclean.com.br/api-reference/channels/reorder-queue.md) ou [Mover post para um horário da fila](https://docs.postclean.com.br/api-reference/channels/move-post-to-queue-slot.md); para mudar os horários, [Atualizar horários de postagem](https://docs.postclean.com.br/api-reference/channels/update-posting-schedule.md) (ele substitui a programação inteira: envie o `timezone` (obrigatório) e o `posting_goal` e o `posting_schedule` atuais para mantê-los, porque os valores omitidos são apagados). Para repetir um post agendado, veja [Definir repetição do post](https://docs.postclean.com.br/api-reference/recurrence/set-post-recurrence.md).

> [!NOTE]
>
> Outra alteração na mesma fila do canal pode estar rodando quando você chamar. Nesse caso a API responde `409`; repita a requisição.

### Agora

Envie `status: publishing`, na criação ou num rascunho ou post agendado que já existe:

```bash theme={null}
curl -X PUT https://post.chatclean.com.br/api/posts/9d3c1f2a-6b4e-4c8a-9f1e-2a7b5c8d0e41 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{ "status": "publishing" }'
```

A resposta volta com `status: "publishing"` enquanto a rede recebe o post. Depois ele passa a `published` ou `failed` (`partially_published` em posts antigos com vários destinos, quando só parte deles saiu). O lado da rede fica em `platforms[].status` (`pending`, `publishing`, `retrying`, `pending_review`, `published`, `failed` ou `rejected`); `platforms[].platform_url` leva ao post publicado e `platforms[].error_message` diz o que deu errado. Consulte [Ver post](https://docs.postclean.com.br/api-reference/posts/get-post.md) periodicamente ou inscreva um [webhook](https://docs.postclean.com.br/api-reference/webhooks/create-webhook.md) em `post.published` e `post.failed`.

Posts criados pela API são publicados direto: as chaves de API pertencem a administradores do workspace, então não há etapa de aprovação (veja [Aprovações](https://docs.postclean.com.br/api-reference/introduction.md)).

## Respostas em fio

Posts no X, no Bluesky e no Mastodon podem levar até **24** respostas, publicadas uma embaixo da outra, abaixo do primeiro post. Envie-as em `platforms[0].meta.thread_replies`, cada uma como `{ "text", "media" }`:

```json theme={null}
{
  "content": "1/ We rebuilt scheduling from scratch. Here is what changed.",
  "status": "scheduled",
  "queue": "next",
  "platforms": [
    {
      "social_account_id": "9c8b7a65-4d3e-4f2a-8b1c-0d9e8f7a6b54",
      "content_type": "x_post",
      "meta": {
        "thread_replies": [
          { "text": "2/ Every channel now has its own posting times." },
          {
            "text": "3/ Full changelog below.",
            "media": [{ "url": "https://example.com/changelog.png" }]
          }
        ]
      }
    }
  ]
}
```

* Uma resposta precisa de texto ou de mídia.
* O texto de cada resposta precisa caber no limite da conta: 280 no X (25000 com posts longos), 300 no Bluesky e 500 no Mastodon. No Mastodon, o aviso de conteúdo (`spoiler_text`) se repete em cada resposta e entra na contagem.
* A mídia de uma resposta pertence só a ela: até 4 itens, informados por `url`, `id` ou `upload_token`, seguindo as regras de mídia da rede.
* Em [Atualizar post](https://docs.postclean.com.br/api-reference/posts/update-post.md), `thread_replies` substitui a lista inteira.

Se a publicação parar no meio, as respostas já publicadas são mantidas, e uma nova tentativa continua da próxima, sem publicá-las de novo.

## Limites de conteúdo

Os limites da rede são conferidos quando um post é agendado ou publicado; rascunhos podem passar deles. O teto de 25000 caracteres vale para todo post, inclusive rascunhos.

* **Texto por conta.** O texto precisa caber no `max_content_length` da conta, medido no texto que a rede recebe. Uma conta do X com posts longos aceita 25000 caracteres; as outras contas do X aceitam 280. Um emoji conta como um caractere.
* **Hashtags no Instagram.** O Instagram aceita no máximo **5** hashtags por post.
* **Stories não têm legenda.** `instagram_story` e `facebook_story` não enviam texto, então o texto deles não é publicado nem medido, e o limite de hashtags não se aplica.
* **Mídia.** Cada tipo de conteúdo tem suas próprias regras de quantidade, tamanho, duração e proporção de mídia, listadas por [Listar tipos de conteúdo](https://docs.postclean.com.br/api-reference/platform/list-content-types.md) e na página de cada rede, por exemplo [Instagram](https://docs.postclean.com.br/platforms/instagram.md), [X](https://docs.postclean.com.br/platforms/x-twitter.md) ou [TikTok](https://docs.postclean.com.br/platforms/tiktok.md).

> [!TIP]
>
> [Ver prévia do post](https://docs.postclean.com.br/api-reference/posts/get-post-preview.md) devolve o texto que o canal do post vai receber (`sanitized_content`), o tamanho dele e o limite da conta.

## Edição, exclusão e erros

* [Atualizar post](https://docs.postclean.com.br/api-reference/posts/update-post.md) altera só os campos que você envia. O canal é fixo (`social_account_id` é recusado); para publicar em outro lugar, crie um novo post. Envie as configurações como `content_type` e `meta` no nível de cima, ou em `platforms`, com o `id` do item de `platforms` do post. O `meta` é mesclado com as configurações salvas, chave por chave; envie `null` numa chave para apagá-la. `thread_replies` substitui a lista inteira.
* Posts em `publishing`, `published`, `partially_published` ou `failed` não podem ser editados: a API responde `422` com `Este post já foi processado e não pode ser republicado. Duplique-o para tentar de novo.`
* [Excluir post](https://docs.postclean.com.br/api-reference/posts/delete-post.md) remove o post só do PostClean e nunca apaga nada numa rede. Só posts que ainda não foram enviados podem ser excluídos; os demais respondem `422` em `post` com `Posts enviados não podem ser excluídos.`
* Os erros de validação vêm com o campo como chave. Em [Criar post](https://docs.postclean.com.br/api-reference/posts/create-post.md) e [Atualizar post](https://docs.postclean.com.br/api-reference/posts/update-post.md), o formato dos campos é conferido em `platforms.0.*` (`platforms.0.content_type`, `platforms.0.meta.board_id`) e nos campos do nível de cima (`content`, `media`); as checagens feitas ao montar o post (configuração obrigatória da rede, formato que não combina com a mídia, falta de texto e de mídia) voltam em `destinations.0.*`, por exemplo `destinations.0.meta.board_id`. Em [Criar posts em lote](https://docs.postclean.com.br/api-reference/posts/create-posts-in-batch.md), tudo o que é de um destino vem em `destinations.N.*`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.