PrivMX DOCS
Version 2.2/Inboxes

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 containers 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.

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.

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)),
[]
);

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)

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.

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]
);

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)
}

Sending Entry

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

//previous code
await inboxApi.sendEntry(entryHandle)

Fetching Entries

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
}
})

We use cookies on our website. We use them to ensure the proper functioning of the site and, if you agree, for purposes we set, such as analytics or marketing.

On this page