Skip to main content

Inbox Entries

Inboxes allow users to receive encrypted entries, either from external or internal sources.

  • Internal sources are people who have access to an Inbox, or are simply registered in a given Context. Those users are known to your application, and their entries can be linked to their accounts.

  • External sources are people from the outside; they do not have an account linked with your app. For example, someone who fills out an online contact form without the need to create an account.

The key difference between Inboxes and other PrivMX tools is that people don't need accounts in your app to be able to submit entries.

About Entries

The structure of an entry and a brief description of its elements is outlined in the following table:

FieldTypeEncryptedDescription
databinaryContent of the entry
filesFile[]List of attached files
authorPubKeystringPublic key of the author

Define Data Structure

Inbox's architecture does not require you to use a specific data structure inside the entries. Before working with Inboxes, define the structure of your entries.

Info

We recommend future-proofing your entries by choosing an easily modifiable format. It is a good idea to include both a type and a version field in the structure.

Example: Form with Text Answer

JSON
{
“content”: {
"answer": USER_PROVIDED_TEXT
},
“version”:number,
“type”: "text_answer",
}

The type field allows future support for different types of entries like: "select_answer", or "multi_select". And in case of changing the schema, you can always distinguish between them using "version" field.

Remember that this is only an example and you should consider your app's requirements and limitations.

Submitting Entries

To submit an entry, you need:

  • URL of your PrivMX Bridge Instance
  • Solution ID with at least one Inbox created
  • ID of the Inbox to submit the entry

If you need more information about how to create an Inbox, go to Creating Inbox.

Sending Process

Sending entries is carried out in two (or three if files are attached) steps.

  1. Preparing Entry

    Use the prepareEntry method to provide the Inbox ID and the data you want to submit. Optionally, you can provide file handles and a private key.

    If you don't want to send any files, pass an empty array for the file handles.

    const entryData = {
    content: {
    "answer": USER_PROVIDED_TEXT
    },
    version:number,
    type: "text_answer",
    }

    const entryHandle = await inboxApi.prepareEntry(
    inboxID,
    this.strToUint8(JSON.stringify(entryData)),
    []
    );

    For JavaScript reference go here.

  2. Sending Entry

    After preparing an entry you will receive an Inbox handle. In this case, all you have to do is pass it to sendEntry method.

    // previous code
    await inboxApi.sendEntry(entryHandle)

    For JavaScript reference go here.

Working With Files

Inbox entries can include any number of files (in accordance with the predefined Inbox file configuration).

Each file may include its own public and private metadata to store additional information.

For example, to include file name and mimetype information, pass this data as JSON to the publicMeta (or privateMeta, if the file name contains sensitive information):

For example:

privateMeta
{
"name":FILE_NAME,
"mimetype": FILE_MIMETYPE
}

Attaching Files

Sending entries with attached files follows a similar process to sending entries without files. The main difference is that you must create file handles for each file and stream their content.

  1. Preparing Entry

    For each file you want to send, create a file handle. You can provide additional data, e.g. file name or its metadata.

    If you’re creating a questionnaire, you can relate files with questions by putting question info in the file's metadata.

    const selectedFile = //File selected by user

    const filePrivateMeta = {
    name: selectedFile.name,
    mimetype: selectedFile.type
    }

    const fileHandle = inboxApi.createFileHandle(
    strToUin8(""),
    strToUin8(JSON.stringify(filePrivateMeta)),
    selectedFile.size
    )

    // preparing entry as shown before
    const entryHandle = await inboxApi.prepareEntry(
    inboxID,
    this.strToUint8(JSON.stringify(entryData)),
    [fileHandle]
    );

    For JavaScript reference go here.

  2. Sending File Contents

    For large files, it is recommended to stream the file content in small buffers rather than loading the entire file into memory. PrivMX Endpoint divides those buffers if required, then streams them to your PrivMX Bridge.

    //previous code
    const reader = await selectedFile.stream().getReader()

    while(true){
    const { done, value } = await reader.read();

    if(done){
    break;
    }

    await inboxApi.writeToFile(entryHandle, fileHandle, value)
    }
  3. Sending Entry

    Finally, send the entry in the same way as described before:

    //previous code
    await inboxApi.sendEntry(entryHandle)

Fetching Entries

Info

Fetching entries requires decoding them back into their original format. Depending on your data structure, you will need to parse and decode the fetched entries.

The process for fetching entries heavily depends on your entry format. Refer back to Define Data Structure if you need guidance on how to structure your entry.

Basic Entries

After fetching entries, you must first decrypt them back to their original format. For schema used earlier, this process looks like this:

//define how much you want to fetch and skip
const defaultQuery = {skip:0, limit:100, sortOrder: "asc"}
const readList = inboxApi.listEntries(inboxId, defaultQuery)

const decodedEntries = readList.readItems(entry => {
return {
...entry,
data: JSON.parse(uint8ToStr(entry.data))
}
})

Entries with Files

Entries include only file metadata, without their contents. Similar to entries data, you have to decode them before using.

For example, if you saved name and metadata of a file in its privateMeta, you can read them like this:

//define how much you want to fetch and skip
const defaultQuery = {skip:0, limit:100, sortOrder: "asc"}
const readList = inboxApi.listEntries(inboxId, defaultQuery)

const decodedEntries = readList.readItems(entry => {
//decoding file meta first
const decodedFiles = entry.files.map(file => {
return {
...file,
privateMeta:JSON.parse(uint8ToStr(file.privateMeta)),
}
})
return {
...entry,
data: JSON.parse(uint8ToStr(entry.data)),
files:decodedFiles
}
})