Get desktop application:
View/edit binary Protocol Buffers messages
Remove an existing message. Note: This is a soft-security feature at best and it applies a best effort approach, meaning that it relies on some level of good will on the receiving end. A malicious receiver can easily persist a message prior to removal by e.g. making a screenshot, forwarding it, changing the date, explicitly saving it (if it contains media), etc. **Properties (1:1)**: - Kind: 1:1 - Flags: - `0x01`: Send push notification. - User profile distribution: No - Exempt from blocking: No - Implicit _direct_ contact creation: No - Protect against replay: Yes - Unarchive: No - Bump _last update_: No - Reflect: - Incoming: Yes - Outgoing: Yes - _Sent_ update: No - Delivery receipts: No - Reactions: No - Edit applies to: N/A - Deletable by: N/A (obviously) - When rejected: N/A (ignored) - Send to Threema Gateway ID group creator: N/A **Properties (Group)**: - Kind: Group - Flags: - `0x01`: Send push notification. - User profile distribution: No - Exempt from blocking: No - Implicit _direct_ contact creation: No - Protect against replay: Yes - Unarchive: No - Bump _last update_: No - Reflect: - Incoming: Yes - Outgoing: Yes - _Sent_ update: No - Delivery receipts: N/A - Reactions: No - Edit applies to: N/A - Deletable by: N/A (obviously) - When rejected: N/A (ignored) - Send to Threema Gateway ID group creator: If capture is enabled The following steps must be invoked when the user wants to delete a 1:1 message: 1. If the sender or the receiver do not have `DELETE_MESSAGE_SUPPORT`, disallow removal and abort these steps. 2. Run the _Common Delete Message Preflight Steps_. 3. Let `deleted-at` be the current timestamp. 4. Run the _1:1 Messages Submit Steps_ with `messages` set from the following properties: - `created-at` set to `deleted-at`, - to construct a `DeleteMessage` message. 5. Replace the referred message with a message informing the user that the referred message of the user has been removed at `deleted-at`.² The following steps must be invoked when the user wants to delete a group message. 1. If the group is marked as _left_, disallow removal and abort these steps. 2. If the sender or all of the group members do not have `DELETE_MESSAGE_SUPPORT`, disallow removal and abort these steps. 3. Run the _Common Delete Message Preflight Steps_. 4. If any of the group members do not have `DELETE_MESSAGE_SUPPORT`, notify the user that the affected contacts will continue to see the message. 5. Let `deleted-at` be the current timestamp. 6. Run the _Group Messages Submit Steps_ with `messages` set from the following properties: - `created-at` set to `deleted-at`, - to construct a `DeleteMessage` message (wrapped by [`group-member-container`](ref:e2e.group-member-container)). 7. Replace the referred message with a message informing the user that the referred message of the user has been removed at `deleted-at`.² The following steps are defined as the _Common Delete Message Preflight Steps_: 1. Let `message` be the referred message. 2. If the user is not the original sender of `message`, disallow removal and abort these steps. 3. If `message` has been sent (`sent-at`) more than 6 hours ago, disallow removal and abort these steps.¹ When reflected from another device as an incoming or outgoing 1:1 message: 1. Run the _Common Delete Message Receive Steps_. When receiving this message as a 1:1 message: 1. Run the _Common Delete Message Receive Steps_. When reflected from another device as an incoming or outgoing group message: 1. Run the _Common Delete Message Receive Steps_. When receiving this message as a group message (wrapped by [`group-member-container`](ref:e2e.group-member-container)): 1. Run the [_Common Group Receive Steps_](ref:e2e#receiving). If the message has been discarded, abort these steps. 2. Run the _Common Delete Message Receive Steps_. The following steps are defined as the _Common Delete Message Receive Steps_: 1. Lookup the message with `message_id` originally sent by the sender within the associated conversation and let `message` be the result. 2. If `referred-message` is not defined or the sender is not the original sender of `message`, discard the message and abort these steps. 3. If `referred-message` is not deletable (see the associated _Deletable by_ property), discard the message and abort these steps. 4. Replace `referred-message` with a message informing the user that the message of the sender has been removed at the message's (the `DeleteMessage`'s) `created-at`.² ¹: For simplicity, the time constraint is applied on the sender side only. The receiver will always accept a request to delete a message. This is deemed acceptable considering this is just barely a soft-security feature. ²: All references to a removed message (e.g. quotes) must be updated as well, so that the message content is no longer visible. An implementation should also try to withdraw or update any notification created for a removed message.
Unique ID of the referred message to be removed.
Edit an existing message (e.g. a text message or a media message caption). **Properties (1:1)**: - Kind: 1:1 - Flags: - `0x01`: Send push notification. - User profile distribution: No - Exempt from blocking: No - Implicit _direct_ contact creation: No - Protect against replay: Yes - Unarchive: No - Bump _last update_: No - Reflect: - Incoming: Yes - Outgoing: Yes - _Sent_ update: No - Delivery receipts: No - Reactions: No - Edit applies to: N/A (obviously) - Deletable by: N/A - When rejected: N/A (ignored) - Send to Threema Gateway ID group creator: N/A **Properties (Group)**: - Kind: Group - Flags: - `0x01`: Send push notification. - User profile distribution: No - Exempt from blocking: No - Implicit _direct_ contact creation: No - Protect against replay: Yes - Unarchive: No - Bump _last update_: No - Reflect: - Incoming: Yes - Outgoing: Yes - _Sent_ update: No - Delivery receipts: N/A - Reactions: No - Edit applies to: N/A (obviously) - Deletable by: N/A - When rejected: N/A (ignored) - Send to Threema Gateway ID group creator: If capture is enabled The following steps must be invoked when the user wants to edit a 1:1 message: 1. If the sender or the receiver do not have `EDIT_MESSAGE_SUPPORT`, disallow editing and abort these steps. 2. Run the _Common Edit Message Enter Steps_. 3. Allow the user to edit the referred message. The following steps must be invoked when the user wants to edit a group message: 1. If the group is marked as _left_, disallow editing and abort these steps. 2. If the sender or all of the group members do not have `EDIT_MESSAGE_SUPPORT`, disallow editing and abort these steps. 3. Run the _Common Edit Message Enter Steps_. 4. If any of the group members do not have `EDIT_MESSAGE_SUPPORT`, notify the user that the affected contacts will not receive the edited content. 5. Allow the user to edit the referred message. The following steps are defined as the _Common Edit Message Enter Steps_: 1. Let `message` be the referred message. 2. If the user is not the original sender of `message`, disallow editing and abort these steps. 3. If `message` has been sent (`sent-at`) more than 6 hours ago, disallow editing and abort these steps.¹ The following steps must be invoked when the user wants to submit an edited 1:1 message. 1. If the sender or the receiver do not have `EDIT_MESSAGE_SUPPORT`, discard the edited message and abort these steps. 2. Run the _Common Edit Message Submit Preflight Steps_. 3. Let `edited-at` be the current timestamp. 4. Run the _1:1 Messages Submit Steps_ with `messages` set from the following properties: - `created-at` set to `edited-at`, - to construct an `EditMessage` message. 5. Edit the referred message as defined by the associated _Edit applies to_ property and add an indicator to the referred message, informing the user that the referred message has been edited by the user at `edited-at`. The following steps must be invoked when the user wants to submit an edited group message. 1. If the group is marked as _left_, discard the edited message and abort these steps. 2. If the sender or all of the group members do not have `EDIT_MESSAGE_SUPPORT`, discard the edited message and abort these steps. 3. Run the _Common Edit Message Submit Preflight Steps_. 4. Let `edited-at` be the current timestamp. 5. Run the _Group Messages Submit Steps_ with `messages` set from the following properties: - `created-at` set to `edited-at`, - to construct an `EditMessage` message (wrapped by [`group-member-container`](ref:e2e.group-member-container)). 6. Edit the referred message as defined by the associated _Edit applies to_ property and add an indicator to the referred message, informing the user that the referred message has been edited by the user at `edited-at`. The following steps are defined as the _Common Edit Message Submit Preflight Steps_: 1. Lookup the message with `message_id` originally sent by the sender within the associated conversation and let `message` be the result. 2. If `message` is no longer defined, discard the edited message and abort these steps. 3. If the content of `message` is identical to the edited message, discard the edited message and abort these steps. When reflected from another device as an incoming or outgoing 1:1 message: 1. Run the _Common Edit Message Receive Steps_. When receiving this message as a 1:1 message: 1. Run the _Common Edit Message Receive Steps_. When reflected from another device as an incoming or outgoing group message: 1. Run the _Common Edit Message Receive Steps_. When receiving this message as a group message (wrapped by [`group-member-container`](ref:e2e.group-member-container)): 1. Run the [_Common Group Receive Steps_](ref:e2e#receiving). If the message has been discarded, abort these steps. 2. Run the _Common Edit Message Receive Steps_. The following steps are defined as the _Common Edit Message Receive Steps_: 1. Lookup the message with `message_id` originally sent by the sender within the associated conversation and let `referred-message` be the result. 2. If `referred-message` is not defined or the sender is not the original sender of `referred-message`, discard the message and abort these steps.² 3. If `referred-message` is not editable (see the associated _Edit applies to_ property), discard the message and abort these steps. 4. Edit `referred-message` as defined by the associated _Edit applies to_ property and add an indicator to `referred-message`, informing the user that the message has been edited by the sender at the message's (the `EditMessage`'s) `created-at`. ¹: For simplicity, the time constraint is applied on the sender side only. The receiver will always accept a request to edit a message. This is deemed acceptable considering this is not a security feature. ²: Implementations do not track the group member setup at the time a message was received. Therefore, an edited message is always sent to the **current** group member setup, including any group members that weren't part of the group when the message was sent. However, any ordinary client will discard `EditMessage` for unknown messages. This leak is not great but considered acceptable for now.
Unique ID of the referred message to be edited.
Text (or caption) to update the referred message with. Should be ≤ 6000 bytes.
Announces and immediately starts a group call. **Properties**: - Kind: Group - Flags: - `0x01`: Send push notification. - User profile distribution: Yes - Exempt from blocking: Yes - Implicit _direct_ contact creation: No - Protect against replay: Yes - Unarchive: TODO(SE-508) - Bump _last update_: TODO(SE-508) - Reflect: - Incoming: Yes - Outgoing: Yes - _Sent_ update: No - Delivery receipts: N/A - Reactions: No - When rejected: N/A¹ - Edit applies to: N/A - Deletable by: N/A - Send to Threema Gateway ID group creator: If capture is enabled ¹: For the group creator it will be handled as if `group-sync-request` was received, re-sending a `GroupCallStart` if still ongoing, implicitly triggered by FS `Reject` receive steps. When the user wants to create a new group call or join an existing group call, run the steps outlined in the _Create or Join_ section of the Group Call Protocol. When reflected from another device as an incoming or outgoing message: 1. Run the _Common Group Call Start Receive Steps_. When receiving this message: 1. Run the [_Common Group Receive Steps_](ref:e2e#receiving). If the message has been discarded, abort these steps. 2. Run the _Common Group Call Start Receive Steps_. The following steps are defined as the _Common Group Call Start Receive Steps_: 1. If the hostname of `sfu_base_url` does not use the scheme `https` or does not end with one of the set of [_Allowed SFU Hostname Suffixes_](ref:group-calls#obtain-sfu-information), log a warning, discard the message and abort these steps. 2. Let `running` be the list of group calls that are currently considered running within the group. 3. If another call with the same GCK exists in `running`, log a warning, discard the message and abort these steps. 4. Add the received call to the list of group calls that are currently considered running (even if `protocol_version` is unsupported¹). 5. Start a task to run the _Group Call Refresh Steps_.² ¹: Adding unsupported `protocol_version`s allows the user to join an ongoing call after an app update where support for `protocol_version` has been added. ²: This ensures that the user automatically switches to the chosen call if it is currently participating in a group call of this group.
Protocol version used for group calls of this group. The current version number is `1`. Note: This is a _major_ version and may only be increased in case of breaking changes due to the significant UX impact this has when running the _Common Group Receive Steps_ (i.e. only calls with supported protocol versions can be _chosen_).
The secret Group Call Key (`GCK`) used for this call.
The base URL of the SFU, used to join or peek the call.
Request joining a group. This message is sent to the administrator of a group. The required information is provided by a `GroupInvite` URL payload. **Properties**: - Kind: 1:1 - Flags: - `0x01`: Send push notification. - User profile distribution: Yes - Exempt from blocking: Yes - Implicit _direct_ contact creation: Yes - Protect against replay: Yes - Reflect: - Incoming: Yes - Outgoing: Yes - _Sent_ update: No - Delivery receipts: No - Reactions: No - When rejected: N/A (ignored) - Edit applies to: N/A - Deletable by: User only - Send to Threema Gateway ID group creator: N/A When receiving this message: 1. Look up the corresponding group invitation by the token. 2. If the group invitation could not be found, discard the message and abort these steps. 3. If the sender is already part of the group, send an accept response and then respond as if the sender had sent a `group-sync-request` (i.e. send a `group-setup`, `group-name`, etc.). Finally, abort these steps. 4. If the group name does not match the name in the originally sent group invitation, discard the message and abort these steps. 5. If the group invitation has expired, send the respective response and abort these steps. 6. If the group invitation requires the admin to accept the request, show this information in the user interface and pause these steps until the user manually confirmed of rejected the request. Note that the date of the decision is allowed to extend beyond the expiration date of the group invitation. Continue with the following sub-steps once the user made a decision on the request: 1. If the user manually rejected the request, send the respective response and abort these steps. 7. If the group is full, send the respective response and abort these steps. 8. Send an accept response. 9. Add the sender of the group invitation request to the group and follow the group protocol from there.
The group invite token, 16 bytes
The group name from the group invite URL
A message for the group administrator, e.g. for identification purposes The message helps the administrator to decide whether or not to accept a join request. Should be requested by the user interface for invitations that require manual confirmation by the administrator. Should not be requested in case the invitation will be automatically accepted.
Response sent by the admin of a group towards a sender of a valid group join request. **Properties**: - Kind: 1:1 - Flags: None - User profile distribution: Yes - Exempt from blocking: Yes - Implicit _direct_ contact creation: Yes - Protect against replay: Yes - Reflect: - Incoming: Yes - Outgoing: Yes - _Sent_ update: No - Delivery receipts: No - Reactions: No - When rejected: N/A (ignored) - Edit applies to: N/A - Deletable by: N/A - Send to Threema Gateway ID group creator: N/A When receiving this message: 1. Look up the corresponding group join request by the token and the sender's Threema ID as the administrator's Threema ID. 2. If the group join request could not be found, discard the message and abort these steps. 3. Mark the group join request as accepted or (automatically) rejected by the given response type. 4. If the group join request has been accepted, remember the group id in order to be able to map an incoming `group-setup` to the group.
The group invite token, 16 bytes
Response of the admin
Used in:
Accept a group invite request
Token of a group invitation expired
Group invitation cannot be accepted due to the group being full
The administrator explicitly rejects the invitation request
Accept a group invite request
Used in:
Group ID (little-endian) as chosen by the group creator Note: Combined with the Threema ID of the administrator, this forms the `GroupIdentity`.
Metadata sent within a CSP payload `message-with-metadata-box` struct.
Padding that is ignored by the receiver. Recommended to be chosen such that the total length of padding + nickname is at least 16 bytes. May be empty if the nickname is long enough.
Unique message ID. Must match the message ID of the outer struct (i.e. `message-with-metadata-box.message-id`).
Unix-ish timestamp in milliseconds for when the message has been created. Messages sent in a group must have the same timestamp for each group member.
Nickname Should be sent when the associate message requires _user profile distribution_. When the user cleared its nickname, send an empty string. Do not send the user's Threema ID (i.e. process data). Recommended to not exceed 32 grapheme clusters. Should not contain whitespace characters at the beginning or the end of string.
React to a message. **Properties (1:1)**: - Kind: 1:1 - Flags: - `0x01`: Send push notification. - User profile distribution: Yes - Exempt from blocking: No - Implicit _direct_ contact creation: No - Protect against replay: Yes - Reflect: - Incoming: Yes - Outgoing: Yes - _Sent_ update: No - Delivery receipts: No - Reactions: No, that would be silly! - When rejected: N/A (ignored) - Edit applies to: N/A (can withdraw and apply with another `Reaction`) - Deletable by: N/A (can withdraw with another `Reaction`) - Send to Threema Gateway ID group creator: N/A **Properties (Group)**: - Kind: 1:1 - Flags: - `0x01`: Send push notification. - User profile distribution: Yes - Exempt from blocking: No - Implicit _direct_ contact creation: No - Protect against replay: Yes - Reflect: - Incoming: Yes - Outgoing: Yes - _Sent_ update: No - Delivery receipts: N/A - Reactions: No, that would be silly! - When rejected: N/A (ignored) - Edit applies to: N/A (can withdraw and apply with another `Reaction`) - Deletable by: N/A (can withdraw with another `Reaction`) - Send to Threema Gateway ID group creator: If capture is enabled When the user submits a reaction in a 1:1 conversation: 1. Let `reaction` be the reaction to be applied to or withdrawn from a referred message which must contain a single fully-qualified [emoji codepoint sequence that is part of the currently supported Unicode standard][emoji-test.txt]. 2. Run the _Legacy Reaction Mapping Steps_ with `reaction` and let `legacy-reaction` be the result. 3. If `legacy-reaction` is not defined and the sender or the receiver does not have `REACTION_SUPPORT`, log a warning and abort these steps.¹ 4. Let `reacted-at` be the current timestamp. 5. If both sender and receiver have `REACTION_SUPPORT`, run the _1:1 Messages Submit Steps_ with `messages` set from the following properties: - `created-at` set to `reacted-at`, - to construct a `Reaction` message from `reaction`. 6. If the sender or the receiver does not have `REACTION_SUPPORT`, run the _1:1 Messages Submit Steps_ with `messages` set from the following properties: - `created-at` set to `reacted-at`, - to construct the `legacy-reaction`. 7. Apply `reaction` (i.e. apply or withdraw) to the referred message with the `reacted-at` timestamp. When the user submits a reaction in a group conversation: 1. Let `reaction` be the reaction to be applied to or withdrawn from a referred message which must contain a single fully-qualified [emoji codepoint sequence that is part of the currently supported Unicode standard][emoji-test.txt]. 2. Run the _Legacy Reaction Mapping Steps_ with `reaction` and let `legacy-reaction` be the result. 3. If `legacy-reaction` is not defined: 1. If the sender does not have `REACTION_SUPPORT`, log a warning and abort these steps.² 2. If all of the group members do not have `REACTION_SUPPORT`, log a warning and and abort these steps.² 3. If any of the group members do not have `REACTION_SUPPORT`, notify the user that the affected contacts will not receive the reaction. 4. Let `reacted-at` be the current timestamp. 5. Run the _Group Messages Submit Steps_ with `messages` set from the following properties: - `created-at` set to `reacted-at`, - to construct a _canonical_ `Reaction` message from `reaction`, - to construct a _specific_ message in the following way: 1. Let `receiver` be the specific receiver. 2. If the `receiver` does not have `REACTION_SUPPORT` and `legacy-reaction` is defined, return the `legacy-reaction` (wrapped by [`group-member-container`](ref:e2e.group-member-container)). 3. Construct and return the _canonical_ `Reaction` message from `reaction` (wrapped by [`group-member-container`](ref:e2e.group-member-container)).³ 6. Apply `reaction` (i.e. apply or withdraw) to the referred message with the `reacted-at` timestamp. The following steps are defined as the _Legacy Reaction Mapping Steps_: 1. If `action` is of variant `apply`: 1. If `action.apply` equals one of the following codepoint sequences, return a `e2e.delivery-receipt` of type _acknowledge_ (0x03): - `1F44D` (👍) - `1F44D 1F3FB` (👍🏻) - `1F44D 1F3FC` (👍🏼) - `1F44D 1F3FD` (👍🏽) - `1F44D 1F3FE` (👍🏾) - `1F44D 1F3FF` (👍🏿) 2. If `action.apply` equals one of the following codepoint sequences, return a `e2e.delivery-receipt` of type _decline_ (0x04): - `1F44E` (👎) - `1F44E 1F3FB` (👎🏻) - `1F44E 1F3FC` (👎🏼) - `1F44E 1F3FD` (👎🏽) - `1F44E 1F3FE` (👎🏾) - `1F44E 1F3FF` (👎🏿) 2. Return no message. When reflected from another device as an incoming or outgoing 1:1 message: 1. Run the _Common Reaction Receive Steps_. When receiving this message: 1. Run the _Common Reaction Receive Steps_. When receiving this message (wrapped by [`group-member-container`](ref:e2e.group-member-container)): 1. Run the [_Common Group Receive Steps_](ref:e2e#receiving). If the reaction message has been discarded, abort these steps. 1. Run the _Common Reaction Receive Steps_. The following steps are defined as the _Common Reaction Receive Steps_: 1. Lookup the referred message with `message_id` within the associated conversation and let `referred-message` be the result. 2. If `referred-message` is not defined, discard the message and abort these steps. 3. If `referred-message` is not reactable (see the associated _Reactions_ property), discard the message and abort these steps. 4. If `action` is of variant `apply`: 1. If `apply` contains more than 64 bytes, discard the message and abort these steps. 2. Decode `apply` to a UTF-8 string. If the string is empty, discard the message and abort these steps. 3. Apply (or re-apply) the resulting emoji from the sender to `referred-message` with the message's (the `Reaction`'s) `created-at` timestamp used for the time of reaction.⁴⁵ 5. If `action` is of variant `withdraw`: 1. If `withdraw` contains more than 64 bytes, discard the message and abort these steps. 2. Decode `withdraw` to a UTF-8 string. If the string is empty, discard the message and abort these steps. 3. Remove the resulting emoji reaction from the sender for `message`.⁴⁵ ¹: The UI should not allow to create non-legacy reactions in 1:1 conversations with a sender or receiver that does not have `REACTION_SUPPORT`. ²: The UI should not allow to create non-legacy reactions in group conversations with a sender that does not have `REACTION_SUPPORT` or when all other group members don't have `REACTION_SUPPORT`. ³: In case the reaction could not be mapped to a legacy reaction, this results in a `Reaction` message being sent to group members that currently do not support reactions. This is intentional. ⁴: Note that the _apply_ mechanism is additive, meaning multiple reactions from the same sender are allowed on a single message. This is why the _withdraw_ mechanism is needed which removes a specific reaction. On the other hand, a deprecated `e2e.delivery-receipt` will replace all existing reactions of the sender at once (including these new-style reactions). ⁵: The UI should display a placeholder (�) for unknown emojis, meaining those which are not a single fully-qualified [emoji codepoint sequence that is part of the currently supported Unicode standard][emoji-test.txt]. But the individual code sequences still have individual display buckets. [emoji-test.txt]: https://www.unicode.org/Public/emoji/latest/emoji-test.txt
Unique ID of the referred message.
A single emoji reaction to be applied or withdrawn.
Apply a new emoji reaction.
Withdraw a specific emoji reaction.