diff --git a/__tests__/QrCodeDataService.test.ts b/__tests__/QrCodeDataService.test.ts
index 4eb55f0448b2266a8fcaea57768a42e162ecc94e..160f82b538a9dda3142fe0798b8e867481533dcb 100644
--- a/__tests__/QrCodeDataService.test.ts
+++ b/__tests__/QrCodeDataService.test.ts
@@ -5,10 +5,9 @@ import Utils, {
   base64ToArrayBuffer,
   arrayBufferToBase64,
 } from "../src/utils/common";
-import { MessageData } from "../src";
+import { MessageData, DocumentData, IpfsContentData } from "../src";
 
 const emailData: MessageData = {
-  statusId: "123",
   sender: {
     name: "Arty",
     email: "arty@mail.ru",
@@ -42,118 +41,230 @@ const emailData: MessageData = {
   senderPublicKeyUuid: "<uuid>",
 };
 
+const documentData: DocumentData = {
+  author: "Craig McCracken",
+  documentTitle: "The_Powerpuff_Girls",
+  documentDescription: "cartoon for kids",
+  creationDate: new Date().toDateString(),
+  documentPages: 10,
+};
+
 /**
  * Algorithm spec
  * https://code.vereign.com/internal/product/-/issues/70#note_56356
  */
 describe("QrCodeDataService", () => {
-  it("performs the whole QR code data breakage/assembling routine", async () => {
-    /**
-     * Encode
-     */
-    const encodedEmailData = QrCodeDataService.encodeEmailData(emailData);
-    const compressedEmailData = Utils.compressData(encodedEmailData);
-    const {
-      data,
-      iv: sessionIv,
-      key: sessionKey,
-    } = await CryptoService.encryptAESGCM(
-      arrayBufferToBase64(compressedEmailData)
-    );
-
-    // 32 is a head bytes size. It's the minimum, and the bigger is better.
-    // Increase it as long as you can maintain good appearance of the QR code
-    const { head, tail } = QrCodeDataService.breakQrCodeData(data, 32);
-
-    const encodedSessionKey = QrCodeDataService.encodeKeyDataPair({
-      key: arrayBufferToBase64(sessionKey),
-      data: arrayBufferToBase64(sessionIv),
-    });
+  describe("Email", () => {
+    it("performs the whole QR code data breakage/assembling routine", async () => {
+      /**
+       * Encode
+       */
+      const encodedEmailData = QrCodeDataService.encodeEmailData(emailData);
+      const compressedEmailData = Utils.compressData(encodedEmailData);
+      const {
+        data,
+        iv: sessionIv,
+        key: sessionKey,
+      } = await CryptoService.encryptAESGCM(
+        arrayBufferToBase64(compressedEmailData)
+      );
+
+      // 32 is a head bytes size. It's the minimum, and the bigger is better.
+      // Increase it as long as you can maintain good appearance of the QR code
+      const { head, tail } = QrCodeDataService.breakQrCodeData(data, 32);
+
+      const encodedSessionKey = QrCodeDataService.encodeKeyDataPair({
+        key: arrayBufferToBase64(sessionKey),
+        data: arrayBufferToBase64(sessionIv),
+      });
+
+      // In client apps, RSA encryption happens using HSM service.
+      const { privateKeyPEM, publicKeyPEM } =
+        await CryptoService.generateRSAKeys();
+
+      const encryptedSessionKey = await CryptoService.encryptRSA(
+        publicKeyPEM,
+        base64ToArrayBuffer(encodedSessionKey)
+      );
+
+      const {
+        data: doubleEncryptedSessionKey,
+        iv: storageIv,
+        key: storageKey,
+      } = await CryptoService.encryptAESGCM(
+        arrayBufferToBase64(encryptedSessionKey)
+      );
+
+      // Put base64 of this into QR code data as `?q=` param
+      const encodedStorageKeyAndHead = QrCodeDataService.encodeKeyDataPair({
+        key: arrayBufferToBase64(storageKey),
+        data: arrayBufferToBase64(head),
+      });
+
+      const encodedDoubleEncryptedSessionKey =
+        QrCodeDataService.encodeKeyDataPair({
+          key: arrayBufferToBase64(doubleEncryptedSessionKey),
+          data: arrayBufferToBase64(storageIv),
+        });
 
-    // In client apps, RSA encryption happens using HSM service.
-    const {
-      privateKeyPEM,
-      publicKeyPEM,
-    } = await CryptoService.generateRSAKeys();
-
-    const encryptedSessionKey = await CryptoService.encryptRSA(
-      publicKeyPEM,
-      base64ToArrayBuffer(encodedSessionKey)
-    );
-
-    const {
-      data: doubleEncryptedSessionKey,
-      iv: storageIv,
-      key: storageKey,
-    } = await CryptoService.encryptAESGCM(
-      arrayBufferToBase64(encryptedSessionKey)
-    );
-
-    // Put base64 of this into QR code data as `?q=` param
-    const encodedStorageKeyAndHead = QrCodeDataService.encodeKeyDataPair({
-      key: arrayBufferToBase64(storageKey),
-      data: arrayBufferToBase64(head),
+      // Send this to putQRCodeData api
+      const backblazeData = {
+        sessionKey: encodedDoubleEncryptedSessionKey,
+        tail: arrayBufferToBase64(tail),
+      };
+
+      /**
+       * Decode
+       */
+
+      // Retrieve base64 of this from QR code URL
+      const decodedStorageKeyAndHead = QrCodeDataService.decodeKeyDataPair(
+        encodedStorageKeyAndHead
+      );
+
+      // decode this from backblaze data
+      const { key: doubleEncryptedSessionKeyDecoded, data: storageIvDecoded } =
+        QrCodeDataService.decodeKeyDataPair(backblazeData.sessionKey);
+
+      const doubleDecryptedSessionKey = await CryptoService.decryptAESGCM(
+        base64ToArrayBuffer(doubleEncryptedSessionKeyDecoded),
+        base64ToArrayBuffer(decodedStorageKeyAndHead.key),
+        base64ToArrayBuffer(storageIvDecoded)
+      );
+
+      // In client apps, RSA decryption happens using HSM service.
+      const decryptedSessionKey = await CryptoService.decryptRSA(
+        privateKeyPEM,
+        base64ToArrayBuffer(doubleDecryptedSessionKey)
+      );
+
+      const decodedSessionKey =
+        QrCodeDataService.decodeKeyDataPair(decryptedSessionKey);
+
+      const assembledData = QrCodeDataService.assembleQrCodeData(
+        base64ToArrayBuffer(decodedStorageKeyAndHead.data),
+        base64ToArrayBuffer(backblazeData.tail)
+      );
+
+      const decryptedEmailData = await CryptoService.decryptAESGCM(
+        assembledData,
+        base64ToArrayBuffer(decodedSessionKey.key),
+        base64ToArrayBuffer(decodedSessionKey.data)
+      );
+
+      const decompressedEmailData = Utils.decompressData(decryptedEmailData);
+      const decodedEmailData = QrCodeDataService.decodeEmailData(
+        decompressedEmailData
+      );
+      expect(decodedEmailData).toEqual(emailData);
     });
+  });
 
-    const encodedDoubleEncryptedSessionKey = QrCodeDataService.encodeKeyDataPair(
-      {
-        key: arrayBufferToBase64(doubleEncryptedSessionKey),
-        data: arrayBufferToBase64(storageIv),
-      }
-    );
-
-    // Send this to putQRCodeData api
-    const backblazeData = {
-      sessionKey: encodedDoubleEncryptedSessionKey,
-      tail: arrayBufferToBase64(tail),
-    };
-
-    /**
-     * Decode
-     */
-
-    // Retrieve base64 of this from QR code URL
-    const decodedStorageKeyAndHead = QrCodeDataService.decodeKeyDataPair(
-      encodedStorageKeyAndHead
-    );
-
-    // decode this from backblaze data
-    const {
-      key: doubleEncryptedSessionKeyDecoded,
-      data: storageIvDecoded,
-    } = QrCodeDataService.decodeKeyDataPair(backblazeData.sessionKey);
-
-    const doubleDecryptedSessionKey = await CryptoService.decryptAESGCM(
-      base64ToArrayBuffer(doubleEncryptedSessionKeyDecoded),
-      base64ToArrayBuffer(decodedStorageKeyAndHead.key),
-      base64ToArrayBuffer(storageIvDecoded)
-    );
-
-    // In client apps, RSA decryption happens using HSM service.
-    const decryptedSessionKey = await CryptoService.decryptRSA(
-      privateKeyPEM,
-      base64ToArrayBuffer(doubleDecryptedSessionKey)
-    );
-
-    const decodedSessionKey = QrCodeDataService.decodeKeyDataPair(
-      decryptedSessionKey
-    );
-
-    const assembledData = QrCodeDataService.assembleQrCodeData(
-      base64ToArrayBuffer(decodedStorageKeyAndHead.data),
-      base64ToArrayBuffer(backblazeData.tail)
-    );
-
-    const decryptedEmailData = await CryptoService.decryptAESGCM(
-      assembledData,
-      base64ToArrayBuffer(decodedSessionKey.key),
-      base64ToArrayBuffer(decodedSessionKey.data)
-    );
-
-    const decompressedEmailData = Utils.decompressData(decryptedEmailData);
-    const decodedEmailData = QrCodeDataService.decodeEmailData(
-      decompressedEmailData
-    );
-    expect(decodedEmailData).toEqual(emailData);
+  describe("Documents", () => {
+    it("performs the whole QR code data breakage/assembling routine ", async () => {
+      /**
+       * Encode
+       */
+      const encodedDocumentData =
+        QrCodeDataService.encodeDocumentData(documentData);
+      const compressedDocumentData = Utils.compressData(encodedDocumentData);
+      const {
+        data,
+        iv: sessionIv,
+        key: sessionKey,
+      } = await CryptoService.encryptAESGCM(
+        arrayBufferToBase64(compressedDocumentData)
+      );
+
+      const { head, tail } = QrCodeDataService.breakQrCodeData(data, 32);
+
+      const encodedSessionKey = QrCodeDataService.encodeKeyDataPair({
+        key: arrayBufferToBase64(sessionKey),
+        data: arrayBufferToBase64(sessionIv),
+      });
+
+      // In client apps, RSA encryption happens using HSM service.
+      const { privateKeyPEM, publicKeyPEM } =
+        await CryptoService.generateRSAKeys();
+
+      const encryptedSessionKey = await CryptoService.encryptRSA(
+        publicKeyPEM,
+        base64ToArrayBuffer(encodedSessionKey)
+      );
+
+      const {
+        data: doubleEncryptedSessionKey,
+        iv: storageIv,
+        key: storageKey,
+      } = await CryptoService.encryptAESGCM(
+        arrayBufferToBase64(encryptedSessionKey)
+      );
+
+      // Put base64 of this into QR code data as `?q=` param
+      const encodedStorageKeyAndHead = QrCodeDataService.encodeKeyDataPair({
+        key: arrayBufferToBase64(storageKey),
+        data: arrayBufferToBase64(head),
+      });
+
+      const encodedDoubleEncryptedSessionKey =
+        QrCodeDataService.encodeKeyDataPair({
+          key: arrayBufferToBase64(doubleEncryptedSessionKey),
+          data: arrayBufferToBase64(storageIv),
+        });
+
+      // Send this to putQRCodeData api
+      const backblazeData = {
+        sessionKey: encodedDoubleEncryptedSessionKey,
+        tail: arrayBufferToBase64(tail),
+      };
+
+      /**
+       * Decode Document
+       */
+
+      // Retrieve base64 of this from QR code URL
+      const decodedStorageKeyAndHead = QrCodeDataService.decodeKeyDataPair(
+        encodedStorageKeyAndHead
+      );
+
+      // decode this from backblaze data
+      const { key: doubleEncryptedSessionKeyDecoded, data: storageIvDecoded } =
+        QrCodeDataService.decodeKeyDataPair(backblazeData.sessionKey);
+
+      const doubleDecryptedSessionKey = await CryptoService.decryptAESGCM(
+        base64ToArrayBuffer(doubleEncryptedSessionKeyDecoded),
+        base64ToArrayBuffer(decodedStorageKeyAndHead.key),
+        base64ToArrayBuffer(storageIvDecoded)
+      );
+
+      // In client apps, RSA decryption happens using HSM service.
+      const decryptedSessionKey = await CryptoService.decryptRSA(
+        privateKeyPEM,
+        base64ToArrayBuffer(doubleDecryptedSessionKey)
+      );
+
+      const decodedSessionKey =
+        QrCodeDataService.decodeKeyDataPair(decryptedSessionKey);
+
+      const assembledData = QrCodeDataService.assembleQrCodeData(
+        base64ToArrayBuffer(decodedStorageKeyAndHead.data),
+        base64ToArrayBuffer(backblazeData.tail)
+      );
+
+      const decryptedDocumentData = await CryptoService.decryptAESGCM(
+        assembledData,
+        base64ToArrayBuffer(decodedSessionKey.key),
+        base64ToArrayBuffer(decodedSessionKey.data)
+      );
+
+      const decompressedDocumentData = Utils.decompressData(
+        decryptedDocumentData
+      );
+      const decodedDocumentData = QrCodeDataService.decodeDocumentData(
+        decompressedDocumentData
+      );
+
+      expect(decodedDocumentData).toEqual(documentData);
+    });
   });
 });
diff --git a/dist/generated/qrcode_data_pb.js b/dist/generated/qrcode_data_pb.js
index 4fb64d64b1f48e4470c501d4a69072f64a6d8792..3eb61e8ba0450908547aa7c3f89901406f591738 100644
--- a/dist/generated/qrcode_data_pb.js
+++ b/dist/generated/qrcode_data_pb.js
@@ -2304,7 +2304,7 @@ $root.vereign = (function () {
                  * @property {string|null} [documentDescription] DocumentData_V1 documentDescription
                  * @property {string|null} [creationDate] DocumentData_V1 creationDate
                  * @property {number|null} [documentPages] DocumentData_V1 documentPages
-                 * @property {vereign.protobuf.qrcode_data.IIpfsContentData_V1|null} [ipfs] DocumentData_V1 ipfs
+                 * @property {vereign.protobuf.qrcode_data.IIpfsData_V1|null} [ipfs] DocumentData_V1 ipfs
                  */
                 /**
                  * Constructs a new DocumentData_V1.
@@ -2357,7 +2357,7 @@ $root.vereign = (function () {
                 DocumentData_V1.prototype.documentPages = 0;
                 /**
                  * DocumentData_V1 ipfs.
-                 * @member {vereign.protobuf.qrcode_data.IIpfsContentData_V1|null|undefined} ipfs
+                 * @member {vereign.protobuf.qrcode_data.IIpfsData_V1|null|undefined} ipfs
                  * @memberof vereign.protobuf.qrcode_data.DocumentData_V1
                  * @instance
                  */
@@ -2396,7 +2396,7 @@ $root.vereign = (function () {
                     if (message.documentPages != null && Object.hasOwnProperty.call(message, "documentPages"))
                         writer.uint32(/* id 5, wireType 0 =*/ 40).int32(message.documentPages);
                     if (message.ipfs != null && Object.hasOwnProperty.call(message, "ipfs"))
-                        $root.vereign.protobuf.qrcode_data.IpfsContentData_V1.encode(message.ipfs, writer.uint32(/* id 6, wireType 2 =*/ 50).fork()).ldelim();
+                        $root.vereign.protobuf.qrcode_data.IpfsData_V1.encode(message.ipfs, writer.uint32(/* id 6, wireType 2 =*/ 50).fork()).ldelim();
                     return writer;
                 };
                 /**
@@ -2445,7 +2445,7 @@ $root.vereign = (function () {
                                 message.documentPages = reader.int32();
                                 break;
                             case 6:
-                                message.ipfs = $root.vereign.protobuf.qrcode_data.IpfsContentData_V1.decode(reader, reader.uint32());
+                                message.ipfs = $root.vereign.protobuf.qrcode_data.IpfsData_V1.decode(reader, reader.uint32());
                                 break;
                             default:
                                 reader.skipType(tag & 7);
@@ -2496,7 +2496,7 @@ $root.vereign = (function () {
                         if (!$util.isInteger(message.documentPages))
                             return "documentPages: integer expected";
                     if (message.ipfs != null && message.hasOwnProperty("ipfs")) {
-                        var error = $root.vereign.protobuf.qrcode_data.IpfsContentData_V1.verify(message.ipfs);
+                        var error = $root.vereign.protobuf.qrcode_data.IpfsData_V1.verify(message.ipfs);
                         if (error)
                             return "ipfs." + error;
                     }
@@ -2527,7 +2527,7 @@ $root.vereign = (function () {
                     if (object.ipfs != null) {
                         if (typeof object.ipfs !== "object")
                             throw TypeError(".vereign.protobuf.qrcode_data.DocumentData_V1.ipfs: object expected");
-                        message.ipfs = $root.vereign.protobuf.qrcode_data.IpfsContentData_V1.fromObject(object.ipfs);
+                        message.ipfs = $root.vereign.protobuf.qrcode_data.IpfsData_V1.fromObject(object.ipfs);
                     }
                     return message;
                 };
@@ -2563,7 +2563,7 @@ $root.vereign = (function () {
                     if (message.documentPages != null && message.hasOwnProperty("documentPages"))
                         object.documentPages = message.documentPages;
                     if (message.ipfs != null && message.hasOwnProperty("ipfs"))
-                        object.ipfs = $root.vereign.protobuf.qrcode_data.IpfsContentData_V1.toObject(message.ipfs, options);
+                        object.ipfs = $root.vereign.protobuf.qrcode_data.IpfsData_V1.toObject(message.ipfs, options);
                     return object;
                 };
                 /**
@@ -2578,530 +2578,6 @@ $root.vereign = (function () {
                 };
                 return DocumentData_V1;
             })();
-            qrcode_data.SealDocumentHeadData_V1 = (function () {
-                /**
-                 * Properties of a SealDocumentHeadData_V1.
-                 * @memberof vereign.protobuf.qrcode_data
-                 * @interface ISealDocumentHeadData_V1
-                 * @property {Uint8Array|null} [key] SealDocumentHeadData_V1 key
-                 * @property {Uint8Array|null} [data] SealDocumentHeadData_V1 data
-                 * @property {string|null} [ipfsIndexCid] SealDocumentHeadData_V1 ipfsIndexCid
-                 */
-                /**
-                 * Constructs a new SealDocumentHeadData_V1.
-                 * @memberof vereign.protobuf.qrcode_data
-                 * @classdesc Reference
-                 * https://community.vereign.com/t/seal-blockchain-status-storage-for-documents-and-beyond/371/6
-                 * Step 14
-                 * @implements ISealDocumentHeadData_V1
-                 * @constructor
-                 * @param {vereign.protobuf.qrcode_data.ISealDocumentHeadData_V1=} [properties] Properties to set
-                 */
-                function SealDocumentHeadData_V1(properties) {
-                    if (properties)
-                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
-                            if (properties[keys[i]] != null)
-                                this[keys[i]] = properties[keys[i]];
-                }
-                /**
-                 * SealDocumentHeadData_V1 key.
-                 * @member {Uint8Array} key
-                 * @memberof vereign.protobuf.qrcode_data.SealDocumentHeadData_V1
-                 * @instance
-                 */
-                SealDocumentHeadData_V1.prototype.key = $util.newBuffer([]);
-                /**
-                 * SealDocumentHeadData_V1 data.
-                 * @member {Uint8Array} data
-                 * @memberof vereign.protobuf.qrcode_data.SealDocumentHeadData_V1
-                 * @instance
-                 */
-                SealDocumentHeadData_V1.prototype.data = $util.newBuffer([]);
-                /**
-                 * SealDocumentHeadData_V1 ipfsIndexCid.
-                 * @member {string} ipfsIndexCid
-                 * @memberof vereign.protobuf.qrcode_data.SealDocumentHeadData_V1
-                 * @instance
-                 */
-                SealDocumentHeadData_V1.prototype.ipfsIndexCid = "";
-                /**
-                 * Creates a new SealDocumentHeadData_V1 instance using the specified properties.
-                 * @function create
-                 * @memberof vereign.protobuf.qrcode_data.SealDocumentHeadData_V1
-                 * @static
-                 * @param {vereign.protobuf.qrcode_data.ISealDocumentHeadData_V1=} [properties] Properties to set
-                 * @returns {vereign.protobuf.qrcode_data.SealDocumentHeadData_V1} SealDocumentHeadData_V1 instance
-                 */
-                SealDocumentHeadData_V1.create = function create(properties) {
-                    return new SealDocumentHeadData_V1(properties);
-                };
-                /**
-                 * Encodes the specified SealDocumentHeadData_V1 message. Does not implicitly {@link vereign.protobuf.qrcode_data.SealDocumentHeadData_V1.verify|verify} messages.
-                 * @function encode
-                 * @memberof vereign.protobuf.qrcode_data.SealDocumentHeadData_V1
-                 * @static
-                 * @param {vereign.protobuf.qrcode_data.ISealDocumentHeadData_V1} message SealDocumentHeadData_V1 message or plain object to encode
-                 * @param {$protobuf.Writer} [writer] Writer to encode to
-                 * @returns {$protobuf.Writer} Writer
-                 */
-                SealDocumentHeadData_V1.encode = function encode(message, writer) {
-                    if (!writer)
-                        writer = $Writer.create();
-                    if (message.key != null && Object.hasOwnProperty.call(message, "key"))
-                        writer.uint32(/* id 1, wireType 2 =*/ 10).bytes(message.key);
-                    if (message.data != null && Object.hasOwnProperty.call(message, "data"))
-                        writer.uint32(/* id 2, wireType 2 =*/ 18).bytes(message.data);
-                    if (message.ipfsIndexCid != null && Object.hasOwnProperty.call(message, "ipfsIndexCid"))
-                        writer.uint32(/* id 3, wireType 2 =*/ 26).string(message.ipfsIndexCid);
-                    return writer;
-                };
-                /**
-                 * Encodes the specified SealDocumentHeadData_V1 message, length delimited. Does not implicitly {@link vereign.protobuf.qrcode_data.SealDocumentHeadData_V1.verify|verify} messages.
-                 * @function encodeDelimited
-                 * @memberof vereign.protobuf.qrcode_data.SealDocumentHeadData_V1
-                 * @static
-                 * @param {vereign.protobuf.qrcode_data.ISealDocumentHeadData_V1} message SealDocumentHeadData_V1 message or plain object to encode
-                 * @param {$protobuf.Writer} [writer] Writer to encode to
-                 * @returns {$protobuf.Writer} Writer
-                 */
-                SealDocumentHeadData_V1.encodeDelimited = function encodeDelimited(message, writer) {
-                    return this.encode(message, writer).ldelim();
-                };
-                /**
-                 * Decodes a SealDocumentHeadData_V1 message from the specified reader or buffer.
-                 * @function decode
-                 * @memberof vereign.protobuf.qrcode_data.SealDocumentHeadData_V1
-                 * @static
-                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
-                 * @param {number} [length] Message length if known beforehand
-                 * @returns {vereign.protobuf.qrcode_data.SealDocumentHeadData_V1} SealDocumentHeadData_V1
-                 * @throws {Error} If the payload is not a reader or valid buffer
-                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
-                 */
-                SealDocumentHeadData_V1.decode = function decode(reader, length) {
-                    if (!(reader instanceof $Reader))
-                        reader = $Reader.create(reader);
-                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.vereign.protobuf.qrcode_data.SealDocumentHeadData_V1();
-                    while (reader.pos < end) {
-                        var tag = reader.uint32();
-                        switch (tag >>> 3) {
-                            case 1:
-                                message.key = reader.bytes();
-                                break;
-                            case 2:
-                                message.data = reader.bytes();
-                                break;
-                            case 3:
-                                message.ipfsIndexCid = reader.string();
-                                break;
-                            default:
-                                reader.skipType(tag & 7);
-                                break;
-                        }
-                    }
-                    return message;
-                };
-                /**
-                 * Decodes a SealDocumentHeadData_V1 message from the specified reader or buffer, length delimited.
-                 * @function decodeDelimited
-                 * @memberof vereign.protobuf.qrcode_data.SealDocumentHeadData_V1
-                 * @static
-                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
-                 * @returns {vereign.protobuf.qrcode_data.SealDocumentHeadData_V1} SealDocumentHeadData_V1
-                 * @throws {Error} If the payload is not a reader or valid buffer
-                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
-                 */
-                SealDocumentHeadData_V1.decodeDelimited = function decodeDelimited(reader) {
-                    if (!(reader instanceof $Reader))
-                        reader = new $Reader(reader);
-                    return this.decode(reader, reader.uint32());
-                };
-                /**
-                 * Verifies a SealDocumentHeadData_V1 message.
-                 * @function verify
-                 * @memberof vereign.protobuf.qrcode_data.SealDocumentHeadData_V1
-                 * @static
-                 * @param {Object.<string,*>} message Plain object to verify
-                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
-                 */
-                SealDocumentHeadData_V1.verify = function verify(message) {
-                    if (typeof message !== "object" || message === null)
-                        return "object expected";
-                    if (message.key != null && message.hasOwnProperty("key"))
-                        if (!(message.key && typeof message.key.length === "number" || $util.isString(message.key)))
-                            return "key: buffer expected";
-                    if (message.data != null && message.hasOwnProperty("data"))
-                        if (!(message.data && typeof message.data.length === "number" || $util.isString(message.data)))
-                            return "data: buffer expected";
-                    if (message.ipfsIndexCid != null && message.hasOwnProperty("ipfsIndexCid"))
-                        if (!$util.isString(message.ipfsIndexCid))
-                            return "ipfsIndexCid: string expected";
-                    return null;
-                };
-                /**
-                 * Creates a SealDocumentHeadData_V1 message from a plain object. Also converts values to their respective internal types.
-                 * @function fromObject
-                 * @memberof vereign.protobuf.qrcode_data.SealDocumentHeadData_V1
-                 * @static
-                 * @param {Object.<string,*>} object Plain object
-                 * @returns {vereign.protobuf.qrcode_data.SealDocumentHeadData_V1} SealDocumentHeadData_V1
-                 */
-                SealDocumentHeadData_V1.fromObject = function fromObject(object) {
-                    if (object instanceof $root.vereign.protobuf.qrcode_data.SealDocumentHeadData_V1)
-                        return object;
-                    var message = new $root.vereign.protobuf.qrcode_data.SealDocumentHeadData_V1();
-                    if (object.key != null)
-                        if (typeof object.key === "string")
-                            $util.base64.decode(object.key, message.key = $util.newBuffer($util.base64.length(object.key)), 0);
-                        else if (object.key.length)
-                            message.key = object.key;
-                    if (object.data != null)
-                        if (typeof object.data === "string")
-                            $util.base64.decode(object.data, message.data = $util.newBuffer($util.base64.length(object.data)), 0);
-                        else if (object.data.length)
-                            message.data = object.data;
-                    if (object.ipfsIndexCid != null)
-                        message.ipfsIndexCid = String(object.ipfsIndexCid);
-                    return message;
-                };
-                /**
-                 * Creates a plain object from a SealDocumentHeadData_V1 message. Also converts values to other types if specified.
-                 * @function toObject
-                 * @memberof vereign.protobuf.qrcode_data.SealDocumentHeadData_V1
-                 * @static
-                 * @param {vereign.protobuf.qrcode_data.SealDocumentHeadData_V1} message SealDocumentHeadData_V1
-                 * @param {$protobuf.IConversionOptions} [options] Conversion options
-                 * @returns {Object.<string,*>} Plain object
-                 */
-                SealDocumentHeadData_V1.toObject = function toObject(message, options) {
-                    if (!options)
-                        options = {};
-                    var object = {};
-                    if (options.defaults) {
-                        if (options.bytes === String)
-                            object.key = "";
-                        else {
-                            object.key = [];
-                            if (options.bytes !== Array)
-                                object.key = $util.newBuffer(object.key);
-                        }
-                        if (options.bytes === String)
-                            object.data = "";
-                        else {
-                            object.data = [];
-                            if (options.bytes !== Array)
-                                object.data = $util.newBuffer(object.data);
-                        }
-                        object.ipfsIndexCid = "";
-                    }
-                    if (message.key != null && message.hasOwnProperty("key"))
-                        object.key = options.bytes === String ? $util.base64.encode(message.key, 0, message.key.length) : options.bytes === Array ? Array.prototype.slice.call(message.key) : message.key;
-                    if (message.data != null && message.hasOwnProperty("data"))
-                        object.data = options.bytes === String ? $util.base64.encode(message.data, 0, message.data.length) : options.bytes === Array ? Array.prototype.slice.call(message.data) : message.data;
-                    if (message.ipfsIndexCid != null && message.hasOwnProperty("ipfsIndexCid"))
-                        object.ipfsIndexCid = message.ipfsIndexCid;
-                    return object;
-                };
-                /**
-                 * Converts this SealDocumentHeadData_V1 to JSON.
-                 * @function toJSON
-                 * @memberof vereign.protobuf.qrcode_data.SealDocumentHeadData_V1
-                 * @instance
-                 * @returns {Object.<string,*>} JSON object
-                 */
-                SealDocumentHeadData_V1.prototype.toJSON = function toJSON() {
-                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
-                };
-                return SealDocumentHeadData_V1;
-            })();
-            qrcode_data.SealIndexObject_V1 = (function () {
-                /**
-                 * Properties of a SealIndexObject_V1.
-                 * @memberof vereign.protobuf.qrcode_data
-                 * @interface ISealIndexObject_V1
-                 * @property {Uint8Array|null} [sealKey] SealIndexObject_V1 sealKey
-                 * @property {string|null} [sealTailCid] SealIndexObject_V1 sealTailCid
-                 * @property {string|null} [chain] SealIndexObject_V1 chain
-                 * @property {string|null} [block] SealIndexObject_V1 block
-                 * @property {string|null} [transactionId] SealIndexObject_V1 transactionId
-                 * @property {string|null} [hashBatchId] SealIndexObject_V1 hashBatchId
-                 */
-                /**
-                 * Constructs a new SealIndexObject_V1.
-                 * @memberof vereign.protobuf.qrcode_data
-                 * @classdesc Represents a SealIndexObject_V1.
-                 * @implements ISealIndexObject_V1
-                 * @constructor
-                 * @param {vereign.protobuf.qrcode_data.ISealIndexObject_V1=} [properties] Properties to set
-                 */
-                function SealIndexObject_V1(properties) {
-                    if (properties)
-                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
-                            if (properties[keys[i]] != null)
-                                this[keys[i]] = properties[keys[i]];
-                }
-                /**
-                 * SealIndexObject_V1 sealKey.
-                 * @member {Uint8Array} sealKey
-                 * @memberof vereign.protobuf.qrcode_data.SealIndexObject_V1
-                 * @instance
-                 */
-                SealIndexObject_V1.prototype.sealKey = $util.newBuffer([]);
-                /**
-                 * SealIndexObject_V1 sealTailCid.
-                 * @member {string} sealTailCid
-                 * @memberof vereign.protobuf.qrcode_data.SealIndexObject_V1
-                 * @instance
-                 */
-                SealIndexObject_V1.prototype.sealTailCid = "";
-                /**
-                 * SealIndexObject_V1 chain.
-                 * @member {string} chain
-                 * @memberof vereign.protobuf.qrcode_data.SealIndexObject_V1
-                 * @instance
-                 */
-                SealIndexObject_V1.prototype.chain = "";
-                /**
-                 * SealIndexObject_V1 block.
-                 * @member {string} block
-                 * @memberof vereign.protobuf.qrcode_data.SealIndexObject_V1
-                 * @instance
-                 */
-                SealIndexObject_V1.prototype.block = "";
-                /**
-                 * SealIndexObject_V1 transactionId.
-                 * @member {string} transactionId
-                 * @memberof vereign.protobuf.qrcode_data.SealIndexObject_V1
-                 * @instance
-                 */
-                SealIndexObject_V1.prototype.transactionId = "";
-                /**
-                 * SealIndexObject_V1 hashBatchId.
-                 * @member {string} hashBatchId
-                 * @memberof vereign.protobuf.qrcode_data.SealIndexObject_V1
-                 * @instance
-                 */
-                SealIndexObject_V1.prototype.hashBatchId = "";
-                /**
-                 * Creates a new SealIndexObject_V1 instance using the specified properties.
-                 * @function create
-                 * @memberof vereign.protobuf.qrcode_data.SealIndexObject_V1
-                 * @static
-                 * @param {vereign.protobuf.qrcode_data.ISealIndexObject_V1=} [properties] Properties to set
-                 * @returns {vereign.protobuf.qrcode_data.SealIndexObject_V1} SealIndexObject_V1 instance
-                 */
-                SealIndexObject_V1.create = function create(properties) {
-                    return new SealIndexObject_V1(properties);
-                };
-                /**
-                 * Encodes the specified SealIndexObject_V1 message. Does not implicitly {@link vereign.protobuf.qrcode_data.SealIndexObject_V1.verify|verify} messages.
-                 * @function encode
-                 * @memberof vereign.protobuf.qrcode_data.SealIndexObject_V1
-                 * @static
-                 * @param {vereign.protobuf.qrcode_data.ISealIndexObject_V1} message SealIndexObject_V1 message or plain object to encode
-                 * @param {$protobuf.Writer} [writer] Writer to encode to
-                 * @returns {$protobuf.Writer} Writer
-                 */
-                SealIndexObject_V1.encode = function encode(message, writer) {
-                    if (!writer)
-                        writer = $Writer.create();
-                    if (message.sealKey != null && Object.hasOwnProperty.call(message, "sealKey"))
-                        writer.uint32(/* id 1, wireType 2 =*/ 10).bytes(message.sealKey);
-                    if (message.sealTailCid != null && Object.hasOwnProperty.call(message, "sealTailCid"))
-                        writer.uint32(/* id 2, wireType 2 =*/ 18).string(message.sealTailCid);
-                    if (message.chain != null && Object.hasOwnProperty.call(message, "chain"))
-                        writer.uint32(/* id 3, wireType 2 =*/ 26).string(message.chain);
-                    if (message.block != null && Object.hasOwnProperty.call(message, "block"))
-                        writer.uint32(/* id 4, wireType 2 =*/ 34).string(message.block);
-                    if (message.transactionId != null && Object.hasOwnProperty.call(message, "transactionId"))
-                        writer.uint32(/* id 5, wireType 2 =*/ 42).string(message.transactionId);
-                    if (message.hashBatchId != null && Object.hasOwnProperty.call(message, "hashBatchId"))
-                        writer.uint32(/* id 6, wireType 2 =*/ 50).string(message.hashBatchId);
-                    return writer;
-                };
-                /**
-                 * Encodes the specified SealIndexObject_V1 message, length delimited. Does not implicitly {@link vereign.protobuf.qrcode_data.SealIndexObject_V1.verify|verify} messages.
-                 * @function encodeDelimited
-                 * @memberof vereign.protobuf.qrcode_data.SealIndexObject_V1
-                 * @static
-                 * @param {vereign.protobuf.qrcode_data.ISealIndexObject_V1} message SealIndexObject_V1 message or plain object to encode
-                 * @param {$protobuf.Writer} [writer] Writer to encode to
-                 * @returns {$protobuf.Writer} Writer
-                 */
-                SealIndexObject_V1.encodeDelimited = function encodeDelimited(message, writer) {
-                    return this.encode(message, writer).ldelim();
-                };
-                /**
-                 * Decodes a SealIndexObject_V1 message from the specified reader or buffer.
-                 * @function decode
-                 * @memberof vereign.protobuf.qrcode_data.SealIndexObject_V1
-                 * @static
-                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
-                 * @param {number} [length] Message length if known beforehand
-                 * @returns {vereign.protobuf.qrcode_data.SealIndexObject_V1} SealIndexObject_V1
-                 * @throws {Error} If the payload is not a reader or valid buffer
-                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
-                 */
-                SealIndexObject_V1.decode = function decode(reader, length) {
-                    if (!(reader instanceof $Reader))
-                        reader = $Reader.create(reader);
-                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.vereign.protobuf.qrcode_data.SealIndexObject_V1();
-                    while (reader.pos < end) {
-                        var tag = reader.uint32();
-                        switch (tag >>> 3) {
-                            case 1:
-                                message.sealKey = reader.bytes();
-                                break;
-                            case 2:
-                                message.sealTailCid = reader.string();
-                                break;
-                            case 3:
-                                message.chain = reader.string();
-                                break;
-                            case 4:
-                                message.block = reader.string();
-                                break;
-                            case 5:
-                                message.transactionId = reader.string();
-                                break;
-                            case 6:
-                                message.hashBatchId = reader.string();
-                                break;
-                            default:
-                                reader.skipType(tag & 7);
-                                break;
-                        }
-                    }
-                    return message;
-                };
-                /**
-                 * Decodes a SealIndexObject_V1 message from the specified reader or buffer, length delimited.
-                 * @function decodeDelimited
-                 * @memberof vereign.protobuf.qrcode_data.SealIndexObject_V1
-                 * @static
-                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
-                 * @returns {vereign.protobuf.qrcode_data.SealIndexObject_V1} SealIndexObject_V1
-                 * @throws {Error} If the payload is not a reader or valid buffer
-                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
-                 */
-                SealIndexObject_V1.decodeDelimited = function decodeDelimited(reader) {
-                    if (!(reader instanceof $Reader))
-                        reader = new $Reader(reader);
-                    return this.decode(reader, reader.uint32());
-                };
-                /**
-                 * Verifies a SealIndexObject_V1 message.
-                 * @function verify
-                 * @memberof vereign.protobuf.qrcode_data.SealIndexObject_V1
-                 * @static
-                 * @param {Object.<string,*>} message Plain object to verify
-                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
-                 */
-                SealIndexObject_V1.verify = function verify(message) {
-                    if (typeof message !== "object" || message === null)
-                        return "object expected";
-                    if (message.sealKey != null && message.hasOwnProperty("sealKey"))
-                        if (!(message.sealKey && typeof message.sealKey.length === "number" || $util.isString(message.sealKey)))
-                            return "sealKey: buffer expected";
-                    if (message.sealTailCid != null && message.hasOwnProperty("sealTailCid"))
-                        if (!$util.isString(message.sealTailCid))
-                            return "sealTailCid: string expected";
-                    if (message.chain != null && message.hasOwnProperty("chain"))
-                        if (!$util.isString(message.chain))
-                            return "chain: string expected";
-                    if (message.block != null && message.hasOwnProperty("block"))
-                        if (!$util.isString(message.block))
-                            return "block: string expected";
-                    if (message.transactionId != null && message.hasOwnProperty("transactionId"))
-                        if (!$util.isString(message.transactionId))
-                            return "transactionId: string expected";
-                    if (message.hashBatchId != null && message.hasOwnProperty("hashBatchId"))
-                        if (!$util.isString(message.hashBatchId))
-                            return "hashBatchId: string expected";
-                    return null;
-                };
-                /**
-                 * Creates a SealIndexObject_V1 message from a plain object. Also converts values to their respective internal types.
-                 * @function fromObject
-                 * @memberof vereign.protobuf.qrcode_data.SealIndexObject_V1
-                 * @static
-                 * @param {Object.<string,*>} object Plain object
-                 * @returns {vereign.protobuf.qrcode_data.SealIndexObject_V1} SealIndexObject_V1
-                 */
-                SealIndexObject_V1.fromObject = function fromObject(object) {
-                    if (object instanceof $root.vereign.protobuf.qrcode_data.SealIndexObject_V1)
-                        return object;
-                    var message = new $root.vereign.protobuf.qrcode_data.SealIndexObject_V1();
-                    if (object.sealKey != null)
-                        if (typeof object.sealKey === "string")
-                            $util.base64.decode(object.sealKey, message.sealKey = $util.newBuffer($util.base64.length(object.sealKey)), 0);
-                        else if (object.sealKey.length)
-                            message.sealKey = object.sealKey;
-                    if (object.sealTailCid != null)
-                        message.sealTailCid = String(object.sealTailCid);
-                    if (object.chain != null)
-                        message.chain = String(object.chain);
-                    if (object.block != null)
-                        message.block = String(object.block);
-                    if (object.transactionId != null)
-                        message.transactionId = String(object.transactionId);
-                    if (object.hashBatchId != null)
-                        message.hashBatchId = String(object.hashBatchId);
-                    return message;
-                };
-                /**
-                 * Creates a plain object from a SealIndexObject_V1 message. Also converts values to other types if specified.
-                 * @function toObject
-                 * @memberof vereign.protobuf.qrcode_data.SealIndexObject_V1
-                 * @static
-                 * @param {vereign.protobuf.qrcode_data.SealIndexObject_V1} message SealIndexObject_V1
-                 * @param {$protobuf.IConversionOptions} [options] Conversion options
-                 * @returns {Object.<string,*>} Plain object
-                 */
-                SealIndexObject_V1.toObject = function toObject(message, options) {
-                    if (!options)
-                        options = {};
-                    var object = {};
-                    if (options.defaults) {
-                        if (options.bytes === String)
-                            object.sealKey = "";
-                        else {
-                            object.sealKey = [];
-                            if (options.bytes !== Array)
-                                object.sealKey = $util.newBuffer(object.sealKey);
-                        }
-                        object.sealTailCid = "";
-                        object.chain = "";
-                        object.block = "";
-                        object.transactionId = "";
-                        object.hashBatchId = "";
-                    }
-                    if (message.sealKey != null && message.hasOwnProperty("sealKey"))
-                        object.sealKey = options.bytes === String ? $util.base64.encode(message.sealKey, 0, message.sealKey.length) : options.bytes === Array ? Array.prototype.slice.call(message.sealKey) : message.sealKey;
-                    if (message.sealTailCid != null && message.hasOwnProperty("sealTailCid"))
-                        object.sealTailCid = message.sealTailCid;
-                    if (message.chain != null && message.hasOwnProperty("chain"))
-                        object.chain = message.chain;
-                    if (message.block != null && message.hasOwnProperty("block"))
-                        object.block = message.block;
-                    if (message.transactionId != null && message.hasOwnProperty("transactionId"))
-                        object.transactionId = message.transactionId;
-                    if (message.hashBatchId != null && message.hasOwnProperty("hashBatchId"))
-                        object.hashBatchId = message.hashBatchId;
-                    return object;
-                };
-                /**
-                 * Converts this SealIndexObject_V1 to JSON.
-                 * @function toJSON
-                 * @memberof vereign.protobuf.qrcode_data.SealIndexObject_V1
-                 * @instance
-                 * @returns {Object.<string,*>} JSON object
-                 */
-                SealIndexObject_V1.prototype.toJSON = function toJSON() {
-                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
-                };
-                return SealIndexObject_V1;
-            })();
             return qrcode_data;
         })();
         return protobuf;
diff --git a/dist/generated/statuses_pb.js b/dist/generated/statuses_pb.js
index 8312ac13a598445ee57fdfc5e5b97b632114cfac..4acdc8b57bc03e16bdeebec67af3984ec277efcb 100644
--- a/dist/generated/statuses_pb.js
+++ b/dist/generated/statuses_pb.js
@@ -1765,6 +1765,225 @@ $root.vereign = (function () {
             };
             return WrapperData;
         })();
+        statuses.DocumentStatusObject = (function () {
+            /**
+             * Properties of a DocumentStatusObject.
+             * @memberof vereign.statuses
+             * @interface IDocumentStatusObject
+             * @property {number|Long|null} [timestamp] DocumentStatusObject timestamp
+             * @property {Uint8Array|null} [sealHash] DocumentStatusObject sealHash
+             */
+            /**
+             * Constructs a new DocumentStatusObject.
+             * @memberof vereign.statuses
+             * @classdesc Represents a DocumentStatusObject.
+             * @implements IDocumentStatusObject
+             * @constructor
+             * @param {vereign.statuses.IDocumentStatusObject=} [properties] Properties to set
+             */
+            function DocumentStatusObject(properties) {
+                if (properties)
+                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                        if (properties[keys[i]] != null)
+                            this[keys[i]] = properties[keys[i]];
+            }
+            /**
+             * DocumentStatusObject timestamp.
+             * @member {number|Long} timestamp
+             * @memberof vereign.statuses.DocumentStatusObject
+             * @instance
+             */
+            DocumentStatusObject.prototype.timestamp = $util.Long ? $util.Long.fromBits(0, 0, false) : 0;
+            /**
+             * DocumentStatusObject sealHash.
+             * @member {Uint8Array} sealHash
+             * @memberof vereign.statuses.DocumentStatusObject
+             * @instance
+             */
+            DocumentStatusObject.prototype.sealHash = $util.newBuffer([]);
+            /**
+             * Creates a new DocumentStatusObject instance using the specified properties.
+             * @function create
+             * @memberof vereign.statuses.DocumentStatusObject
+             * @static
+             * @param {vereign.statuses.IDocumentStatusObject=} [properties] Properties to set
+             * @returns {vereign.statuses.DocumentStatusObject} DocumentStatusObject instance
+             */
+            DocumentStatusObject.create = function create(properties) {
+                return new DocumentStatusObject(properties);
+            };
+            /**
+             * Encodes the specified DocumentStatusObject message. Does not implicitly {@link vereign.statuses.DocumentStatusObject.verify|verify} messages.
+             * @function encode
+             * @memberof vereign.statuses.DocumentStatusObject
+             * @static
+             * @param {vereign.statuses.IDocumentStatusObject} message DocumentStatusObject message or plain object to encode
+             * @param {$protobuf.Writer} [writer] Writer to encode to
+             * @returns {$protobuf.Writer} Writer
+             */
+            DocumentStatusObject.encode = function encode(message, writer) {
+                if (!writer)
+                    writer = $Writer.create();
+                if (message.timestamp != null && Object.hasOwnProperty.call(message, "timestamp"))
+                    writer.uint32(/* id 1, wireType 0 =*/ 8).int64(message.timestamp);
+                if (message.sealHash != null && Object.hasOwnProperty.call(message, "sealHash"))
+                    writer.uint32(/* id 2, wireType 2 =*/ 18).bytes(message.sealHash);
+                return writer;
+            };
+            /**
+             * Encodes the specified DocumentStatusObject message, length delimited. Does not implicitly {@link vereign.statuses.DocumentStatusObject.verify|verify} messages.
+             * @function encodeDelimited
+             * @memberof vereign.statuses.DocumentStatusObject
+             * @static
+             * @param {vereign.statuses.IDocumentStatusObject} message DocumentStatusObject message or plain object to encode
+             * @param {$protobuf.Writer} [writer] Writer to encode to
+             * @returns {$protobuf.Writer} Writer
+             */
+            DocumentStatusObject.encodeDelimited = function encodeDelimited(message, writer) {
+                return this.encode(message, writer).ldelim();
+            };
+            /**
+             * Decodes a DocumentStatusObject message from the specified reader or buffer.
+             * @function decode
+             * @memberof vereign.statuses.DocumentStatusObject
+             * @static
+             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+             * @param {number} [length] Message length if known beforehand
+             * @returns {vereign.statuses.DocumentStatusObject} DocumentStatusObject
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            DocumentStatusObject.decode = function decode(reader, length) {
+                if (!(reader instanceof $Reader))
+                    reader = $Reader.create(reader);
+                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.vereign.statuses.DocumentStatusObject();
+                while (reader.pos < end) {
+                    var tag = reader.uint32();
+                    switch (tag >>> 3) {
+                        case 1:
+                            message.timestamp = reader.int64();
+                            break;
+                        case 2:
+                            message.sealHash = reader.bytes();
+                            break;
+                        default:
+                            reader.skipType(tag & 7);
+                            break;
+                    }
+                }
+                return message;
+            };
+            /**
+             * Decodes a DocumentStatusObject message from the specified reader or buffer, length delimited.
+             * @function decodeDelimited
+             * @memberof vereign.statuses.DocumentStatusObject
+             * @static
+             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+             * @returns {vereign.statuses.DocumentStatusObject} DocumentStatusObject
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            DocumentStatusObject.decodeDelimited = function decodeDelimited(reader) {
+                if (!(reader instanceof $Reader))
+                    reader = new $Reader(reader);
+                return this.decode(reader, reader.uint32());
+            };
+            /**
+             * Verifies a DocumentStatusObject message.
+             * @function verify
+             * @memberof vereign.statuses.DocumentStatusObject
+             * @static
+             * @param {Object.<string,*>} message Plain object to verify
+             * @returns {string|null} `null` if valid, otherwise the reason why it is not
+             */
+            DocumentStatusObject.verify = function verify(message) {
+                if (typeof message !== "object" || message === null)
+                    return "object expected";
+                if (message.timestamp != null && message.hasOwnProperty("timestamp"))
+                    if (!$util.isInteger(message.timestamp) && !(message.timestamp && $util.isInteger(message.timestamp.low) && $util.isInteger(message.timestamp.high)))
+                        return "timestamp: integer|Long expected";
+                if (message.sealHash != null && message.hasOwnProperty("sealHash"))
+                    if (!(message.sealHash && typeof message.sealHash.length === "number" || $util.isString(message.sealHash)))
+                        return "sealHash: buffer expected";
+                return null;
+            };
+            /**
+             * Creates a DocumentStatusObject message from a plain object. Also converts values to their respective internal types.
+             * @function fromObject
+             * @memberof vereign.statuses.DocumentStatusObject
+             * @static
+             * @param {Object.<string,*>} object Plain object
+             * @returns {vereign.statuses.DocumentStatusObject} DocumentStatusObject
+             */
+            DocumentStatusObject.fromObject = function fromObject(object) {
+                if (object instanceof $root.vereign.statuses.DocumentStatusObject)
+                    return object;
+                var message = new $root.vereign.statuses.DocumentStatusObject();
+                if (object.timestamp != null)
+                    if ($util.Long)
+                        (message.timestamp = $util.Long.fromValue(object.timestamp)).unsigned = false;
+                    else if (typeof object.timestamp === "string")
+                        message.timestamp = parseInt(object.timestamp, 10);
+                    else if (typeof object.timestamp === "number")
+                        message.timestamp = object.timestamp;
+                    else if (typeof object.timestamp === "object")
+                        message.timestamp = new $util.LongBits(object.timestamp.low >>> 0, object.timestamp.high >>> 0).toNumber();
+                if (object.sealHash != null)
+                    if (typeof object.sealHash === "string")
+                        $util.base64.decode(object.sealHash, message.sealHash = $util.newBuffer($util.base64.length(object.sealHash)), 0);
+                    else if (object.sealHash.length)
+                        message.sealHash = object.sealHash;
+                return message;
+            };
+            /**
+             * Creates a plain object from a DocumentStatusObject message. Also converts values to other types if specified.
+             * @function toObject
+             * @memberof vereign.statuses.DocumentStatusObject
+             * @static
+             * @param {vereign.statuses.DocumentStatusObject} message DocumentStatusObject
+             * @param {$protobuf.IConversionOptions} [options] Conversion options
+             * @returns {Object.<string,*>} Plain object
+             */
+            DocumentStatusObject.toObject = function toObject(message, options) {
+                if (!options)
+                    options = {};
+                var object = {};
+                if (options.defaults) {
+                    if ($util.Long) {
+                        var long = new $util.Long(0, 0, false);
+                        object.timestamp = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
+                    }
+                    else
+                        object.timestamp = options.longs === String ? "0" : 0;
+                    if (options.bytes === String)
+                        object.sealHash = "";
+                    else {
+                        object.sealHash = [];
+                        if (options.bytes !== Array)
+                            object.sealHash = $util.newBuffer(object.sealHash);
+                    }
+                }
+                if (message.timestamp != null && message.hasOwnProperty("timestamp"))
+                    if (typeof message.timestamp === "number")
+                        object.timestamp = options.longs === String ? String(message.timestamp) : message.timestamp;
+                    else
+                        object.timestamp = options.longs === String ? $util.Long.prototype.toString.call(message.timestamp) : options.longs === Number ? new $util.LongBits(message.timestamp.low >>> 0, message.timestamp.high >>> 0).toNumber() : message.timestamp;
+                if (message.sealHash != null && message.hasOwnProperty("sealHash"))
+                    object.sealHash = options.bytes === String ? $util.base64.encode(message.sealHash, 0, message.sealHash.length) : options.bytes === Array ? Array.prototype.slice.call(message.sealHash) : message.sealHash;
+                return object;
+            };
+            /**
+             * Converts this DocumentStatusObject to JSON.
+             * @function toJSON
+             * @memberof vereign.statuses.DocumentStatusObject
+             * @instance
+             * @returns {Object.<string,*>} JSON object
+             */
+            DocumentStatusObject.prototype.toJSON = function toJSON() {
+                return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+            };
+            return DocumentStatusObject;
+        })();
         return statuses;
     })();
     return vereign;
diff --git a/dist/services/QrCodeDataService.d.ts b/dist/services/QrCodeDataService.d.ts
index 1babbf049d295d8854ecdcda67ad720e4fc8a1b0..5ea7dcc6a447755dbf447c219cc4dd1ec3a92b2d 100644
--- a/dist/services/QrCodeDataService.d.ts
+++ b/dist/services/QrCodeDataService.d.ts
@@ -1,5 +1,7 @@
-import { KeyDataPair, MessageData } from "../types";
+import { KeyDataPair, MessageData, DocumentData } from "../types";
 declare const _default: {
+    encodeDocumentData: (documentData: DocumentData) => string;
+    decodeDocumentData: (binary: string | ArrayBuffer | Uint8Array) => DocumentData;
     encodeEmailData: (emailData: MessageData) => string;
     decodeEmailData: (binary: string | ArrayBuffer | Uint8Array) => MessageData;
     encodeKeyDataPair: (keyData: KeyDataPair) => string;
diff --git a/dist/services/QrCodeDataService.js b/dist/services/QrCodeDataService.js
index 1c668db6c7598507da2882538839fcad47506bd2..b019c4eda6e11dfb26902f428b03cece1fa410a8 100644
--- a/dist/services/QrCodeDataService.js
+++ b/dist/services/QrCodeDataService.js
@@ -12,10 +12,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
 const qrcode_data_pb_1 = require("../generated/qrcode_data_pb");
 const common_1 = require("../utils/common");
 const index_1 = require("../index");
+const DocumentDataMessageV1 = qrcode_data_pb_1.vereign.protobuf.qrcode_data.DocumentData_V1;
 const EmailDataMessageV1 = qrcode_data_pb_1.vereign.protobuf.qrcode_data.EmailData_V1;
 const KeyDataMessageV1 = qrcode_data_pb_1.vereign.protobuf.qrcode_data.KeyData_V1;
 const WrapperDataMessage = qrcode_data_pb_1.vereign.protobuf.qrcode_data.WrapperData;
 const EMAIL_DATA_V1 = "EmailData_V1";
+const DOCUMENT_DATA_V1 = "DocumentData_V1";
 const encodeEmailData = (emailData) => {
     const emailDataMessage = EmailDataMessageV1.fromObject(emailData);
     const emailDataBuffer = EmailDataMessageV1.encode(emailDataMessage).finish();
@@ -83,7 +85,35 @@ const verifyQrCodeSignature = (publicKey, qrCodeSignature, recipientQRCodeHash)
     const result = yield index_1.CryptoService.verifyRSASignature(publicKey, recipientQRCodeHashAsBuffer, qrCodeSignatureAsBuffer);
     return result;
 });
+const decodeDocumentData = (binary) => {
+    const wrappedDataMessage = WrapperDataMessage.decode((0, common_1.ensureUint8Array)(binary));
+    const wrappedData = WrapperDataMessage.toObject(wrappedDataMessage);
+    if (wrappedData.className === DOCUMENT_DATA_V1) {
+        const documentDataMessage = DocumentDataMessageV1.decode((0, common_1.ensureUint8Array)(wrappedData.data));
+        const messageData = DocumentDataMessageV1.toObject(documentDataMessage, {
+            bytes: String,
+            arrays: true,
+            objects: true, // populates empty objects (map fields) even if defaults=false
+        });
+        return messageData;
+    }
+    return null;
+};
+const encodeDocumentData = (documentData) => {
+    const documentDataMessage = DocumentDataMessageV1.fromObject(documentData);
+    const documentDataBuffer = DocumentDataMessageV1.encode(documentDataMessage).finish();
+    const wrappedData = {
+        version: 1,
+        className: DOCUMENT_DATA_V1,
+        data: documentDataBuffer,
+    };
+    const wrappedDataMessage = WrapperDataMessage.fromObject(wrappedData);
+    const wrappedDataBuffer = WrapperDataMessage.encode(wrappedDataMessage).finish();
+    return (0, common_1.arrayBufferToBase64)(wrappedDataBuffer);
+};
 exports.default = {
+    encodeDocumentData,
+    decodeDocumentData,
     encodeEmailData,
     decodeEmailData,
     encodeKeyDataPair,
diff --git a/dist/types.d.ts b/dist/types.d.ts
index e346f229980231919afc52f9b8194e0af5367087..5c87d616e6f3c51e6f9dacbbda27da3f5569969d 100644
--- a/dist/types.d.ts
+++ b/dist/types.d.ts
@@ -135,3 +135,15 @@ export interface KeyDataPair {
     key: string;
     data: string;
 }
+export interface DocumentData {
+    author: string;
+    documentTitle: string;
+    documentDescription: string;
+    creationDate: string;
+    documentPages: number;
+    ipfs: IpfsContentData;
+}
+export interface DocumentStatusObject {
+    timestamp: number;
+    sealHash: string;
+}
diff --git a/src/services/QrCodeDataService.ts b/src/services/QrCodeDataService.ts
index 03bc827ef1452d97d5059839e28c31167d668879..38f08f62c5900570b75e84ab7de181a16aaf1032 100644
--- a/src/services/QrCodeDataService.ts
+++ b/src/services/QrCodeDataService.ts
@@ -1,4 +1,4 @@
-import { KeyDataPair, MessageData } from "../types";
+import { KeyDataPair, MessageData, DocumentData } from "../types";
 import { vereign } from "../generated/qrcode_data_pb";
 
 import {
@@ -9,11 +9,13 @@ import {
 
 import { CryptoService } from "../index";
 
+const DocumentDataMessageV1 = vereign.protobuf.qrcode_data.DocumentData_V1;
 const EmailDataMessageV1 = vereign.protobuf.qrcode_data.EmailData_V1;
 const KeyDataMessageV1 = vereign.protobuf.qrcode_data.KeyData_V1;
 const WrapperDataMessage = vereign.protobuf.qrcode_data.WrapperData;
 
 const EMAIL_DATA_V1 = "EmailData_V1";
+const DOCUMENT_DATA_V1 = "DocumentData_V1";
 
 interface WrappedData {
   version: number;
@@ -133,7 +135,53 @@ const verifyQrCodeSignature = async (
   return result;
 };
 
+const decodeDocumentData = (
+  binary: string | Uint8Array | ArrayBuffer
+): DocumentData => {
+  const wrappedDataMessage = WrapperDataMessage.decode(
+    ensureUint8Array(binary)
+  );
+  const wrappedData = WrapperDataMessage.toObject(
+    wrappedDataMessage
+  ) as WrappedData;
+
+  if (wrappedData.className === DOCUMENT_DATA_V1) {
+    const documentDataMessage = DocumentDataMessageV1.decode(
+      ensureUint8Array(wrappedData.data)
+    );
+
+    const messageData = DocumentDataMessageV1.toObject(documentDataMessage, {
+      bytes: String,
+      arrays: true, // populates empty arrays (repeated fields) even if defaults=false
+      objects: true, // populates empty objects (map fields) even if defaults=false
+    }) as DocumentData;
+
+    return messageData;
+  }
+
+  return null;
+};
+
+const encodeDocumentData = (documentData: DocumentData): string => {
+  const documentDataMessage = DocumentDataMessageV1.fromObject(documentData);
+  const documentDataBuffer =
+    DocumentDataMessageV1.encode(documentDataMessage).finish();
+
+  const wrappedData = {
+    version: 1,
+    className: DOCUMENT_DATA_V1,
+    data: documentDataBuffer,
+  };
+
+  const wrappedDataMessage = WrapperDataMessage.fromObject(wrappedData);
+  const wrappedDataBuffer =
+    WrapperDataMessage.encode(wrappedDataMessage).finish();
+  return arrayBufferToBase64(wrappedDataBuffer);
+};
+
 export default {
+  encodeDocumentData,
+  decodeDocumentData,
   encodeEmailData,
   decodeEmailData,
   encodeKeyDataPair,
diff --git a/src/types.ts b/src/types.ts
index be29d595d9ee722535f70fa3d72f2ef996aa8e6b..37557bcac0643e7d58c18078e23d25ad41ad734d 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -152,3 +152,23 @@ export interface KeyDataPair {
   key: string;
   data: string;
 }
+
+export interface DocumentData {
+  author: string;
+  documentTitle: string;
+  documentDescription: string;
+  creationDate: string;
+  documentPages: number;
+  ipfs: IpfsContentData;
+  // head of document //after ipfs impl
+  // cid of tail of document
+  // key
+  // Add the two below for UX optimization
+  // png of the first page
+  // sign  info
+}
+
+export interface DocumentStatusObject {
+  timestamp: number;
+  sealHash: string;
+}
diff --git a/vereign/protobuf/qrcode_data.proto b/vereign/protobuf/qrcode_data.proto
index 5e4e07ea749162a28d3b14ffbf75ceb40f5627ae..7f14d6af429b5c662685f5665d934d51e9dd3b4c 100644
--- a/vereign/protobuf/qrcode_data.proto
+++ b/vereign/protobuf/qrcode_data.proto
@@ -64,3 +64,12 @@ message WrapperData {
   int32 version = 2;
   string className = 3;
 }
+
+message DocumentData_V1 {
+  string author = 1;
+  string documentTitle = 2;
+  string documentDescription = 3;
+  string creationDate = 4;
+  int32 documentPages = 5;
+  IpfsData_V1 ipfs = 6;
+}