PrivMX DOCS
Version 2.3/Inboxes

Working with Inboxes

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.

Permissions

The user list in Inbox is designed to be flexible, accommodating a wide range of use cases.

Inboxes differentiate three types of users: Regular Users, Managers, and External Users. The table below shows what actions can be performed by each type of users:

ActivityUserManagerExternal
Submitting entriesyesyesyes
Fetching entriesyesyesno
Deleting entriesnoyesno
Editing Inboxnoyesno

The values above are the default policy values defined by PrivMX. To read more about Policies and learn how to modify them, go to Policies.

Initial Assumptions

The initial assumptions for all the code examples below are as follows:

Replace placeholder values such as BRIDGE_URL, SOLUTION_ID, CONTEXT_ID with those corresponding to your PrivMX Bridge instance.

The private keys here are for demonstration purposes only. Normally, they should be kept separately by each user and stored in a safe place, or generated from a password (see the derivePrivateKey2() method in Crypto API)

#include <privmx/endpoint/core/Connection.hpp>
#include <privmx/endpoint/thread/ThreadApi.hpp>
#include <privmx/endpoint/store/StoreApi.hpp>
#include <privmx/endpoint/inbox/InboxApi.hpp>
#include <privmx/endpoint/core/Buffer.hpp>
// ...

/* 
All the values below like BRIDGE_URL, SOLUTION_ID, CONTEXT_ID 
should be replaced by the ones corresponding to your Bridge Server instance.

The private keys here are for demonstration purposes only. 
Normally, they should be kept separately by each user and stored in a safe place,
or generated from a password (see the derivePrivateKey2() method in the Crypto API).
*/

std::string BRIDGE_URL {"http://localhost:9111"};
std::string SOLUTION_ID {"YOUR_SOLUTION_ID"};
std::string CONTEXT_ID {"YOUR_CONTEXT_ID"};

std::string USER1_ID {"user_1"};
std::string USER1_PUBLIC_KEY {"PUBLIC_KEY_1"};
std::string USER1_PRIV {"PRIVATE_KEY_1"};

std::string USER2_ID {"user_2"};
std::string USER2_PUBLIC_KEY {"PUBLIC_KEY_2"};

std::string USER3_ID {"user_3"};
std::string USER3_PUBLIC_KEY {"PUBLIC_KEY_3"};

// initialize Endpoint connection and Threads API
auto connection {core::Connection::connect(USER1_PRIV, SOLUTION_ID, BRIDGE_URL)};
auto threadApi {thread::ThreadApi::create(connection)};
auto storeApi {store::StoreApi::create(connection)};
auto inboxApi {inbox::InboxApi::create(connection, threadApi, storeApi)};

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

After creating an Inbox, all the users with management rights will be able to edit it. Skip to Modifying Inboxes for more info.

The examples below demonstrate how to create Inboxes:

Create a new Inbox with access for user_1 as a manager and user_2 as a regular user. You can include the name of the Inbox within the privateMeta object. This metadata is encrypted before being sent to PrivMX Bridge, ensuring its confidentiality.

std::vector<core::UserWithPubKey> managers{
    core::UserWithPubKey{USER1_ID, USER1_PUBLIC_KEY}
};
std::vector<core::UserWithPubKey> users{
    core::UserWithPubKey{USER1_ID, USER1_PUBLIC_KEY},
    core::UserWithPubKey{USER2_ID, USER2_PUBLIC_KEY}
};
// create a new Inbox with access for user_1 as manager and user_2 as regular user
auto storeId {inboxApi.createInbox(CONTEXT_ID, users, managers, 
    core::Buffer::from("some store's public meta-data"), 
    core::Buffer::from("some store's private meta-data")
)};

Managers declared while creating the Inbox, also have to be included in the regular user list.

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.

Here's an example of how to download the last 30 Inboxes created within a Context:

core::PagingQuery defaultListQuery = {.skip = 0, .limit = 30, .sortOrder = "desc"};

// fetching Inboxes
auto inboxList {inboxApi.listInboxes(CONTEXT_ID, defaultListQuery)};
for (const auto& inbox : inboxList.readItems) {
    std::cout << "Inbox ID: " << inbox.inboxId << std::endl;
}

To limit collecting too much data when downloading Inboxes, specify the page index (starting from 0) and the number of items to be included on each page.

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.

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.

Below there is an example of modifying an Inbox:

// Add a new user to the existing ones in the Inbox
std::vector<core::UserWithPubKey> newUsersList{
    core::UserWithPubKey{USER1_ID, USER1_PUBLIC_KEY},
    core::UserWithPubKey{USER2_ID, USER2_PUBLIC_KEY}
    core::UserWithPubKey{USER3_ID, USER3_PUBLIC_KEY}
};
// Getting a single Inbox
auto currentInbox {inboxApi.getInbox(inboxId)};

// Update a new Inbox with access for USER_1 as the only user.
inboxApi.updateInbox(
    inboxId, 
    users, managers,
    currentInbox.publicMeta, 
    currentInbox.privateMeta,
    currentInbox.filesConfig,
    currentInbox.version, // <- pass the version of the Inbox you will perform the update on
    false, // <- force update (without checking version)
    false // <- force to regenerate a key for the Store
);

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.

Deleting an Inbox

You can delete an Inbox using the deleteInbox method.

Below there is an example of deleting an Inbox:

inboxApi.deleteInbox(inboxId);

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:

// Retrieve and print the public view of the Inbox
auto publicView {inboxApi.getInboxPublicView(inboxId)};
std::cout << "Public meta: " << publicView.publicMeta.stdString() << std::endl;

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.

This is documentation for PrivMX v2.3, which is no longer actively maintained.

For up-to-date documentation, go to latest here

On this page