---
title: "Atualizações ao vivo: mude mensagens do mssgs após publicar"
description: "Atualize ou apague uma mensagem do mssgs depois de publicada pela callback URL, mostre o progresso com um loader e ouça respostas, reações e botões ao vivo."
canonical: https://docs.mss.gs/pt/live-updates
language: pt
---

# Atualize mensagens ao vivo

Uma mensagem não precisa ficar como foi publicada. Mostre o progresso enquanto um job roda, troque um loader pelo resultado, tire os botões quando alguém já decidiu ou apague a mensagem. Todos no canal veem a mudança na hora.

## O que você pode fazer

- **Atualize o cartão** Mude o texto, a cor e os botões, no mesmo lugar.

- **Mostre o progresso** Um loader que passa pelas etapas, e depois o resultado.

- **Apague** Remova uma mensagem quando ela deixar de ser verdade.

- **Escute** Respostas, reações e toques em botões na sua mensagem, ao vivo.

No app

Publicado com um loader

Atualizado: etapa 2 de 3

#### Deploy concluído

Atualizado: concluído, com um botão

Uma mensagem, atualizada duas vezes pela callback URL dela. Ninguém vê três mensagens, só uma que muda.

- [Início rápido](#quick-start)

- [Atualizar](#update)

- [Mostrar progresso](#progress)

- [Apagar](#delete)

- [Escutar](#stream)

## Início rápido

### Guarde a callback URL

Toda publicação por [webhook](https://docs.mss.gs/pt/webhooks) e toda requisição de [comando](https://docs.mss.gs/pt/commands) vem com uma callback_url para aquela mensagem.

```bash
BODY='{"message_container": {"color": "blue", "loader": true, "loader_text": "Deploying…"}}'
SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$MSSGS_WEBHOOK_SECRET" | sed 's/^.* //')

curl -X POST "$MSSGS_WEBHOOK_URL" -H "Content-Type: application/json" \
  -H "X-Mssgs-Signature: sha256=$SIG" -d "$BODY"

# {"success": true, "message_id": "...", "callback_url": "https://mss.gs/api/v1/trigger-callback/8f14e45f-..."}
```

### PUT para atualizar

Envie o novo estado. O cartão muda no mesmo lugar para todos.

```bash
curl -X PUT "$CALLBACK_URL" -H "Content-Type: application/json" \
  -d '{"message_container": {"color": "green", "title": "Deploy complete", "description": "v2.1 is live."}}'
```

### DELETE para remover

Não precisa de corpo.

```bash
curl -X DELETE "$CALLBACK_URL"
```

## Atualizar uma mensagem

Faça um PUT de JSON na callback_url . Envie só o que você quer mudar.

| Campo | Tipo | O que faz |
| --- | --- | --- |
| message_container | object | O novo cartão. Veja [cartões de mensagem](https://docs.mss.gs/pt/bots). |
| actions | array | Novos botões. "actions": [] tira todos; deixar o campo de fora mantém os atuais. |
| content | string | Novo texto. |
| title , description , color , loader , ... | string | Atalho: campos de cartão no nível superior são embrulhados num cartão para você. |

### Respostas

| Status | Código | Significado |
| --- | --- | --- |
| 200 | {"success": true} | Aceito. A atualização vem logo em seguida. |
| 400 | MISSING_FIELDS | Nada para atualizar no corpo. |
| 400 | INVALID_BODY | O corpo não é um JSON válido. |
| 400 | um código de botão | Há algo errado com um botão, veja [botões](https://docs.mss.gs/pt/buttons). |
| 401 | INVALID_TOKEN | A URL não é válida. |
| 404 | TOKEN_NOT_FOUND | A URL expirou ou foi usada para apagar a mensagem. |
| 502 | PUBLISH_FAILED | A atualização não pôde ser entregue. Tente de novo. |

### Por quanto tempo funciona

30 minutos a partir do momento em que a mensagem foi publicada, ou em que o comando foi usado. Atualizar não prolonga esse prazo. Apagar a mensagem esgota a URL. Não é possível adicionar arquivos por uma atualização.

## Mostrar progresso

Publique um cartão com um loader, atualize o subtexto dele à medida que o job avança e termine com o resultado. O loader é um spinner com uma linha e uma linha menor embaixo ( loader_text , loader_sub_text ).

```javascript
const { callback_url } = await post({
  message_container: { color: 'blue', loader: true, loader_text: 'Deploying…', loader_sub_text: 'Step 1 of 3: building' }
});

const update = (body) => {
  return fetch(callback_url, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) });
};

await build();
await update({ message_container: { color: 'blue', loader: true, loader_text: 'Deploying…', loader_sub_text: 'Step 2 of 3: running migrations' } });

await migrate();
await update({
  message_container: { color: 'green', title: 'Deploy complete', description: 'v2.1 is live on production.' },
  actions: [{ type: 'url:https://ci.example.com/deploys/218', text: 'View logs', color: 'green' }]
});
```

## Apagar uma mensagem

Envie DELETE para a callback_url e a mensagem some para todos. Depois disso, a URL não pode ser usada de novo.

## Escutar uma mensagem

Uma stream_url é um stream ao vivo (Server-Sent Events) do que acontece na sua mensagem. Abra-a e os eventos chegam na hora em que acontecem, cada um como uma linha JSON data: cujo type diz o que ele é:

```sse
curl -N "$STREAM_URL"

data: {"type": "reaction", "message_id": "...", "emoji": ":tada:", "action": "add", "member_guid": "...", "member": {...}, "ts": 1790000000000}

data: {"type": "action", "message_id": "...", "action_id": "approve", "action": {"id": "approve", "payload": {"deploy": 218}, ...}, "member_guid": "...", "member": {...}, "ts": 1790000004200}

data: {"type": "reply", "message_id": "...", "content": "Ship it!", "member_guid": "...", "member": {...}, "ts": 1790000009800}

event: expired
data: {}
```

| Evento | Quando | Dados |
| --- | --- | --- |
| action | Um botão foi tocado. | action_id , e o botão guardado em action com o payload dele |
| reaction | Uma reação foi adicionada ou removida. | emoji , e action : add, remove ou removeall |
| reply | Alguém respondeu à mensagem. | O content da resposta |
| expired | O stream está fechando. Enviado como evento nomeado. | Nenhum |

### Escutando em JavaScript

```javascript
const events = new EventSource(streamUrl);

// Every event arrives as a plain message; its kind is in "type".
events.onmessage = (e) => {
  const ev = JSON.parse(e.data);
  if ((ev.type === 'action') && (ev.action_id === 'approve')) {
    startDeploy(ev.action.payload.deploy);
  }
};

// The one named event: the stream is closing.
events.addEventListener('expired', () => {
  events.close();
});
```

### Onde você recebe uma

| De onde vem | Aberto por |
| --- | --- |
| Uma publicação por webhook com botões | 10 minutos, ou uma hora com "sse_event_extended_timeout": true |
| Toda requisição de comando | 10 minutos |

### Erros

| Status | Código | Significado |
| --- | --- | --- |
| 401 | INVALID_TOKEN | O token na URL está errado. |
| 404 | NOT_FOUND | O stream expirou ou nunca existiu. |

## Continue criando
