{
    "componentChunkName": "component---src-templates-protocol-protocol-tsx",
    "path": "/messagepickup/4.0/",
    "result": {"data":{"markdownRemark":{"html":"<h2 id=\"Summary\">Summary</h2>\n<p>A protocol to facilitate a <em>Recipient</em> agent picking up messages held at a <em>Mediator</em>. This protocol is likely to be used in tandem with the <a href=\"https://didcomm.org/coordinate-mediation/3.0/\">Cooridinate Mediation protocol</a>.</p>\n<h2 id=\"Motivation\">Motivation</h2>\n<p>This protocol is needed to facilitate retrieval of messages from a mediator in an explicit manner. Additionally, this protocol provides behavior for initiating live delivery of messages, which is crucial for good user experience for agents operating on mobile devices.</p>\n<p>Motivation for v4 of this protocol primarily stems from ambiguity in the <a href=\"https://github.com/hyperledger/aries-rfcs/tree/main/features/0685-pickup-v2\">pickup v2 protocol</a> and <a href=\"https://didcomm.org/messagepickup/3.0/\">messagepickup v3 protocol</a> as to whether <code>delivery</code> and <code>messages-received</code> messages must be used while using live mode.</p>\n<h2 id=\"Version-Change-Log\">Version Change Log</h2>\n<h3 id=\"40\">4.0</h3>\n<ul>\n<li>Clarifies that <code>delivery</code> and <code>messages-received</code> messages MUST be used while using <em>Live Mode</em> to ensure delivery of all messages.</li>\n<li>Adjusts handling of <code>delivery-request</code> messages when no messages are queued to be delivered. Rather than sending a status message indicating no messages are queued, an empty delivery message is sent. This was chosen to reduce complexity of the protocol.</li>\n<li>Adds DIDComm v1 message format (pickup v3 only contained DIDComm v2).\n<ul>\n<li>In pickup v4 while using DIDComm v1, every <code>recipient_did</code> must be a <a href=\"https://github.com/hyperledger/aries-rfcs/tree/main/features/0360-use-did-key\"><code>did:key</code> reference</a>.</li>\n</ul>\n</li>\n<li>Adjustments to the protocol's use of thread ids\n<ul>\n<li>Added thread id to <code>status</code> messages, as status messages are always in response to an original message from the <code>recipient</code>.</li>\n<li>Made the thread id (thid) on <code>delivery</code> messages optional, as messages received in <em>Live Mode</em> do not have an associated <code>delivery-request</code> message.</li>\n</ul>\n</li>\n<li>Removed return route all from <code>messages-received</code> messages, as it is not required.</li>\n<li>Updates protocol-name to <code>message-pickup</code>.</li>\n<li>Removes the <code>longest_waited_seconds</code> field on the <code>status</code> message (as it is redundant in regards to <code>oldest_received_time</code>).</li>\n<li>Renames <code>limit</code> in the <code>delivery-request</code> to <code>message_count_limit</code> for increased specificity.</li>\n<li>Adjusts timing fields to be specified in UTC Epoch milliseconds instead of seconds for greater precision.</li>\n</ul>\n<h2 id=\"Roles\">Roles</h2>\n<p>There are two roles in this protocol:</p>\n<ul>\n<li><code>mediator</code>: The agent that has messages waiting for pickup by the <code>recipient</code>.</li>\n<li><code>recipient</code>: The agent who is picking up messages from the <code>mediator</code>.</li>\n</ul>\n<h2 id=\"Requirements\">Requirements</h2>\n<h3 id=\"Return-Route\">Return Route</h3>\n<p>The <code>return_route</code> extension must be supported by both agents (<code>recipient</code> and <code>mediator</code>).\nThe common use of this protocol is for the reply messages from the <code>mediator</code> to be synchronous, utilizing the same connection channel for the reply. In order to have this synchronous behavior the <code>recipient</code> should specify <code>return_route</code> header to <code>all</code>.\nThis header must be set each time the communication channel is established: once per established websocket, and every message for an HTTP POST.</p>\n<h3 id=\"DIDComm-V1-Requirements\">DIDComm V1 Requirements</h3>\n<p>When using this protocol with DIDComm V1, <code>recipient_did</code> <strong>MUST</strong> be a <a href=\"https://github.com/hyperledger/aries-rfcs/tree/main/features/0360-use-did-key\"><code>did:key</code> reference</a>.</p>\n<h2 id=\"Basic-Walkthrough\">Basic Walkthrough</h2>\n<p>This protocol consists of three different message requests from the <code>recipient</code> that should be replied to by the <code>mediator</code>:</p>\n<ol>\n<li>Status Request -> Status</li>\n<li>Delivery Request -> Message Delivery -> Message Received</li>\n<li>Live Mode -> Status or Problem Report -> Message Delivery -> Message Received</li>\n</ol>\n<h2 id=\"States\">States</h2>\n<p>This protocol follows the request-response message exchange pattern, and only requires the simple state of waiting for a response or to produce a response.</p>\n<p>Additionally, the <code>return_route</code> header extension must be set to <code>all</code> in all request submitted by the <code>recipient</code>.</p>\n<h2 id=\"Basic-Walkthrough-1\">Basic Walkthrough</h2>\n<p>The <code>status-request</code> message is sent by the <code>recipient</code> to the <code>mediator</code> to query how many messages are pending.</p>\n<p>The <code>status</code> message is the response to <code>status-request</code> to communicate the state of the message queue.</p>\n<p>The <code>delivery-request</code> message is sent by the <code>recipient</code> to request delivery of pending messages.</p>\n<p>The <code>delivery</code> message is the response to the <code>delivery-request</code> to send queued messages back to the <code>recipient</code>.</p>\n<p>The <code>messages-received</code> message is sent by the <code>recipient</code> to confirm receipt of delivered messages, prompting the <code>mediator</code> to clear messages from the queue.</p>\n<p>The <code>live-delivery-change</code> message is used to set the state of <code>live_delivery</code>.</p>\n<p>When <em>Live Mode</em> is enabled, messages that arrive when an existing connection exists are delivered over the connection immediately, via a <code>delivery</code> message, rather than being pushed to the queue. See <em>Live Mode</em> below for more details.</p>\n<h2 id=\"Security\">Security</h2>\n<p>This protocol expects messages to be encrypted during transmission, and repudiable.</p>\n<h2 id=\"Message-Reference\">Message Reference</h2>\n<h3 id=\"Status-Request\">Status Request</h3>\n<p>Sent by the <code>recipient</code> to the <code>mediator</code> to request a <code>status</code> message.</p>\n<p>Message Type URI: <code>https://didcomm.org/message-pickup/4.0/status-request</code></p>\n<p>DIDComm v1 example:</p>\n<pre><code class=\"language-json\">{\n    \"@id\": \"123456780\",\n    \"@type\": \"https://didcomm.org/message-pickup/4.0/status-request\",\n    \"recipient_did\": \"&#x3C;did:key for messages>\",\n    \"~transport\": {\n        \"return_route\": \"all\"\n    }\n}\n</code></pre>\n<p>DIDComm v2 example:</p>\n<pre><code class=\"language-json\">{\n    \"id\": \"123456780\",\n    \"type\": \"https://didcomm.org/message-pickup/4.0/status-request\",\n    \"body\" : {\n        \"recipient_did\": \"&#x3C;did for messages>\"\n    },\n    \"return_route\": \"all\"\n}\n</code></pre>\n<p><code>recipient_did</code> is optional. When specified, the <code>mediator</code> <strong>MUST</strong> only return status related to that recipient did. This allows the <code>recipient</code> to discover if any messages are in the queue that were sent to a specific DID. If using DIDComm v1, <code>recipient_did</code> <strong>MUST</strong> be a <a href=\"https://github.com/hyperledger/aries-rfcs/tree/main/features/0360-use-did-key\"><code>did:key</code> reference</a>.</p>\n<h3 id=\"Status\">Status</h3>\n<p>Status details about waiting messages.</p>\n<p>Message Type URI: <code>https://didcomm.org/message-pickup/4.0/status</code></p>\n<p>DIDComm v1 example:</p>\n<pre><code class=\"language-json\">{\n    \"@id\": \"123456780\",\n    \"@type\": \"https://didcomm.org/message-pickup/4.0/status\",\n    \"~thread\": {\n        \"thid\": \"&#x3C;message id of status-request message>\"\n    },\n    \"recipient_did\": \"&#x3C;did:key for messages>\",\n    \"message_count\": 7,\n    \"newest_received_time\": 1739420343823,\n    \"oldest_received_time\": 1739420343823,\n    \"total_bytes\": 8096,\n    \"live_delivery\": false\n}\n</code></pre>\n<p>DIDComm v2 example:</p>\n<pre><code class=\"language-json\">{\n    \"id\": \"123456780\",\n    \"thid\": \"&#x3C;message id of status-request message>\",\n    \"type\": \"https://didcomm.org/message-pickup/4.0/status\",\n    \"body\": {\n        \"recipient_did\": \"&#x3C;did for messages>\",\n        \"message_count\": 7,\n        \"newest_received_time\": 1739420343823,\n        \"oldest_received_time\": 1739420343823,\n        \"total_bytes\": 8096,\n        \"live_delivery\": false\n    }\n}\n</code></pre>\n<p><code>message_count</code> is the only <strong>REQUIRED</strong> attribute. The others <strong>MAY</strong> be present if offered by the <code>mediator</code>.</p>\n<p><code>newest_received_time</code> and <code>oldest_received_time</code> are expressed in UTC Epoch Milliseconds (Milliseconds since 1970-01-01T00:00:00Z) as an integer.</p>\n<p><code>total_bytes</code> represents the total size of all messages.</p>\n<p>If a <code>recipient_did</code> was specified in the <code>status-request</code> message, the matching value <strong>MUST</strong> be specified in the <code>recipient_did</code> attribute of the status message.</p>\n<p><code>live_delivery</code> state is also indicated in the status message.</p>\n<p><strong>Note</strong>: due to the potential for confusing what the actual state of the message queue is, a <code>status</code> message <strong>MUST NOT</strong> be put on the pending message queue and <strong>MUST</strong> only be sent when the <code>recipient</code> is actively connected (HTTP request awaiting response, WebSocket, etc.).</p>\n<h3 id=\"Delivery-Request\">Delivery Request</h3>\n<p>A request from the <code>recipient</code> to the <code>mediator</code> to have pending messages delivered.</p>\n<p>Message Type URI: <code>https://didcomm.org/message-pickup/4.0/delivery-request</code></p>\n<p>DIDComm v1 example:</p>\n<pre><code class=\"language-json\">{\n    \"@id\": \"123456780\",\n    \"@type\": \"https://didcomm.org/message-pickup/4.0/delivery-request\",\n    \"message_count_limit\": 10,\n    \"recipient_did\": \"&#x3C;did:key for messages>\",\n    \"~transport\": {\n        \"return_route\": \"all\"\n    }\n}\n</code></pre>\n<p>DIDComm v2 example:</p>\n<pre><code class=\"language-json\">{\n    \"id\": \"123456780\",\n    \"type\": \"https://didcomm.org/message-pickup/4.0/delivery-request\",\n    \"body\": {\n        \"message_count_limit\": 10,\n        \"recipient_did\": \"&#x3C;did for messages>\"\n    },\n    \"return_route\": \"all\"\n}\n</code></pre>\n<p><code>message_count_limit</code> is a <strong>REQUIRED</strong> attribute, and after receipt of this message, the <code>mediator</code> <strong>SHOULD</strong> deliver up to the limit indicated.</p>\n<p><code>recipient_did</code> is optional. When specified, the <code>mediator</code> <strong>MUST</strong> only return messages sent to that recipient did.</p>\n<p>If no messages are available to be sent, a <code>delivery</code> message with an empty attachments array <strong>MUST</strong> be sent immediately.</p>\n<p>Delivered messages <strong>MUST NOT</strong> be deleted until delivery is acknowledged by a <code>messages-received</code> message.</p>\n<h3 id=\"Message-Delivery\">Message Delivery</h3>\n<p>Batch of messages delivered to the <code>recipient</code> as attachments.</p>\n<p>Message Type URI: <code>https://didcomm.org/message-pickup/4.0/delivery</code></p>\n<p>DIDComm v1 example:</p>\n<pre><code class=\"language-json\">{\n    \"@id\": \"123456780\",\n    \"@type\": \"https://didcomm.org/message-pickup/4.0/delivery\",\n    \"~thread\": {\n        \"thid\": \"&#x3C;message id of delivery-request message>\"\n    },\n    \"recipient_did\": \"&#x3C;did:key for messages>\",\n    \"~attach\": [{\n        \"@id\": \"&#x3C;id of message>\",\n        \"data\": {\n            \"base64\": \"&#x3C;message>\"\n        }\n    }]\n}\n</code></pre>\n<p>DIDComm v2 example:</p>\n<pre><code class=\"language-json\">{\n    \"id\": \"123456780\",\n    \"thid\": \"&#x3C;message id of delivery-request message>\",\n    \"type\": \"https://didcomm.org/message-pickup/4.0/delivery\",\n    \"body\": {\n        \"recipient_did\": \"&#x3C;did for messages>\"\n    },\n    \"attachments\": [{\n        \"id\": \"&#x3C;id of message>\",\n        \"data\": {\n            \"base64\": \"&#x3C;message>\"\n        }\n    }]\n}\n</code></pre>\n<p>Messages delivered from the queue <strong>MUST</strong> be delivered in a delivery message as attachments. If the <code>delivery</code> message is in response to a <code>delivery-request</code> message that specifies a <code>message_count_limit</code>, the number of attached messages <strong>MUST NOT</strong> exceed the <code>message_count_limit</code> specified in the <code>delivery-request</code>.\nThe <code>id</code> of each attachment is used to confirm receipt.\nThe <code>id</code> is an opaque value, and the recipient <strong>SHOULD NOT</strong> deduce any information from it, except that it is unique to the mediator. The recipient can use the <code>id</code>s in the <code>message_id_list</code> field of <code>messages-received</code>.</p>\n<p>If there are no messages in the queue for the <code>delivery-request</code>, the <code>delivery</code> message <strong>MUST</strong> contain an empty array of attachments.</p>\n<p>The ONLY valid type of attachment for this message is a DIDComm v1 or v2 Message in encrypted form.</p>\n<p><code>thid</code> -- an optional field if the delivery message is in response to a singular <code>delivery-request</code> messsage.</p>\n<p>The <code>recipient_did</code> attribute is only included when responding to a <code>delivery-request</code> message that indicates a <code>recipient_did</code>.</p>\n<h3 id=\"Messages-Received\">Messages Received</h3>\n<p>After receiving messages, the <code>recipient</code> <strong>MUST</strong> send an acknowledge message indiciating which messages are safe to clear from the queue.</p>\n<p>Message Type URI: <code>https://didcomm.org/message-pickup/4.0/messages-received</code></p>\n<p>DIDComm v1 example:</p>\n<pre><code class=\"language-json\">{\n    \"@id\": \"123456780\",\n    \"@type\": \"https://didcomm.org/message-pickup/4.0/messages-received\",\n    \"message_id_list\": [\"123\",\"456\"]\n}\n</code></pre>\n<p>DIDComm v2 example:</p>\n<pre><code class=\"language-json\">{\n    \"id\": \"123456780\",\n    \"type\": \"https://didcomm.org/message-pickup/4.0/messages-received\",\n    \"body\": {\n        \"message_id_list\": [\"123\",\"456\"]\n    }\n}\n</code></pre>\n<p><code>message_id_list</code> is a list of <code>ids</code> of each message received. The <code>id</code> of each message is present in the attachment descriptor of each attached message of a delivery message.</p>\n<p>Upon receipt of this message, the <code>mediator</code> knows which messages have been received, and can remove them from the collection of queued messages with confidence.</p>\n<h4 id=\"Multiple-Recipients\">Multiple Recipients</h4>\n<p>If a message arrives at a <code>mediator</code> addressed to multiple <code>recipients</code>, the message <strong>MUST</strong> be queued for each <code>recipient</code> independently. If one of the addressed <code>recipients</code> retrieves a message and indicates it has been received, that message <strong>MUST</strong> still be held and then removed by the other addressed <code>recipients</code>.</p>\n<h3 id=\"Live-Mode\">Live Mode</h3>\n<p><em>Live Mode</em> is the practice of delivering newly arriving messages directly to a connected <code>recipient</code>. It is disabled by default and only activated by the <code>recipient</code>. Messages that arrive when <em>Live Mode</em> is off <strong>MUST</strong> be stored in the queue for retrieval as described above. If <em>Live Mode</em> is active, and the connection is broken, a new inbound connection starts with <em>Live Mode</em> disabled.</p>\n<p>Messages already in the queue are not affected by <em>Live Mode</em>; they <strong>MUST</strong> still be requested with <code>delivery-request</code> messages.</p>\n<p><em>Live Mode</em> <strong>MUST</strong> only be enabled when a persistent transport is used, such as WebSockets.</p>\n<p>If <em>Live Mode</em> is active, messages still <strong>MUST</strong> be delivered via a <code>delivery</code> message and the <code>recipient</code> <strong>MUST</strong> send an acknowledgement message <code>messages-received</code>. If a message is not acknowledged, the message <strong>MUST</strong> be added to the queue for later pickup.</p>\n<p>Recipients have three modes of possible operation for message delivery with various abilities and level of development complexity:</p>\n<ol>\n<li>Never activate <em>Live Mode</em>. Poll for new messages with a <code>status_request</code> message, and retrieve them when available.</li>\n<li>Retrieve all messages from queue, and then activate <em>Live Mode</em>. This simplifies message processing logic in the <code>recipient</code>.</li>\n<li>Activate <em>Live Mode</em> immediately upon connecting to the <code>mediator</code>. Retrieve messages from the queue as possible. When receiving a message delivered live, the queue may be queried for any waiting messages delivered to the same did for processing.</li>\n</ol>\n<h3 id=\"Live-Mode-Change\">Live Mode Change</h3>\n<p><em>Live Mode</em> is changed with a <code>live-delivery-change</code> message.</p>\n<p>Message Type URI: <code>https://didcomm.org/message-pickup/4.0/live-delivery-change</code></p>\n<p>DIDComm v1 example:</p>\n<pre><code class=\"language-json\">{\n    \"@id\": \"123456780\",\n    \"@type\": \"https://didcomm.org/message-pickup/4.0/live-delivery-change\",\n    \"live_delivery\": true\n}\n</code></pre>\n<p>DIDComm v2 example:</p>\n<pre><code class=\"language-json\">{\n    \"id\": \"123456780\",\n    \"type\": \"https://didcomm.org/message-pickup/4.0/live-delivery-change\",\n    \"body\": {\n        \"live_delivery\": true\n    }\n}\n</code></pre>\n<p>Upon receiving the <code>live_delivery_change</code> message, the <code>mediator</code> <strong>MUST</strong> respond with a <code>status</code> message.</p>\n<p>If sent with <code>live_delivery</code> set to true on a connection incapable of live delivery, a <code>problem_report</code> <strong>SHOULD</strong> be sent as follows:</p>\n<p>DIDComm v1 example:</p>\n<pre><code class=\"language-json\">{\n    \"@id\": \"123456780\",\n    \"@type\": \"https://didcomm.org/message-pickup/4.0/problem-report\",\n    \"~thread\": {\n        \"pthid\": \"&#x3C;the value is the thid of the thread in which the problem occurred>\"\n    },\n    \"description\": {\n        \"code\": \"e.m.live-mode-not-supported\",\n        \"en\": \"Connection does not support Live Delivery\"\n    }\n}\n</code></pre>\n<p>DIDComm v2 example:</p>\n<pre><code class=\"language-json\">{\n    \"id\": \"123456780\",\n    \"type\": \"https://didcomm.org/message-pickup/4.0/problem-report\",\n    \"pthid\": \"&#x3C;the value is the thid of the thread in which the problem occurred>\",\n    \"body\": {\n        \"code\": \"e.m.live-mode-not-supported\",\n        \"comment\": \"Connection does not support Live Delivery\"\n    }\n}\n</code></pre>\n<h2 id=\"L10n\">L10n</h2>\n<p>No localization is required.</p>\n<h2 id=\"Implementations\">Implementations</h2>\n<table>\n<thead>\n<tr>\n<th>Name / Link</th>\n<th>Implementation Notes</th>\n</tr>\n</thead>\n</table>\n<h2 id=\"Endnotes\">Endnotes</h2>\n<h3 id=\"Future-Considerations\">Future Considerations</h3>\n<p>The style of wrapping messages in a <code>delivery</code> message incurs an additional roughly 33% increased message size due to wrapping of the message. This size bloating is outweighed by the benefit of having explicit and guaranteed delivery of messages. This issue may be resolved in future versions of DIDComm.</p>\n<p>Should there be a strategy for a <code>mediator</code> to indicate support for <em>Live Mode</em> via discover features?</p>","frontmatter":{"title":"Message Pickup","tags":[],"license":"MIT","publisher":"JamesKEbert","status":"Production","piuri":"https://didcomm.org/message-pickup/4.0","summary":"A protocol to facilitate an agent picking up messages held at a mediator.","authors":[{"name":"Sam Curren","email":"telegramsam@gmail.com"},{"name":"James Ebert","email":"james@jamesebert.dev"}]},"fields":{"modifiedDate":"Wed Jul 22 2026 15:46:37 GMT+0000 (Coordinated Universal Time)","avatar":"https://avatars.githubusercontent.com/u/30242284?v=4&s=48","version":"4.0"}}},"pageContext":{"matchPath":"messagepickup/4.0/*","id":"f19d4ac6-1bbe-5471-88b2-52e3440211dd","html":"<h2 id=\"Summary\">Summary</h2>\n<p>A protocol to facilitate a <em>Recipient</em> agent picking up messages held at a <em>Mediator</em>. This protocol is likely to be used in tandem with the <a href=\"https://didcomm.org/coordinate-mediation/3.0/\">Cooridinate Mediation protocol</a>.</p>\n<h2 id=\"Motivation\">Motivation</h2>\n<p>This protocol is needed to facilitate retrieval of messages from a mediator in an explicit manner. Additionally, this protocol provides behavior for initiating live delivery of messages, which is crucial for good user experience for agents operating on mobile devices.</p>\n<p>Motivation for v4 of this protocol primarily stems from ambiguity in the <a href=\"https://github.com/hyperledger/aries-rfcs/tree/main/features/0685-pickup-v2\">pickup v2 protocol</a> and <a href=\"https://didcomm.org/messagepickup/3.0/\">messagepickup v3 protocol</a> as to whether <code>delivery</code> and <code>messages-received</code> messages must be used while using live mode.</p>\n<h2 id=\"Version-Change-Log\">Version Change Log</h2>\n<h3 id=\"40\">4.0</h3>\n<ul>\n<li>Clarifies that <code>delivery</code> and <code>messages-received</code> messages MUST be used while using <em>Live Mode</em> to ensure delivery of all messages.</li>\n<li>Adjusts handling of <code>delivery-request</code> messages when no messages are queued to be delivered. Rather than sending a status message indicating no messages are queued, an empty delivery message is sent. This was chosen to reduce complexity of the protocol.</li>\n<li>Adds DIDComm v1 message format (pickup v3 only contained DIDComm v2).\n<ul>\n<li>In pickup v4 while using DIDComm v1, every <code>recipient_did</code> must be a <a href=\"https://github.com/hyperledger/aries-rfcs/tree/main/features/0360-use-did-key\"><code>did:key</code> reference</a>.</li>\n</ul>\n</li>\n<li>Adjustments to the protocol's use of thread ids\n<ul>\n<li>Added thread id to <code>status</code> messages, as status messages are always in response to an original message from the <code>recipient</code>.</li>\n<li>Made the thread id (thid) on <code>delivery</code> messages optional, as messages received in <em>Live Mode</em> do not have an associated <code>delivery-request</code> message.</li>\n</ul>\n</li>\n<li>Removed return route all from <code>messages-received</code> messages, as it is not required.</li>\n<li>Updates protocol-name to <code>message-pickup</code>.</li>\n<li>Removes the <code>longest_waited_seconds</code> field on the <code>status</code> message (as it is redundant in regards to <code>oldest_received_time</code>).</li>\n<li>Renames <code>limit</code> in the <code>delivery-request</code> to <code>message_count_limit</code> for increased specificity.</li>\n<li>Adjusts timing fields to be specified in UTC Epoch milliseconds instead of seconds for greater precision.</li>\n</ul>\n<h2 id=\"Roles\">Roles</h2>\n<p>There are two roles in this protocol:</p>\n<ul>\n<li><code>mediator</code>: The agent that has messages waiting for pickup by the <code>recipient</code>.</li>\n<li><code>recipient</code>: The agent who is picking up messages from the <code>mediator</code>.</li>\n</ul>\n<h2 id=\"Requirements\">Requirements</h2>\n<h3 id=\"Return-Route\">Return Route</h3>\n<p>The <code>return_route</code> extension must be supported by both agents (<code>recipient</code> and <code>mediator</code>).\nThe common use of this protocol is for the reply messages from the <code>mediator</code> to be synchronous, utilizing the same connection channel for the reply. In order to have this synchronous behavior the <code>recipient</code> should specify <code>return_route</code> header to <code>all</code>.\nThis header must be set each time the communication channel is established: once per established websocket, and every message for an HTTP POST.</p>\n<h3 id=\"DIDComm-V1-Requirements\">DIDComm V1 Requirements</h3>\n<p>When using this protocol with DIDComm V1, <code>recipient_did</code> <strong>MUST</strong> be a <a href=\"https://github.com/hyperledger/aries-rfcs/tree/main/features/0360-use-did-key\"><code>did:key</code> reference</a>.</p>\n<h2 id=\"Basic-Walkthrough\">Basic Walkthrough</h2>\n<p>This protocol consists of three different message requests from the <code>recipient</code> that should be replied to by the <code>mediator</code>:</p>\n<ol>\n<li>Status Request -&gt; Status</li>\n<li>Delivery Request -&gt; Message Delivery -&gt; Message Received</li>\n<li>Live Mode -&gt; Status or Problem Report -&gt; Message Delivery -&gt; Message Received</li>\n</ol>\n<h2 id=\"States\">States</h2>\n<p>This protocol follows the request-response message exchange pattern, and only requires the simple state of waiting for a response or to produce a response.</p>\n<p>Additionally, the <code>return_route</code> header extension must be set to <code>all</code> in all request submitted by the <code>recipient</code>.</p>\n<h2 id=\"Basic-Walkthrough-1\">Basic Walkthrough</h2>\n<p>The <code>status-request</code> message is sent by the <code>recipient</code> to the <code>mediator</code> to query how many messages are pending.</p>\n<p>The <code>status</code> message is the response to <code>status-request</code> to communicate the state of the message queue.</p>\n<p>The <code>delivery-request</code> message is sent by the <code>recipient</code> to request delivery of pending messages.</p>\n<p>The <code>delivery</code> message is the response to the <code>delivery-request</code> to send queued messages back to the <code>recipient</code>.</p>\n<p>The <code>messages-received</code> message is sent by the <code>recipient</code> to confirm receipt of delivered messages, prompting the <code>mediator</code> to clear messages from the queue.</p>\n<p>The <code>live-delivery-change</code> message is used to set the state of <code>live_delivery</code>.</p>\n<p>When <em>Live Mode</em> is enabled, messages that arrive when an existing connection exists are delivered over the connection immediately, via a <code>delivery</code> message, rather than being pushed to the queue. See <em>Live Mode</em> below for more details.</p>\n<h2 id=\"Security\">Security</h2>\n<p>This protocol expects messages to be encrypted during transmission, and repudiable.</p>\n<h2 id=\"Message-Reference\">Message Reference</h2>\n<h3 id=\"Status-Request\">Status Request</h3>\n<p>Sent by the <code>recipient</code> to the <code>mediator</code> to request a <code>status</code> message.</p>\n<p>Message Type URI: <code>https://didcomm.org/message-pickup/4.0/status-request</code></p>\n<p>DIDComm v1 example:</p>\n<pre><code class=\"language-json\">{\n    \"@id\": \"123456780\",\n    \"@type\": \"https://didcomm.org/message-pickup/4.0/status-request\",\n    \"recipient_did\": \"&lt;did:key for messages&gt;\",\n    \"~transport\": {\n        \"return_route\": \"all\"\n    }\n}\n</code></pre>\n<p>DIDComm v2 example:</p>\n<pre><code class=\"language-json\">{\n    \"id\": \"123456780\",\n    \"type\": \"https://didcomm.org/message-pickup/4.0/status-request\",\n    \"body\" : {\n        \"recipient_did\": \"&lt;did for messages&gt;\"\n    },\n    \"return_route\": \"all\"\n}\n</code></pre>\n<p><code>recipient_did</code> is optional. When specified, the <code>mediator</code> <strong>MUST</strong> only return status related to that recipient did. This allows the <code>recipient</code> to discover if any messages are in the queue that were sent to a specific DID. If using DIDComm v1, <code>recipient_did</code> <strong>MUST</strong> be a <a href=\"https://github.com/hyperledger/aries-rfcs/tree/main/features/0360-use-did-key\"><code>did:key</code> reference</a>.</p>\n<h3 id=\"Status\">Status</h3>\n<p>Status details about waiting messages.</p>\n<p>Message Type URI: <code>https://didcomm.org/message-pickup/4.0/status</code></p>\n<p>DIDComm v1 example:</p>\n<pre><code class=\"language-json\">{\n    \"@id\": \"123456780\",\n    \"@type\": \"https://didcomm.org/message-pickup/4.0/status\",\n    \"~thread\": {\n        \"thid\": \"&lt;message id of status-request message&gt;\"\n    },\n    \"recipient_did\": \"&lt;did:key for messages&gt;\",\n    \"message_count\": 7,\n    \"newest_received_time\": 1739420343823,\n    \"oldest_received_time\": 1739420343823,\n    \"total_bytes\": 8096,\n    \"live_delivery\": false\n}\n</code></pre>\n<p>DIDComm v2 example:</p>\n<pre><code class=\"language-json\">{\n    \"id\": \"123456780\",\n    \"thid\": \"&lt;message id of status-request message&gt;\",\n    \"type\": \"https://didcomm.org/message-pickup/4.0/status\",\n    \"body\": {\n        \"recipient_did\": \"&lt;did for messages&gt;\",\n        \"message_count\": 7,\n        \"newest_received_time\": 1739420343823,\n        \"oldest_received_time\": 1739420343823,\n        \"total_bytes\": 8096,\n        \"live_delivery\": false\n    }\n}\n</code></pre>\n<p><code>message_count</code> is the only <strong>REQUIRED</strong> attribute. The others <strong>MAY</strong> be present if offered by the <code>mediator</code>.</p>\n<p><code>newest_received_time</code> and <code>oldest_received_time</code> are expressed in UTC Epoch Milliseconds (Milliseconds since 1970-01-01T00:00:00Z) as an integer.</p>\n<p><code>total_bytes</code> represents the total size of all messages.</p>\n<p>If a <code>recipient_did</code> was specified in the <code>status-request</code> message, the matching value <strong>MUST</strong> be specified in the <code>recipient_did</code> attribute of the status message.</p>\n<p><code>live_delivery</code> state is also indicated in the status message.</p>\n<p><strong>Note</strong>: due to the potential for confusing what the actual state of the message queue is, a <code>status</code> message <strong>MUST NOT</strong> be put on the pending message queue and <strong>MUST</strong> only be sent when the <code>recipient</code> is actively connected (HTTP request awaiting response, WebSocket, etc.).</p>\n<h3 id=\"Delivery-Request\">Delivery Request</h3>\n<p>A request from the <code>recipient</code> to the <code>mediator</code> to have pending messages delivered.</p>\n<p>Message Type URI: <code>https://didcomm.org/message-pickup/4.0/delivery-request</code></p>\n<p>DIDComm v1 example:</p>\n<pre><code class=\"language-json\">{\n    \"@id\": \"123456780\",\n    \"@type\": \"https://didcomm.org/message-pickup/4.0/delivery-request\",\n    \"message_count_limit\": 10,\n    \"recipient_did\": \"&lt;did:key for messages&gt;\",\n    \"~transport\": {\n        \"return_route\": \"all\"\n    }\n}\n</code></pre>\n<p>DIDComm v2 example:</p>\n<pre><code class=\"language-json\">{\n    \"id\": \"123456780\",\n    \"type\": \"https://didcomm.org/message-pickup/4.0/delivery-request\",\n    \"body\": {\n        \"message_count_limit\": 10,\n        \"recipient_did\": \"&lt;did for messages&gt;\"\n    },\n    \"return_route\": \"all\"\n}\n</code></pre>\n<p><code>message_count_limit</code> is a <strong>REQUIRED</strong> attribute, and after receipt of this message, the <code>mediator</code> <strong>SHOULD</strong> deliver up to the limit indicated.</p>\n<p><code>recipient_did</code> is optional. When specified, the <code>mediator</code> <strong>MUST</strong> only return messages sent to that recipient did.</p>\n<p>If no messages are available to be sent, a <code>delivery</code> message with an empty attachments array <strong>MUST</strong> be sent immediately.</p>\n<p>Delivered messages <strong>MUST NOT</strong> be deleted until delivery is acknowledged by a <code>messages-received</code> message.</p>\n<h3 id=\"Message-Delivery\">Message Delivery</h3>\n<p>Batch of messages delivered to the <code>recipient</code> as attachments.</p>\n<p>Message Type URI: <code>https://didcomm.org/message-pickup/4.0/delivery</code></p>\n<p>DIDComm v1 example:</p>\n<pre><code class=\"language-json\">{\n    \"@id\": \"123456780\",\n    \"@type\": \"https://didcomm.org/message-pickup/4.0/delivery\",\n    \"~thread\": {\n        \"thid\": \"&lt;message id of delivery-request message&gt;\"\n    },\n    \"recipient_did\": \"&lt;did:key for messages&gt;\",\n    \"~attach\": [{\n        \"@id\": \"&lt;id of message&gt;\",\n        \"data\": {\n            \"base64\": \"&lt;message&gt;\"\n        }\n    }]\n}\n</code></pre>\n<p>DIDComm v2 example:</p>\n<pre><code class=\"language-json\">{\n    \"id\": \"123456780\",\n    \"thid\": \"&lt;message id of delivery-request message&gt;\",\n    \"type\": \"https://didcomm.org/message-pickup/4.0/delivery\",\n    \"body\": {\n        \"recipient_did\": \"&lt;did for messages&gt;\"\n    },\n    \"attachments\": [{\n        \"id\": \"&lt;id of message&gt;\",\n        \"data\": {\n            \"base64\": \"&lt;message&gt;\"\n        }\n    }]\n}\n</code></pre>\n<p>Messages delivered from the queue <strong>MUST</strong> be delivered in a delivery message as attachments. If the <code>delivery</code> message is in response to a <code>delivery-request</code> message that specifies a <code>message_count_limit</code>, the number of attached messages <strong>MUST NOT</strong> exceed the <code>message_count_limit</code> specified in the <code>delivery-request</code>.\nThe <code>id</code> of each attachment is used to confirm receipt.\nThe <code>id</code> is an opaque value, and the recipient <strong>SHOULD NOT</strong> deduce any information from it, except that it is unique to the mediator. The recipient can use the <code>id</code>s in the <code>message_id_list</code> field of <code>messages-received</code>.</p>\n<p>If there are no messages in the queue for the <code>delivery-request</code>, the <code>delivery</code> message <strong>MUST</strong> contain an empty array of attachments.</p>\n<p>The ONLY valid type of attachment for this message is a DIDComm v1 or v2 Message in encrypted form.</p>\n<p><code>thid</code> -- an optional field if the delivery message is in response to a singular <code>delivery-request</code> messsage.</p>\n<p>The <code>recipient_did</code> attribute is only included when responding to a <code>delivery-request</code> message that indicates a <code>recipient_did</code>.</p>\n<h3 id=\"Messages-Received\">Messages Received</h3>\n<p>After receiving messages, the <code>recipient</code> <strong>MUST</strong> send an acknowledge message indiciating which messages are safe to clear from the queue.</p>\n<p>Message Type URI: <code>https://didcomm.org/message-pickup/4.0/messages-received</code></p>\n<p>DIDComm v1 example:</p>\n<pre><code class=\"language-json\">{\n    \"@id\": \"123456780\",\n    \"@type\": \"https://didcomm.org/message-pickup/4.0/messages-received\",\n    \"message_id_list\": [\"123\",\"456\"]\n}\n</code></pre>\n<p>DIDComm v2 example:</p>\n<pre><code class=\"language-json\">{\n    \"id\": \"123456780\",\n    \"type\": \"https://didcomm.org/message-pickup/4.0/messages-received\",\n    \"body\": {\n        \"message_id_list\": [\"123\",\"456\"]\n    }\n}\n</code></pre>\n<p><code>message_id_list</code> is a list of <code>ids</code> of each message received. The <code>id</code> of each message is present in the attachment descriptor of each attached message of a delivery message.</p>\n<p>Upon receipt of this message, the <code>mediator</code> knows which messages have been received, and can remove them from the collection of queued messages with confidence.</p>\n<h4 id=\"Multiple-Recipients\">Multiple Recipients</h4>\n<p>If a message arrives at a <code>mediator</code> addressed to multiple <code>recipients</code>, the message <strong>MUST</strong> be queued for each <code>recipient</code> independently. If one of the addressed <code>recipients</code> retrieves a message and indicates it has been received, that message <strong>MUST</strong> still be held and then removed by the other addressed <code>recipients</code>.</p>\n<h3 id=\"Live-Mode\">Live Mode</h3>\n<p><em>Live Mode</em> is the practice of delivering newly arriving messages directly to a connected <code>recipient</code>. It is disabled by default and only activated by the <code>recipient</code>. Messages that arrive when <em>Live Mode</em> is off <strong>MUST</strong> be stored in the queue for retrieval as described above. If <em>Live Mode</em> is active, and the connection is broken, a new inbound connection starts with <em>Live Mode</em> disabled.</p>\n<p>Messages already in the queue are not affected by <em>Live Mode</em>; they <strong>MUST</strong> still be requested with <code>delivery-request</code> messages.</p>\n<p><em>Live Mode</em> <strong>MUST</strong> only be enabled when a persistent transport is used, such as WebSockets.</p>\n<p>If <em>Live Mode</em> is active, messages still <strong>MUST</strong> be delivered via a <code>delivery</code> message and the <code>recipient</code> <strong>MUST</strong> send an acknowledgement message <code>messages-received</code>. If a message is not acknowledged, the message <strong>MUST</strong> be added to the queue for later pickup.</p>\n<p>Recipients have three modes of possible operation for message delivery with various abilities and level of development complexity:</p>\n<ol>\n<li>Never activate <em>Live Mode</em>. Poll for new messages with a <code>status_request</code> message, and retrieve them when available.</li>\n<li>Retrieve all messages from queue, and then activate <em>Live Mode</em>. This simplifies message processing logic in the <code>recipient</code>.</li>\n<li>Activate <em>Live Mode</em> immediately upon connecting to the <code>mediator</code>. Retrieve messages from the queue as possible. When receiving a message delivered live, the queue may be queried for any waiting messages delivered to the same did for processing.</li>\n</ol>\n<h3 id=\"Live-Mode-Change\">Live Mode Change</h3>\n<p><em>Live Mode</em> is changed with a <code>live-delivery-change</code> message.</p>\n<p>Message Type URI: <code>https://didcomm.org/message-pickup/4.0/live-delivery-change</code></p>\n<p>DIDComm v1 example:</p>\n<pre><code class=\"language-json\">{\n    \"@id\": \"123456780\",\n    \"@type\": \"https://didcomm.org/message-pickup/4.0/live-delivery-change\",\n    \"live_delivery\": true\n}\n</code></pre>\n<p>DIDComm v2 example:</p>\n<pre><code class=\"language-json\">{\n    \"id\": \"123456780\",\n    \"type\": \"https://didcomm.org/message-pickup/4.0/live-delivery-change\",\n    \"body\": {\n        \"live_delivery\": true\n    }\n}\n</code></pre>\n<p>Upon receiving the <code>live_delivery_change</code> message, the <code>mediator</code> <strong>MUST</strong> respond with a <code>status</code> message.</p>\n<p>If sent with <code>live_delivery</code> set to true on a connection incapable of live delivery, a <code>problem_report</code> <strong>SHOULD</strong> be sent as follows:</p>\n<p>DIDComm v1 example:</p>\n<pre><code class=\"language-json\">{\n    \"@id\": \"123456780\",\n    \"@type\": \"https://didcomm.org/message-pickup/4.0/problem-report\",\n    \"~thread\": {\n        \"pthid\": \"&lt;the value is the thid of the thread in which the problem occurred&gt;\"\n    },\n    \"description\": {\n        \"code\": \"e.m.live-mode-not-supported\",\n        \"en\": \"Connection does not support Live Delivery\"\n    }\n}\n</code></pre>\n<p>DIDComm v2 example:</p>\n<pre><code class=\"language-json\">{\n    \"id\": \"123456780\",\n    \"type\": \"https://didcomm.org/message-pickup/4.0/problem-report\",\n    \"pthid\": \"&lt;the value is the thid of the thread in which the problem occurred&gt;\",\n    \"body\": {\n        \"code\": \"e.m.live-mode-not-supported\",\n        \"comment\": \"Connection does not support Live Delivery\"\n    }\n}\n</code></pre>\n<h2 id=\"L10n\">L10n</h2>\n<p>No localization is required.</p>\n<h2 id=\"Implementations\">Implementations</h2>\n<table>\n<thead>\n<tr>\n<th>Name / Link</th>\n<th>Implementation Notes</th>\n</tr>\n</thead>\n</table>\n<h2 id=\"Endnotes\">Endnotes</h2>\n<h3 id=\"Future-Considerations\">Future Considerations</h3>\n<p>The style of wrapping messages in a <code>delivery</code> message incurs an additional roughly 33% increased message size due to wrapping of the message. This size bloating is outweighed by the benefit of having explicit and guaranteed delivery of messages. This issue may be resolved in future versions of DIDComm.</p>\n<p>Should there be a strategy for a <code>mediator</code> to indicate support for <em>Live Mode</em> via discover features?</p>"}},
    "staticQueryHashes": ["3000541721","3766577012"],
    "matchPath": "messagepickup/4.0/*"}