Edit a message
PATCH https://balena.zulipchat.com/api/v1/messages/{message_id}
Update the content, topic, or channel of the message with the specified
ID.
You can resolve topics by editing the topic to
✔ {original_topic}
with the propagate_mode
parameter set to
"change_all"
.
See configuring message editing for detailed
documentation on when users are allowed to edit message content, and
restricting moving messages for detailed
documentation on when users are allowed to change a message's topic
and/or channel.
The relevant realm settings in the API that are related to the above
linked documentation on when users are allowed to update messages are:
allow_message_editing
can_move_messages_between_channels_group
can_move_messages_between_topics_group
message_content_edit_limit_seconds
move_messages_within_stream_limit_seconds
move_messages_between_streams_limit_seconds
More details about these realm settings can be found in the
POST /register
response or in the documentation
of the realm op: update_dict
event in GET /events
.
Changes: In Zulip 10.0 (feature level 316), edit_topic_policy
was removed and replaced by can_move_messages_between_topics_group
realm setting.
Changes: In Zulip 10.0 (feature level 310), move_messages_between_streams_policy
was removed and replaced by can_move_messages_between_channels_group
realm setting.
Prior to Zulip 7.0 (feature level 172), anyone could add a
topic to channel messages without a topic, regardless of the organization's
topic editing permissions. As of this
feature level, messages without topics have the same restrictions for
topic edits as messages with topics.
Before Zulip 7.0 (feature level 172), by using the change_all
value for
the propagate_mode
parameter, users could move messages after the
organization's configured time limits for changing a message's topic or
channel had passed. As of this feature level, the server will return an
error with "code":
"MOVE_MESSAGES_TIME_LIMIT_EXCEEDED"
if users, other than organization
administrators or moderators, try to move messages after these time
limits have passed.
Before Zulip 7.0 (feature level 162), users who were not administrators or
moderators could only edit topics if the target message was sent within the
last 3 days. As of this feature level, that time limit is now controlled by
the realm setting move_messages_within_stream_limit_seconds
. Also at this
feature level, a similar time limit for moving messages between channels was
added, controlled by the realm setting
move_messages_between_streams_limit_seconds
. Previously, all users who
had permission to move messages between channels did not have any time limit
restrictions when doing so.
Before Zulip 7.0 (feature level 159), editing channels and topics of messages
was forbidden if the realm setting for allow_message_editing
was false
,
regardless of an organization's configuration for the realm settings
edit_topic_policy
or move_messages_between_streams_policy
.
Before Zulip 7.0 (feature level 159), message senders were allowed to edit
the topic of their messages indefinitely.
In Zulip 5.0 (feature level 75), the edit_topic_policy
realm setting
was added, replacing the allow_community_topic_editing
boolean.
In Zulip 4.0 (feature level 56), the move_messages_between_streams_policy
realm setting was added.
Usage examples
#!/usr/bin/env python3
import zulip
# Pass the path to your zuliprc file here.
client = zulip.Client(config_file="~/zuliprc")
# Edit a message. Make sure that `message_id` is set to the ID of the
# message you wish to update.
request = {
"message_id": message_id,
"content": "New content",
}
result = client.update_message(request)
print(result)
More examples and documentation can be found here.
const zulipInit = require("zulip-js");
// Pass the path to your zuliprc file here.
const config = { zuliprc: "zuliprc" };
(async () => {
const client = await zulipInit(config);
// Update a message with the given "message_id"
const params = {
message_id,
content: "New Content",
};
console.log(await client.messages.update(params));
})();
curl -sSX PATCH https://balena.zulipchat.com/api/v1/messages/43 \
-u BOT_EMAIL_ADDRESS:BOT_API_KEY \
--data-urlencode topic=Castle \
--data-urlencode propagate_mode=change_all \
--data-urlencode send_notification_to_old_thread=true \
--data-urlencode send_notification_to_new_thread=true \
--data-urlencode content=Hello
Parameters
message_id integer required in path
Example: 43
topic string optional
Example: "Castle"
The topic to move the message(s) to, to request changing the topic.
Clients should use the max_topic_length
returned by the
POST /register
endpoint to determine
the maximum topic length
Should only be sent when changing the topic, and will throw an error
if the target message is not a channel message.
Changes: New in Zulip 2.0.0. Previous Zulip releases encoded
this as subject
, which is currently a deprecated alias.
propagate_mode string optional
Example: "change_all"
Which message(s) should be edited:
"change_later"
: The target message and all following messages.
"change_one"
: Only the target message.
"change_all"
: All messages in this topic.
Only the default value of "change_one"
is valid when editing
only the content of a message.
This parameter determines both which messages get moved and also whether
clients that are currently narrowed to the topic containing the message
should navigate or adjust their compose box recipient to point to the
post-edit channel/topic.
Must be one of: "change_one"
, "change_later"
, "change_all"
.
Defaults to "change_one"
.
send_notification_to_old_thread boolean optional
Example: true
Whether to send an automated message to the old topic to
notify users where the messages were moved to.
Changes: Before Zulip 6.0 (feature level 152), this parameter
had a default of true
and was ignored unless the channel was changed.
New in Zulip 3.0 (feature level 9).
Defaults to false
.
send_notification_to_new_thread boolean optional
Example: true
Whether to send an automated message to the new topic to
notify users where the messages came from.
If the move is just resolving/unresolving a topic,
this parameter will not trigger an additional notification.
Changes: Before Zulip 6.0 (feature level 152), this parameter
was ignored unless the channel was changed.
New in Zulip 3.0 (feature level 9).
Defaults to true
.
content string optional
Example: "Hello"
The updated content of the target message.
Clients should use the max_message_length
returned by the
POST /register
endpoint to determine
the maximum message size.
Note that a message's content and channel cannot be changed at the
same time, so sending both content
and stream_id
parameters will
throw an error.
stream_id integer optional
Example: 43
The channel ID to move the message(s) to, to request moving
messages to another channel.
Should only be sent when changing the channel, and will throw an error
if the target message is not a channel message.
Note that a message's content and channel cannot be changed at the
same time, so sending both content
and stream_id
parameters will
throw an error.
Changes: New in Zulip 3.0 (feature level 1).
Response
Return values
-
detached_uploads
: (object)[]
Details on all files uploaded by the acting user whose only references
were removed when editing this message. Clients should ask the acting user
if they wish to delete the uploaded files returned in this response,
which might otherwise remain visible only in message edit history.
Note that access to message edit
history is configurable; this detail
may be important in presenting the question clearly to users.
New in Zulip 10.0 (feature level 285).
-
id
: integer
The unique ID for the attachment.
-
name
: string
Name of the uploaded file.
-
path_id
: string
A representation of the path of the file within the
repository of user-uploaded files. If the path_id
of a
file is {realm_id}/ab/cdef/temp_file.py
, its URL will be:
{server_url}/user_uploads/{realm_id}/ab/cdef/temp_file.py
.
-
size
: integer
Size of the file in bytes.
-
create_time
: integer
Time when the attachment was uploaded as a UNIX timestamp
multiplied by 1000 (matching the format of getTime() in JavaScript).
Changes: Changed in Zulip 3.0 (feature level 22). This field was
previously a floating point number.
-
messages
: (object)[]
Contains basic details on any Zulip messages that have been
sent referencing this uploaded file.
This includes messages sent by any user in the Zulip
organization who sent a message containing a link to the
uploaded file.
-
date_sent
: integer
Time when the message was sent as a UNIX timestamp
multiplied by 1000 (matching the format of getTime() in JavaScript).
Changes: Changed in Zulip 3.0 (feature level 22). This
field was previously strangely called name
and was a floating
point number.
-
id
: integer
The unique message ID. Messages should always be
displayed sorted by ID.
Example response(s)
Changes: As of Zulip 7.0 (feature level 167), if any
parameters sent in the request are not supported by this
endpoint, a successful JSON response will include an
ignored_parameters_unsupported
array.
A typical successful JSON response may look like:
{
"detached_uploads": [
{
"create_time": 1687984706000,
"id": 3,
"messages": [],
"name": "1253601-1.jpg",
"path_id": "2/5d/BD5NRptFxPDKY3RUKwhhup8r/1253601-1.jpg",
"size": 1339060
}
],
"msg": "",
"result": "success"
}
A typical JSON response for when one doesn't have the permission to
edit a particular message:
{
"code": "BAD_REQUEST",
"msg": "You don't have permission to edit this message",
"result": "error"
}
A special failed JSON response ("code": "MOVE_MESSAGES_TIME_LIMIT_EXCEEDED"
)
for when the user has permission to move
the target message, but asked to move all messages in a topic
("propagate_mode": "change_all"
) and the user does not have permission
to move the entire topic.
This happens when the topic contains some messages that are older than an
applicable time limit for the requested topic move (see
move_messages_within_stream_limit_seconds
and/or
move_messages_between_streams_limit_seconds
in the
POST /register
response).
The error response contains data on which portion of this topic the user has
permission to move. first_message_id_allowed_to_move
is the oldest message
ID in this topic that the user has permission to move.
There are total_messages_in_topic
in the topic, but the user only has
permission to move the (most recent) total_messages_allowed_to_move
messages.
Clients should support this error code with
"first_message_id_allowed_to_move": null
for forward compatibility
with future server versions that may use this error code with other
propagation modes where the user does not have permission to move any
messages, or where the server did not calculate the total message counts
noted above.
Clients can either only present the error to the user or, if
first_message_id_allowed_to_move
is not null
, prompt the user to adjust
their query with the above information.
If clients choose to present a prompt for this error code, they should
recommend the option of cancelling and (manually) asking a moderator to
move the entire topic, since that's often a better experience than
partially moving a topic. This API supports a client that wishes to allow
the user to repeat the request with a change_later
propagation mode and
a target message ID of first_message_id_allowed_to_move
, if the user
desires to move only the portion of the topic that they can.
Note that in a channel with protected history,
the Zulip security model requires that the above calculations only include
messages the acting user has access to. So in the rare case of a user
attempting to move a topic that started before the user joined a private
channel with protected history, this API endpoint might move only the portion
of a topic that they have access to, without this error or any confirmation
dialog.
Changes: New in Zulip 7.0 (feature level 172).
{
"code": "MOVE_MESSAGES_TIME_LIMIT_EXCEEDED",
"first_message_id_allowed_to_move": 123,
"msg": "You only have permission to move the 2/5 most recent messages in this topic.",
"result": "error",
"total_messages_allowed_to_move": 2,
"total_messages_in_topic": 5
}
An example JSON error response for when the message was rejected because
of the organization's wildcard_mention_policy
and large number of
subscribers to the channel.
Changes: New in Zulip 8.0 (feature level 229). Previously, this
error returned the "BAD_REQUEST"
code.
{
"code": "STREAM_WILDCARD_MENTION_NOT_ALLOWED",
"msg": "You do not have permission to use channel wildcard mentions in this channel.",
"result": "error"
}
An example JSON error response for when the message was rejected because
the message contains a topic wildcard mention, but the user doesn't have
permission to use such a mention in this topic due to the
wildcard_mention_policy
(and large number of participants in this
specific topic).
Changes: New in Zulip 8.0 (feature level 229). Previously,
wildcard_mention_policy
was not enforced for topic mentions.
{
"code": "TOPIC_WILDCARD_MENTION_NOT_ALLOWED",
"msg": "You do not have permission to use topic wildcard mentions in this topic.",
"result": "error"
}