Skip to content

Edit and delete messages

Both operations act on a message you already sent. The message_id is the same msg_{hex32} returned by the original send or seen in webhooks/polling. Both return 202 Accepted immediately; the actual result arrives asynchronously via webhook.

Use POST /v1/messages/{id}/edit and POST /v1/messages/{id}/delete for the main number. For extra numbers, use POST /v1/numbers/{ref}/messages/{id}/edit and .../delete.

Required scope: messages:send

Before editing or deleting, Turbo Notify opens the conversation the way a person would: the number shows as online, the unread messages in the chat the target message belongs to are marked as read, and only then does the edit or deletion happen. See Mark as read.

What can be changed after sending

MessageEditDelete for everyone
TextYes. Send the new text.Yes
Image, video or documentYes, the caption only. Send the new caption.Yes
Calendar eventYes, the whole event is replaced, or the event is canceled.Yes
Location, contact card, link button, sticker or audioNoYes, the only change

The file of an image, video or document never changes. To send a different file, send a new message. Only messages sent through the API by this number can be changed (origin: "tn").

A text or a caption can only be changed within 15 minutes of sending it, which is WhatsApp’s own limit. After that the API answers 400 edit_window_expired, and the way out is to send a new message. The 15 minutes do not apply to a calendar event, although WhatsApp may still refuse an event edit (the outcome arrives as message.edit.failed).

Edit a message

Replaces the text of a text message you already sent (native WhatsApp editing: the conversation history shows “edited”). To change the caption of an image, video or document, see the caption section. To edit or cancel a calendar event, see the event section.

edit-message.sh
curl -X POST \
https://api.turbonotify.com/v1/numbers/NUMBER_ALIAS/messages/msg_01993c5a1b24d3e9f01a2b3c4d5e6f70/edit \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "Corrected message text."
}'

Request body

FieldTypeRequiredNotes
textstringyes1 to 4,096 characters. The only accepted field: the body is strict (any other field returns 422).

Response (202)

HTTP status: 202
{
  "message_id": "msg_01993c5a1b24d3e9f01a2b3c4d5e6f70",
  "status": {
    "state": "pending",
    "at": "2026-06-01T13:05:01Z",
    "error": null
  }
}

The actual result arrives via the message.edited webhook (success) or message.edit.failed (failure, with an error object). After the edit, GET /v1/numbers/{ref}/messages/{id} already returns the updated text.

Mentions in edits

The new text of the edit (and the new caption, see Edit a caption) also goes through @<number> mention detection, with the same rules as Mentions (@mentions). The edit replaces the message’s whole set of mentions: the mentions returned by GET /v1/numbers/{ref}/messages/{id} (and the data.mentions of the message.edited webhook) then reflects only the tokens present in the new text. An edit that removes every @<number> from the original text makes mentions disappear from the response.

Edit a caption

Replaces the caption of an image, video or document your number sent. Use the same edit route and send caption instead of text. The recipient sees the new caption marked as “edited”. The file stays as it was and the message keeps its id.

edit-caption.sh
curl -X POST \
https://api.turbonotify.com/v1/numbers/NUMBER_ALIAS/messages/msg_01993c5a1b24d3e9f01a2b3c4d5e6f70/edit \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"caption": "Invoice for October, corrected total."
}'

Request body (caption)

FieldTypeRequiredNotes
captionstringyes1 to 1,024 characters. It replaces the whole caption and cannot be empty. Accepts the same @<number> mentions as the caption of a send. The only accepted field: any other field returns 422.

Response and outcome

The response is the same as for any edit: 202 with the message_id and the pending status. The outcome arrives by webhook (or by polling):

  • message.edited when the caption was changed. It carries the content_type of the message (image, video or document) and the new caption in preview (up to 50 characters, as with text).
  • message.edit.failed when the edit was not made.

Captions edited in the WhatsApp app also arrive as message.edited, with origin: "native", the content_type of the file and the new caption in preview.

The edit does not consume the message quota. A caption body on a text message, a text body on an image, or any body on a message that cannot be edited answers 400 message_not_editable.

Edit or cancel a calendar event

A calendar event your number sent (see Send a calendar event) can also be edited or canceled. Use the same edit route and send the event body instead of text. The name field tells the API the body is an event.

The edit replaces the whole event: whatever you do not send is removed from it. That is why name and start_at are required, as when sending, and why an edit without location removes the place.

edit-event.sh
curl -X POST \
https://api.turbonotify.com/v1/numbers/NUMBER_ALIAS/messages/msg_01993c5a1b24d3e9f01a2b3c4d5e6f70/edit \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Sprint Planning",
"description": "Planning for sprint 24. New room.",
"start_at": "2026-11-05T15:00:00Z",
"end_at": "2026-11-05T16:00:00Z",
"join_link": "https://meet.example.com/abc",
"location": {
"latitude": -23.5505,
"longitude": -46.6333,
"name": "HQ - Blue Room"
}
}'

Request body (event)

The fields are the same as in sending a calendar event, without the content object, plus canceled.

FieldTypeRequiredNotes
namestringyesevent title; up to 200 characters (the field that marks the body as an event)
start_atdatetimeyesISO-8601 with time zone
end_atdatetimenoISO-8601 with time zone; must be > start_at
descriptionstringnoup to 2000 characters
locationobjectnosame format as the location object of a send
join_linkstringnohttp:///https:// only
has_reminderboolnodefaults to false
reminder_offset_secintnoseconds before the event; only takes effect with has_reminder=true
extra_guests_allowedboolnodefaults to false
canceledboolnodefaults to false. With true, the event is canceled.

Cancel the event

Send "canceled": true in the same body. The event stays in the chat, shows as canceled, and WhatsApp notifies the guests.

cancel-event.sh
curl -X POST \
https://api.turbonotify.com/v1/numbers/NUMBER_ALIAS/messages/msg_01993c5a1b24d3e9f01a2b3c4d5e6f70/edit \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Sprint Planning",
"start_at": "2026-11-05T15:00:00Z",
"canceled": true
}'

Response and outcome

The response is the same as for any edit: 202 with the message_id and the pending status. The outcome arrives by webhook (or by polling):

  • message.edited when the event was changed. It carries content_type: "calendar", the event name in preview, and canceled: true only when the event was canceled.
  • message.edit.failed when the edit was not made. With error.code set to message_secret_unavailable, this number can no longer change the event, for example because it was linked again after the event was sent. Send a new event with the new details. With calendar_edit_unavailable, the platform cannot change events at the moment and repeating the request does not help: send a new event with the new details. WhatsApp may also refuse an edit after some time, and the outcome is then the same message.edit.failed.

Examples of each event are in Calendar events.

Rules

  • Only an event sent by this number can be edited, and only in status sent, delivered or read.
  • A body that does not fit the message (text on a calendar event, an event on a text message, a caption on a text) answers 400 message_not_editable.
  • A message from another number answers 404 not_found.
  • The edit does not consume the message quota.

What happens to the guests

SituationWhat to do
A correction: typo, description or linkEdit the event. The card shows the change and a guest who already answered keeps the answer.
The date, time or location changed and guests must accept the new conditionsCancel the event and send a new one. The new message draws the guest’s attention, and the old answer (“Going”) does not carry over.

Neither an edit nor a cancel changes the entry a guest created in their own calendar with the “Add to calendar” button: it stays on the old date and is not marked as canceled, and adding it again creates a second entry. Ask the guest to delete the old entry.

Delete (revoke) a message

Revokes a message you already sent (the same as “Delete for everyone” on WhatsApp). The request body is empty.

delete-message.sh
curl -X POST \
https://api.turbonotify.com/v1/numbers/NUMBER_ALIAS/messages/msg_01993c5a1b24d3e9f01a2b3c4d5e6f70/delete \
-H "Authorization: Bearer YOUR_KEY"

Response (202)

HTTP status: 202
{
  "message_id": "msg_01993c5a1b24d3e9f01a2b3c4d5e6f70",
  "status": {
    "state": "pending",
    "at": "2026-06-01T13:06:01Z",
    "error": null
  }
}

The actual result arrives via the message.deleted webhook (success) or message.delete.failed (failure, with an error object).

After a successful deletion, GET /v1/numbers/{ref}/messages/{id} no longer returns the original content, both for whoever deleted it and for every recipient of the message. The message’s content_type does not change: what changes is the content of the matching structured field:

Original content_typeAffected fieldValue after deletion
texttext"" (empty string)
image / video / audio / document / stickerimage / video / audio / document / sticker{"kind": "unavailable", "reason": "deleted"}: the media is no longer reachable via signed URL
locationlocation{"kind": "unavailable", "reason": "deleted"}
calendarcalendar{"kind": "unavailable", "reason": "deleted"}
contactcontact{"kind": "unavailable", "reason": "deleted"}
interactiveinteractive{"kind": "unavailable", "reason": "deleted"}

Every type other than text uses the same object, so “this content is no longer available” has a single format, whatever the content_type.

Possible errors

Both endpoints share the same set of errors:

StatusError codeDescription
400message_not_editable(edit only) The message was received (sent by someone else), was sent from the phone itself (origin: "native"), is not a text, a calendar event or the caption of an image, video or document, the body does not fit the message (text on an event, an event on a text, a caption on a text), has not been sent yet, was already deleted, or its current status (failed, for example) does not allow editing. Only text messages, calendar events and the caption of an image, video or document can be edited.
400edit_window_expired(edit only) More than 15 minutes have passed since a text or a caption was sent, the time WhatsApp gives to change them. Send a new message. The 15 minutes do not apply to a calendar event.
400message_not_deletable(delete only) The message was received (sent by someone else), was sent from the phone itself (origin: "native"), has not been sent yet, was already deleted, or its current status does not allow deletion.
401not_authenticatedThe API key is invalid or missing.
403insufficient_scopeThe API key does not have the messages:send scope (the response includes required_scope).
404number_not_foundThe alias or id in the URL does not match any registered number.
400invalid_number_idThe value in the URL starts with num_ but is not a valid number id.
404not_foundThe message was not found, belongs to another organization, or belongs to a number other than the one in the URL (on the shortcut route without {ref}, the main number): all of these cases return the same response, with no distinction.
404request_not_foundThe message could no longer be found while the edit or deletion was being processed. Look up the message with GET and, if it still exists, try again.
409number_not_connectedThe number that sent the message is not connected to WhatsApp. Reconnect the number and try again.
500internal_errorUnexpected internal server error.

Which messages can be edited or deleted

The message must meet the criteria below. If it fails any one, the request is rejected immediately, with 400 message_not_editable / 400 message_not_deletable (or 400 edit_window_expired, for the edit time limit), before any contact with WhatsApp:

  1. Sent by this number, through this API: the message must have been sent through the Turbo Notify API by this number (direction: "outbound" and origin: "tn"). Two kinds of message are excluded by this criterion:
    • Received messages: messages a contact or participant sent to you. They belong to the sender, not to you, and WhatsApp does not let you edit or revoke a message you did not send.
    • Messages typed on the phone itself (origin: "native"), sent outside the API, directly on the device. Turbo Notify is not the client that originated that message, so it cannot edit or revoke it either.
  2. Content type (edit only): WhatsApp only allows editing text messages, the caption of an image, video or document, and calendar events, and the request body must match the message: text for a text message, caption for an image, video or document, the event fields (name, start_at) for an event. Editing audio, a sticker or another type (location, contact card, link button) fails with 400 message_not_editable: for those, deleting is the only change.
  3. Status: only messages that are already sent, delivered or read, and that have not been deleted yet, are accepted. Messages still pending, already failed, or already deleted return 400 message_not_editable / 400 message_not_deletable.
  4. Time limit (text and caption edits only): a text or a caption can only be changed within 15 minutes of sending it. After that the answer is 400 edit_window_expired. The 15 minutes do not apply to a calendar event.

See also: Get a message · Message status · Webhook.