PrivMX DOCS
JavaScript

Working with Inboxes

About Inboxes

Inboxes are a way for users to send encrypted data to your app.

The advantage of Inboxes is that they don't require the user to be registered in order to send encrypted data. This opens up various possibilities in environments where you need to gather sensitive information from unregistered users (e.g. on your website).

Inboxes provide a secure way to receive entries from both internal and external sources.

  • Entries can contain binary data and files.
  • Each Context can contain any number of Inboxes with unique identifiers (inboxId) used to distinguish them.
  • Everyone with access to inboxID, solutionID, and Bridge URL can send an entry, but only the users who are added to given Inbox can read them.

Before working with Inboxes, follow our Getting Started Guide. It will show you how to set up your project to work with PrivMX Bridge.

Sample code on this page is based on the initial assumptions

Working with Inboxes

When working with Inboxes, you will use inboxApi, for methods used to manage Inboxes in given Context.

JavaScript
const threadApi = await Endpoint.createThreadApi(connection);
const storeApi = await Endpoint.createStoreApi(connection);
const inboxApi = await Endpoint.createInboxApi(connection, threadApi, storeApi);

Creating an Inbox

To create an Inbox, you need to name it and provide a list of public key - userID pairs. Due to the fact that each Inbox is inside a Context, all the public keys have to be registered inside the given Context. You can do it using PrivMX Bridge API context/addUserToContext method.

While creating an Inbox, you can also provide additional information:

  • publicMeta contains additional info about the Inbox. It is not encrypted before sending to PrivMX Bridge. Inbox API provides methods for accessing this field as publicView. For more information about Inbox publicView and its common use cases go to Using Public View.

  • privateMeta this field will be encrypted by PrivMX Endpoint before sending to PrivMX Bridge. It's meant to store additional sensitive information about the Inbox. privateMeta is accessible only for users registered to the given Inbox.

  • filesConfig you can specify up front file requirements for each entry submitted to the Inbox. This config includes min and max count of files in an entry, their max size, but also max size of whole upload.

  • policy determines what actions will be available to specific users. For more information and use cases, go to Policies.

Public and private metadata is sent in binary format.

Creating a basic unnamed Inbox, which can be used if your app needs only one Inbox and you don't need a distinction between them:

JavaScript
const users = [{ userId: 'MY_USER', pubKey: 'PUB_KEY' }, { userId: 'MY_USER2', pubKey: 'PUB_KEY2' }];
const managers = [{ userId: 'MY_USER', pubKey: 'PUB_KEY' }];


const inboxId = await inboxApi.createInbox(
    'CONTEXT_ID',
    users,
    managers,
    serializeObject("some public-meta"),
    serializeObject("some private-meta"),
    undefined // optional files config
);

Listing Inboxes

Your application may include multiple Inboxes, each associated with different Contexts. You can retrieve a list of all Inboxes within a given Context. This list, alongside the metadata you sent while creating the Inbox, will include useful metadata about the Inbox, such as the creation date, last file upload date, user list, and information about the last modification.

PrivMX Endpoint takes care of decrypting received data, which means you only have to take care of decoding them from binary format.

Listing the most recent Inboxes in given Context:

JavaScript
const defaultListQuery = {skip:0, limit: 100, sortOrder: "asc"};

const inboxList = await inboxApi.listInboxes(
    "CONTEXT_ID",
    defaultListQuery
);

const inboxListwithDeserializedMeta = inboxList.readItems.map(inbox => {
    return {
        inbox: inbox,
        privateMeta: deserializeObject(inbox.privateMeta),
        publicMeta: deserializeObject(inbox.publicMeta)
    };
});

Remember that data is transmitted in binary format, so you'll need to parse it back into your desired format. You can use the deserializeObject function provided by the SDK for this purpose.

Modifying Inboxes

Depending on your project's specification, it may be necessary to modify an Inbox. It could be, for example, changing the name or adding/removing users. Each user with management rights is able to modify Inboxes, delete them as a whole or only particular entries.

Three additional options are available when changing the list of users inside an Inbox:

  • force - applies an update, without checking the current version.
  • forceGenerateNewKey - re-encrypts entries in the Inbox. It's useful when a user is removed, and you want to prevent them from accessing the Inbox.
  • policy - you can also pass a new policy object as the last optional argument.

Updating an Inbox means overwriting it with the provided data. To successfully update an Inbox, you must specify its current version. The version field is mandatory to handle multiple updates on the server, and it is incremented by 1 with each update.

To update an Inbox you must always provide its current version, as well as:

  • list of users,
  • list of managers,
  • new private and public meta (even if it didn't change).
JavaScript
const inbox = await inboxApi.getInbox(
    inboxId    
);

const newUsers = inbox.users.map(user => ({
        //Your application must provide a way,
        //to get user's public key from their userId.
        userId: user,
        pubKey: 'USER_PUBLIC_KEY'
    })
);

const newManagers = newUsers.filter(user =>
    inbox.managers.find(manager => manager == user.userId));

const newPrivateMeta = {
    title: 'New inbox name'
};

await inboxApi.updateInbox(
    inboxId    
    newUsers,
    newManagers,
    inbox.publicMeta,
    serializeObject(newPrivateMeta),
    inbox.filesConfig,
    inbox.version,
    false, 
    false
);

Using Public View

You can fetch Inbox public view using getInboxPublicView. Public view contains the publicMeta field from Inbox.

Keep in mind that every user with access to Inbox ID can get its public view.

In Inboxes, publicMeta can store information about the required structure of an entry.

For example, while creating an Inbox, you could save the required fields:

publicMeta
{
    "fields": [
      {
        "type": "text",
        "question": "Your Name"
      },
      {
        "type": "select",
        "question": "Favorite Language",
        "options": ["JavaScript","Java","Swift","C#"]
      }
    ]
}

Then, you can dynamically create a form based on this schema:

JavaScript
const publicView = await inboxApi.getInboxPublicView(INBOX_ID)
const publicMeta = JSON.parse(uint8ToStr(publicView.publicMeta))

In React, for example, you could map each of the fields to its input types:

//rest of your component

<form>
    {publicMeta.fields.map(field => {
        switch (field.type) {
            case "text":
                return (
                    <>
                    <label>{field.question}</label>
                    <input type={"text"} name={field.question} />
                    </>
                )
            case "select":
                return (
                    <>
                    <label>{field.question}</label>
                    <select name={field.question}>
                        {field.options.map(option => (
                            <option value={option}>{option}</option>
                        ))}
                    </select>
                    </>
                )
            default:
                return <></>
        }
    })}
</form>

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

On this page

Working with Inboxes | PrivMX Docs