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

# Posts e comentários

> O modelo Post, escopo feed vs grupo, quem pode criar, e como comentar e reagir via API.

Posts são a unidade de conteúdo da comunidade. Cada Post tem um **autor**, um **conteúdo** e um **escopo** (feed do tenant ou grupo específico). Comentários pendem de um Post, e reações (curtir/descurtir) pendem tanto de Posts quanto de Comentários. Todas as rotas abaixo são da API da Cativa, autenticadas por API Key no header `Authorization: Bearer cativa_live_...`.

Pense na estrutura como um mural: o **Post** é o cartaz que alguém prega; os **comentários** são os bilhetes colados embaixo dele; as **reações** são os "joinhas" que qualquer um dá no cartaz ou num bilhete. O mural pode ser o pátio inteiro (feed) ou uma sala fechada (grupo).

## O modelo Post

```
Post
├── author   (usuário associado à credencial autenticada)
├── content  (texto da publicação)
└── escopo
    ├── feed    → aparece no feed geral do tenant
    └── grupo   → aparece só dentro de um grupo específico
```

<Note>
  O autor do post é sempre o usuário associado à credencial autenticada. Você não envia (nem pode enviar) `authorId` no body. Veja [Identidade e usuários](/pt-BR/concepts/identity-and-users) para entender como a credencial resolve o autor.
</Note>

### Escopo: feed vs grupo

Um Post no **feed** é publicado no nível da comunidade e aparece para todos que enxergam o feed do tenant. Um Post de **grupo** vive dentro de um grupo específico e só aparece para quem tem acesso àquele grupo. A diferença está no endpoint de criação: feed usa `POST /community/posts`, grupo usa `POST /community/groups/{groupId}/posts`.

## Quem pode criar

A criação de Post usa a permissão **`CreatePost`**. Uma chave com escopo de admin cria em qualquer escopo (feed ou qualquer grupo). Uma chave de parceiro com escopo padrão cria em nome do usuário associado à credencial, e esse usuário precisa ter **acesso** ao grupo alvo (pelo menos um badge compatível, ou pertencer a um grupo aberto). Sem acesso, a chamada retorna `403 forbidden`.

<Note>
  Edição e exclusão de um Post são feitas **pelo autor**. Uma chave de admin também pode moderar. Um usuário comum não edita nem apaga o post de outro.
</Note>

## Posts

### Listar o feed

```bash theme={null}
curl "https://apis.cativalab.digital/tenant/api/v2/community/posts?page=1&pageSize=20" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Retorna o feed do tenant paginado. Use os parâmetros de paginação para percorrer as páginas. O schema completo de cada campo do response está na aba **API Reference** (tag "Post").

### Buscar um post

```bash theme={null}
curl https://apis.cativalab.digital/tenant/api/v2/community/posts/01HQ7Z3X4Y5Z6A7B8C9D0E1F2G \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Fluxo: publicar num grupo e repercutir

<Steps>
  <Step title="Descubra o groupId">
    Liste os grupos que o usuário enxerga (veja [Comunidades e espaços](/pt-BR/concepts/communities-and-spaces)) e guarde o `groupId` alvo. Sem acesso ao grupo, o passo seguinte retorna `403 forbidden`.
  </Step>

  <Step title="Crie o post no grupo">
    `POST /community/groups/{groupId}/posts` com o `content`. A resposta traz o `id` do post recém-criado.
  </Step>

  <Step title="Comente e reaja">
    Use o `id` do post para `POST .../comments` (comentar) e `POST .../reactions` (curtir). Reagir é idempotente: pode repetir sem duplicar.
  </Step>
</Steps>

### Criar um post no feed

O body traz o `content` da publicação. O exemplo abaixo é o caso mínimo plausível. O contrato exato (campos opcionais como anexos, mídia ou metadados) está na **API Reference** (tag "Post").

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://apis.cativalab.digital/tenant/api/v2/community/posts \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "content": "Bem-vindos ao feed da comunidade!"
    }'
  ```

  ```js Node theme={null}
  const res = await fetch('https://apis.cativalab.digital/tenant/api/v2/community/posts', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${apiKey}`,
      'Content-Type': 'application/json'
    },
    // content é o corpo do post. Campos extras (mídia, metadados) na API Reference.
    body: JSON.stringify({
      content: 'Bem-vindos ao feed da comunidade!'
    })
  });
  const post = await res.json();
  ```
</CodeGroup>

Resposta ilustrativa (o schema autoritativo fica na aba **API Reference**, tag "Post"):

```json theme={null}
{
  "post": {
    "id": "01HQ7Z3X4Y5Z6A7B8C9D0E1F2G",
    "userId": "01HQ0USER1234567890ABCDEF",
    "content": "Bem-vindos ao feed da comunidade!",
    "htmlContent": null,
    "title": null,
    "isPrivate": false,
    "allowComments": true,
    "groupId": null,
    "createdAt": "2026-07-10T14:32:00Z",
    "tags": []
  }
}
```

### Criar um post num grupo

Mesmo body, mas o `groupId` vai na rota. O post fica restrito ao grupo.

```bash theme={null}
curl -X POST https://apis.cativalab.digital/tenant/api/v2/community/groups/01HQ7Z3X4Y5Z6A7B8C9D0E1F2G/posts \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Aviso exclusivo do grupo."
  }'
```

### Editar um post

Apenas o autor (ou uma chave de admin) edita. O `postId` vai na rota.

```bash theme={null}
curl -X PUT https://apis.cativalab.digital/tenant/api/v2/community/posts/01HQ7Z3X4Y5Z6A7B8C9D0E1F2G \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Conteúdo atualizado."
  }'
```

### Excluir um post

```bash theme={null}
curl -X DELETE https://apis.cativalab.digital/tenant/api/v2/community/posts/01HQ7Z3X4Y5Z6A7B8C9D0E1F2G \
  -H "Authorization: Bearer YOUR_API_KEY"
```

## Comentários

Comentários pendem de um Post. O `postId` está sempre na rota. Mesma regra de acesso: o usuário associado à credencial precisa enxergar o Post para comentar.

### Listar comentários de um post

```bash theme={null}
curl https://apis.cativalab.digital/tenant/api/v2/community/posts/01HQ7Z3X4Y5Z6A7B8C9D0E1F2G/comments \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Comentar num post

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://apis.cativalab.digital/tenant/api/v2/community/posts/01HQ7Z3X4Y5Z6A7B8C9D0E1F2G/comments \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "content": "Adorei o post!"
    }'
  ```

  ```js Node theme={null}
  const postId = '01HQ7Z3X4Y5Z6A7B8C9D0E1F2G';
  const res = await fetch(
    `https://apis.cativalab.digital/tenant/api/v2/community/posts/${postId}/comments`,
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${apiKey}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ content: 'Adorei o post!' })
    }
  );
  const comment = await res.json();
  ```
</CodeGroup>

Resposta ilustrativa (schema completo na **API Reference**, tag "Comment"):

```json theme={null}
{
  "comment": {
    "id": "01HQ8A1B2C3D4E5F6G7H8J9K0L",
    "userId": "01HQ0USER1234567890ABCDEF",
    "postId": "01HQ7Z3X4Y5Z6A7B8C9D0E1F2G",
    "replyToId": null,
    "content": "Adorei o post!",
    "gifUrl": null,
    "createdAt": "2026-07-10T14:40:00Z"
  }
}
```

### Editar e excluir um comentário

Mesma regra do Post: só o autor (ou admin) altera. `postId` e `commentId` vão na rota.

```bash theme={null}
# Editar
curl -X PUT https://apis.cativalab.digital/tenant/api/v2/community/posts/01HQ7Z3X4Y5Z6A7B8C9D0E1F2G/comments/01HQ8A1B2C3D4E5F6G7H8J9K0L \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "content": "Comentário corrigido." }'

# Excluir
curl -X DELETE https://apis.cativalab.digital/tenant/api/v2/community/posts/01HQ7Z3X4Y5Z6A7B8C9D0E1F2G/comments/01HQ8A1B2C3D4E5F6G7H8J9K0L \
  -H "Authorization: Bearer YOUR_API_KEY"
```

## Reações

Reagir (curtir) e desreagir (descurtir) é um **par idempotente**. Curtir duas vezes deixa o estado igual a curtir uma vez. Descurtir algo que já não está curtido não dá erro. Isso simplifica retries em jobs e webhook handlers. O schema da reação está na **API Reference** (tag "Reaction").

### Curtir e descurtir um post

```bash theme={null}
# Curtir
curl -X POST https://apis.cativalab.digital/tenant/api/v2/community/posts/01HQ7Z3X4Y5Z6A7B8C9D0E1F2G/reactions \
  -H "Authorization: Bearer YOUR_API_KEY"

# Descurtir
curl -X DELETE https://apis.cativalab.digital/tenant/api/v2/community/posts/01HQ7Z3X4Y5Z6A7B8C9D0E1F2G/reactions \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Reagir a um comentário

Reações de comentário usam o `commentId` na rota, não o `postId`.

```bash theme={null}
# Reagir
curl -X POST https://apis.cativalab.digital/tenant/api/v2/community/comments/01HQ8A1B2C3D4E5F6G7H8J9K0L/reactions \
  -H "Authorization: Bearer YOUR_API_KEY"

# Remover reação
curl -X DELETE https://apis.cativalab.digital/tenant/api/v2/community/comments/01HQ8A1B2C3D4E5F6G7H8J9K0L/reactions \
  -H "Authorization: Bearer YOUR_API_KEY"
```

## Erros comuns e dúvidas

<AccordionGroup>
  <Accordion title="Recebi 403 forbidden ao criar um post num grupo">
    O usuário associado à credencial não tem acesso àquele grupo. Acesso a grupo vem de **badge** (ou de o grupo ser aberto). Atribua o badge exigido pelo grupo ao usuário (veja [Badges como permissão](/pt-BR/concepts/badges-as-permissions)) e repita. Uma chave de admin passa por cima dessa regra e cria em qualquer grupo.
  </Accordion>

  <Accordion title="Curtir duas vezes conta como dois likes?">
    Não. Reagir e desreagir são um **par idempotente**: curtir de novo deixa o estado igual a curtir uma vez, e descurtir algo que não estava curtido não dá erro. Isso torna seguro reprocessar um webhook ou dar retry num job sem inflar a contagem.
  </Accordion>

  <Accordion title="Posso editar ou apagar o post de outro usuário?">
    Não com uma chave de escopo padrão. Edição e exclusão são **do autor**. Tentar alterar o post de outro usuário retorna `403 forbidden`. Só uma chave de admin modera conteúdo alheio.
  </Accordion>

  <Accordion title="Como envio o autor do post?">
    Você não envia. O autor é sempre o usuário resolvido pela credencial autenticada; não existe campo `authorId` no body. Para postar em nome de outra pessoa, use a chave de admin dela ou o mecanismo de identidade (veja [Identidade e usuários](/pt-BR/concepts/identity-and-users)).
  </Accordion>

  <Accordion title="Deletei um post e os comentários sumiram junto?">
    Sim. Comentários e reações pendem do Post: ao excluir o Post, o que pendia dele deixa de ser acessível. Não há como "recuperar" pela API pública; trate a exclusão como definitiva do ponto de vista da integração.
  </Accordion>
</AccordionGroup>

## Próximos passos

<CardGroup cols={3}>
  <Card title="Comunidades e espaços" icon="layer-group" href="/pt-BR/concepts/communities-and-spaces">
    Onde os grupos vivem e como descobrir o `groupId` antes de postar.
  </Card>

  <Card title="Identidade e usuários" icon="user" href="/pt-BR/concepts/identity-and-users">
    Como a credencial resolve o autor do post e do comentário.
  </Card>

  <Card title="Evento post.created" icon="webhook" href="/pt-BR/webhooks/events/post-created">
    Receba um webhook toda vez que um post é criado.
  </Card>
</CardGroup>
