waiaconnect

Documentazione / Completo

Messaggi modificati ed eliminati

Markdown

Programmi con l'IA? Collegala al tuo account via MCP: controlla la tua configurazione, crea webhook e modelli con la tua conferma e scrive il codice. Scopri come →

Quando un contatto modifica un messaggio (per esempio, per correggere un importo), ti arriva message.edited; quando lo elimina, message.revoked. Entrambi portano originalMessageId: il wamid del messaggio originale, lo stesso data.message.id che ti è arrivato nel suo message.received. Con quello aggiorni la riga che hai già salvato.

Cosa arriva dipende dal tipo di numero (lo decide Meta):

Numero in coesistenza (app + API). Modifica → message.edited con textAvailable: true e data.message = la versione finale (testo, o foto/video con la nuova didascalia), con la stessa forma di message.received. Eliminazione → message.revoked.

Numero solo Cloud API. Modifica → message.edited con textAvailable: false, message: null e reason: "META_EDIT_TEXT_NOT_PROVIDED": Meta segnala la modifica ma non invia il nuovo testo. Eliminazione → Meta non la segnala.

WhatsApp permette di modificare solo entro 15 minuti dall'invio (e di eliminare, fino a 2 giorni). Una modifica senza testo è un limite di Meta: non c'è modo di chiedere il testo dopo.

Il testo precedente non lo conserviamo (WAIA Connect non salva il contenuto dei messaggi): se ti serve, è nel tuo database, sotto originalMessageId.

# Nothing to call: WAIA Connect POSTs message.edited / message.revoked to your webhook.
# Read a saved body: the final text (or null when Meta did not send it) and the original id.
jq -r 'if .type == "message.edited"
  then "\(.data.originalMessageId) edited -> " + (if .data.textAvailable then (.data.message.text.body // .data.message.image.caption // .data.message.video.caption // "") else "(text not provided by Meta)" end)
  else "\(.data.originalMessageId) deleted" end' body.json
// Inside your webhook handler, after verifying the signature.
const evt = req.body;
if (evt.type === "message.edited") {
  const d = evt.data;
  if (d.textAvailable) {
    const m = d.message; // same shape as message.received → data.message
    const text = m.text?.body ?? m.image?.caption ?? m.video?.caption ?? null;
    await db.messages.update({ wamid: d.originalMessageId }, { text, editedAt: d.editedAt }); // your code
  } else {
    // Cloud API-only number: Meta says it was edited but sends no text (reason META_EDIT_TEXT_NOT_PROVIDED)
    if (d.originalMessageId) await db.messages.update({ wamid: d.originalMessageId }, { editedAt: d.editedAt, textOutdated: true });
  }
} else if (evt.type === "message.revoked") {
  await db.messages.update({ wamid: evt.data.originalMessageId }, { deletedAt: evt.data.revokedAt }); // your code
}
<?php
// Inside your webhook handler, after verifying the signature.
$evt = json_decode(file_get_contents("php://input"), true);
$d = $evt["data"] ?? [];
if ($evt["type"] === "message.edited") {
  if ($d["textAvailable"]) {
    $m = $d["message"]; // same shape as message.received → data.message
    $text = $m["text"]["body"] ?? $m["image"]["caption"] ?? $m["video"]["caption"] ?? null;
    update_message($d["originalMessageId"], ["text" => $text, "edited_at" => $d["editedAt"]]); // your code
  } elseif ($d["originalMessageId"]) {
    // Cloud API-only number: Meta sends no text (reason META_EDIT_TEXT_NOT_PROVIDED)
    update_message($d["originalMessageId"], ["edited_at" => $d["editedAt"], "text_outdated" => true]);
  }
} elseif ($evt["type"] === "message.revoked") {
  update_message($d["originalMessageId"], ["deleted_at" => $d["revokedAt"]]); // your code
}
# Inside your webhook handler, after verifying the signature.
evt = request.get_json()
d = evt.get("data", {})
if evt["type"] == "message.edited":
    if d["textAvailable"]:
        m = d["message"]  # same shape as message.received -> data.message
        text = (m.get("text") or {}).get("body") or (m.get("image") or {}).get("caption") or (m.get("video") or {}).get("caption")
        update_message(d["originalMessageId"], text=text, edited_at=d["editedAt"])  # your code
    elif d["originalMessageId"]:
        # Cloud API-only number: Meta sends no text (reason META_EDIT_TEXT_NOT_PROVIDED)
        update_message(d["originalMessageId"], edited_at=d["editedAt"], text_outdated=True)
elif evt["type"] == "message.revoked":
    update_message(d["originalMessageId"], deleted_at=d["revokedAt"])  # your code

Un webhook creato prima di questi eventi con «tutti gli eventi» non li riceve da solo: scegli di nuovo «tutti» (PATCH con events: null, o il pulsante della sua riga nel pannello) o aggiungili all'elenco. newEventsAvailable dice quali mancano.

Un endpoint che riceve message.edited/message.revoked non riceve più quella modifica o eliminazione grezza come message.received (type: "edit", "revoke" o "unsupported"). Uno che non li riceve resta come prima.

originalConnectMessageId è il nostro msg_… quando hai inviato l'originale tramite l'API; per un messaggio del contatto è null.

Deduplica come qualsiasi evento: per l'id della busta (evt_…).