Saltar al contenido principal
Desarrolladores Actualizaciones en directo

Actualiza mensajes en directo

Un mensaje no tiene por qué quedarse como se publicó. Muestra el progreso mientras se ejecuta un trabajo, cambia un loader por el resultado, quita los botones cuando alguien ya ha decidido, o bórralo. Todos en el canal ven el cambio al instante.

Qué puedes hacer

  • Actualiza la tarjetaCambia el texto, el color y los botones, en el mismo sitio.
  • Muestra el progresoUn loader que avanza por los pasos y después el resultado.
  • BórraloQuita un mensaje cuando ya no es cierto.
  • EscúchaloRespuestas, reacciones y pulsaciones de botón en tu mensaje, en directo.

En la app

Publicada con un loader

Actualizada: paso 2 de 3

Actualizada: hecho, con un botón

Un mensaje, actualizado dos veces a través de su callback URL. Nadie ve tres mensajes, solo uno que cambia.

Inicio rápido

  1. Guarda la callback URL

    Cada publicación de webhook y cada petición de comando trae una callback_url para ese mensaje.

    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-..."}
  2. PUT para actualizar

    Envía el nuevo estado. La tarjeta cambia en el mismo sitio 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."}}'
  3. DELETE para borrar

    No hace falta cuerpo.

    bash
    curl -X DELETE "$CALLBACK_URL"

Actualizar un mensaje

Envía JSON con PUT a la callback_url. Envía solo lo que quieras cambiar.

CampoTipoQué hace
message_containerobjectLa nueva tarjeta. Consulta tarjetas de mensaje.
actionsarrayBotones nuevos. "actions": [] los quita todos; si omites el campo, se mantienen.
contentstringTexto nuevo.
title, description, color, loader, ...stringAtajo: los campos de tarjeta en el nivel superior se envuelven en una tarjeta por ti.
Un message_container nuevo sustituye la tarjeta anterior entera: un campo que omitas desaparece. Solo se conservan su tipo, su nombre y su avatar. Así que envía siempre la tarjeta completa.

Respuestas

EstadoCódigoSignificado
200{"success": true}Aceptado. La actualización llega justo después.
400MISSING_FIELDSNo hay nada que actualizar en el cuerpo.
400INVALID_BODYEl cuerpo no es JSON válido.
400un código de botónAlgo falla en un botón, consulta botones.
401INVALID_TOKENLa URL no es válida.
404TOKEN_NOT_FOUNDLa URL ha caducado o se ha usado para borrar el mensaje.
502PUBLISH_FAILEDNo se ha podido entregar la actualización. Vuelve a intentarlo.

Cuánto tiempo funciona

30 minutos desde el momento en que se publicó el mensaje o se usó el comando. Actualizar no lo alarga. Borrar el mensaje agota la URL. No se pueden añadir archivos con una actualización.

Mostrar el progreso

Publica una tarjeta con un loader, actualiza su texto secundario a medida que avanza el trabajo y termina con el resultado. El loader es un spinner con una línea y otra más pequeña debajo (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' }]
});

Borrar un mensaje

Envía DELETE a la callback_url y el mensaje desaparece para todos. Después, la URL ya no se puede volver a usar.

Escuchar un mensaje

Una stream_url es un stream en directo (Server-Sent Events) de lo que pasa en tu mensaje. Ábrelo y los eventos llegan en cuanto ocurren, cada uno como una línea JSON data: cuyo type dice qué es:

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: {}
EventoCuándoDatos
actionSe ha pulsado un botón.action_id, y el botón guardado en action con su payload
reactionSe ha añadido o quitado una reacción.emoji, y action: add, remove o removeall
replyAlguien ha respondido al mensaje.El content de la respuesta
expiredEl stream se está cerrando. Se envía como evento con nombre.Ninguno
Los eventos no se guardan para después. Abre el stream en cuanto tengas la URL: lo que pase antes de conectarte no se envía. Cada evento lleva también el message_id, quién lo hizo (member_guid, member) y cuándo (ts). Una línea de comentario cada 20 segundos mantiene abierta la conexión.

Escuchar en 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();
});

De dónde sacas una

De dónde saleAbierto durante
Una publicación de webhook con botones10 minutos, o una hora con "sse_event_extended_timeout": true
Cada petición de comando10 minutos

Errores

EstadoCódigoSignificado
401INVALID_TOKENEl token de la URL es incorrecto.
404NOT_FOUNDEl stream ha caducado o nunca existió.

Sigue construyendo