Managing integration mapping between Slack channels and Box folders using the Box API

Paweł Fijałkowski
Box Developer Blog
Published in
9 min readJun 6, 2023
Box for Slack integration helps users seamlessly access and share the content stored in Box.

Box enterprise users enjoy 1500+ integrations like Microsoft Teams, Salesforce, Zoom and Slack. Among the most popular integrations is Box for Slack. The application offers convenient features such as the ability to quickly select and share permissions for shared files, receive Box notifications directly within Slack, and provide a single secure Content Layer for all conversations in Slack.

When Box as the Content Layer for Slack is enabled, Box folders are created for each channel, and files are uploaded to those folders. Channel members become editing collaborators of the created folder, and content is easily accessible via bookmark in the channel.

Box Integration Mappings API — why do I need it?

Teams across enterprises tend to work in a similar fashion, having a Slack channel and a Box folder or number of folders per initiative (sales pitch, recruitment process, etc.). Until now, Box for Slack users in enterprises with Box as the Content Layer for Slack had to rely on the default channel-to-folder mapping. Integration Mappings API allows Box Admins to customize the upload folder to fit your team-specific needs, by targeting the uploads to any folder within Box enterprise.

Goals and assumptions

In this article, I will describe how to manage (create, update, and delete) a custom mapping between a Box folder and a Slack channel using the Integration Mappings API.

Before we start, make sure you satisfy all of the prerequisites:

  1. Box enterprise account you’re using has a Admin or Co-admin role.
  2. Box for Slack is installed in the relevant Slack workspaces or orgs (link).
  3. Box as the Content Layer for Slack is enabled (link).

Note, that for Slack-side channel validation, the Integration Mappings API is calling the Slack API.

Box Integration Mappings API — what it offers?

As stated in the developer documentation, the API offers standard CRUD endpoints for mapping management:

GET— fetching and filtering the mappings (both created manually by the Admin and automatically created by the integration).

curl --location --request GET 'https://api.box.com/2.0/integration_mappings/slack?partner_item_id=C987654321&box_item_id=123456789' \
--header 'Authorization: Bearer {{token}}' \

POST — creating a new mapping. Requires providing box_item and partner_item, which are references to the Box folder and Slack channel. Providing options will override default settings for the created mapping. For example: is_access_management_disabled option will disable creating collaborations on the Box folder, assuming the Admin handles access themselves.

curl --location --request POST 'https://api.box.com/2.0/integration_mappings/slack' \
--header 'Authorization: Bearer {{token}}' \
--header 'Content-Type: application/json' \
--data-raw '{
"partner_item": {
"id": "C987654321",
"type": "channel",
"slack_workspace_id": "T5555555"
},
"box_item": {
"id": "123456789",
"type": "folder"
}
}'

PUT— updating options (e.g. is_access_management_disabled) of the mapping or the target Box folder.

curl --location --request PUT 'https://api.box.com/2.0/integration_mappings/slack/512521' \
--header 'Authorization: Bearer {{token}}' \
--header 'Content-Type: application/json' \
--data-raw '{
"options": {
"is_access_management_disabled": true
}
}'

DELETE— deleting the mapping. Deleting the mapping for a channel will result in the creation of a new, default channel folder when the next file is next uploaded. When the mapping is deleted, neither the Box folder nor the Slack channel gets deleted.

curl --location --request DELETE 'https://api.box.com/2.0/integration_mappings/slack/512521' \
--header 'Authorization: Bearer {{token}}' \
--data-raw ''

Authorization

In order to be able to call the Integration Mappings API, the Admin needs to create a Custom App in Box Developer Console. This tutorial utilizes the “User Authentication (OAuth 2.0)” authentication method, but it’s also possible to opt for “Server Authentication”.

Create an app to authorise requests. Select OAuth 2.0 as the authentication method for the application.

After creating the application, in Configuration > Application Scopes section, the Admin must select “Manage enterprise properties” and save changes, as this scope is required to call the API.

Check “Manage enterprise properties” scope.

Then, the easiest way to authorize is to generate and add Developer Token to the HTTP header of each Integration Mappings API request: Authorization: Bearer {developer_token}.

Generate Developer Token to access the API.

The token will be valid for 60-minutes and will need to be regenerated after that time. Of course, Admin can also go through the OAuth 2.0 flow in order to obtain an access token (Box developer documentation for reference).

Creating the mapping

Postman and Box UI

In this section, we will use Postman and Box UI to create the Slack channel — Box folder mapping. Postman is an API development and testing tool. Refer to Postman’s documentation for more information.

Let’s assume that we have a folder in Box and a channel in Slack, and we want the uploads for that channel to point to that folder.

Folder in Box, already contains content.

In order to create the mapping, we will be sending POST request. As specified in the API reference, we need to provide partner_item and box_item in the payload.

Body of a POST request to create a slack integration mapping.

Slack applications can be installed in a single workspace or across the whole organization (see documentation). In the case of a workspace installation of Box for Slack, input data for partner_item can be easily found in the URL of the Slack channel : app.slack.com/client/{slack_workspace_id}/{channel_id}.

Alternatively, to find your channel_id, you can double click on the channel name, and select “View channel details” and copy from the bottom of the displayed modal.

Channel ID can be found in the “View channel details” modal.

For org-wide installations, channel_id is found in the same way as above, and slack_org_id can be found in the URL of the Slack org management page: app.slack.com/manage/{slack_org_id} (that is the case in the screenshot).

Similarly, box_item can be found in the URL of the Box folder: app.box.com/folder/{folder_id}.

Additionally, we can provide options if we want to override the default settings for the created mapping.

After sending the request, you will most likely, get the following error response:

Box as a File Storage for Slack service account needs to be a co-owner of the folder.

Box as the Content Layer for Slack uses a service account to manage content and collaborators inside channel folders. Before the mapping can be created, this service account needs to have a collaboration in the co-owner role on the folder that is being mapped. The easiest way to create the collaboration is to copy the service_account_email from context_info (AutomationUser_...) and then use the Box UI (“Invite People”).

Adding service account as an co-owner of the Box folder using Box UI.

After resending the request, you should be able to create the mapping (if that’s not the case, see “Troubleshooting” section). Box API will return 201 Created as well as a full integration mapping object.

Slack channel — Box folder mapping was successfully created and returned.

Admin can verify that the mapping was created by sending a GET request with partner_item_id equal to the channel_id of the mapped channel.

Now, let’s verify that everything is working by performing an upload to Slack.

File is uploaded to Slack channel that was mapped to the Box folder manually. Bookmark points to the folder with the same id that we provided in the request.
File was correctly uploaded to the Box folder and channel members were collaborated onto the folder.

As visible in the screenshots from both Box and Slack, a custom folder is used for uploads to Box. Bookmark points to that folder, and collaborators are synchronized with channel members in Slack. We managed to successfully connect the Slack channel and Box folder.

Box SDK

Admins can use the Box SDK in order to automate the whole process. First, in the Box application configuration, check “Write all files and folders stored in Box” so that we will be able to create collaborations:

In the application configuration, select “Write all files and folders stored in Box”.

After saving the changes, Admin should be able to use the script below to automatically create a co-owner collaboration (service account information is extracted from the error message similarly to the “manual” method) of the service account on the folder and the Slack channel — Box folder mapping.

const BoxSDK = require('box-node-sdk');
const axios = require('axios');

const integrationMappingsApiUrl = 'https://api.box.com/2.0/integration_mappings/slack'
const boxFolderId = 'PASTE YOUR FOLDER ID HERE';
const slackChannelId = 'PASTE YOUR CHANNEL ID HERE';
const slackOrgId = 'PASTE YOUR SLACK ORG ID HERE (CHANGE TO WORKSPACE ID IF NECESSARY)';
const developerToken = 'PASTE YOUR DEVELOPER TOKEN HERE';

let serviceAccountId = '<PLACEHOLDER>';

const client = BoxSDK.getBasicClient(developerToken);

async function postIntegrationMappingSlack(){

return axios.post(integrationMappingsApiUrl, {
partner_item: {
id: slackChannelId,
slack_org_id: slackOrgId, // change slack_org_id to slack_workspace_id if Box for Slack is installed on the workspace level
type: "channel"
},
box_item: {
id: boxFolderId,
type: "folder"
}
}, {
headers: {
'Authorization': `Bearer ${developerToken}`
}
});

}

function isPlaceholder(str){
return str === '<PLACEHOLDER>';
}

async function addCoowner(serviceAccountId, folderId){
try {
await client.collaborations.createWithUserID(serviceAccountId, folderId, 'co-owner')
} catch (error){
if(error.response.body.code === 'user_already_collaborator'){
console.log('Service account already collaborated in the co-owner role.')
} else {
throw error;
}
}
}

async function logServiceAccountId() {
try {
await postIntegrationMappingSlack();
} catch (error) {
console.log(`Replace the value of serviceAccountId with: ${error.response.data.context_info.service_account_id} and re-run the script.`)
}
}

async function createSlackIntegrationMapping() {

if(isPlaceholder(serviceAccountId)){
await logServiceAccountId();
} else {
await addCoowner(serviceAccountId, boxFolderId);
await postIntegrationMappingSlack();
}

}

module.exports = { createSlackIntegrationMapping }

Similarly to the example in Postman, if Box for Slack is deployed per workspace, then slack_org_id should be replaced with slack_workspace_id.

When you run the script for the first time, the console will display the serviceAccountId. Please remember to replace the <PLACEHOLDER> with this value, which remains constant for each enterprise.

Troubleshooting

Integration mappings API performs different types of validation to ensure the correctness of the mapping. Here, we provide a description and possible solutions for those validation errors.

Service account is not a co-owner of the folder

The Box as Content Layer for Slack service account must be added as a co-owner or owner of the folder in order to manage collaborations and uploads.

SERVICE_ACCOUNT_IS_NOT_A_COOWNER_OR_OWNER error response.

To resolve this error, add the service account (you can use the ID or email provided in the error message) as a co-owner or owner of the folder through Box UI or Box SDK.

Channel is already mapped to a folder in Box

The API will return the following error when the user attempts to create a mapping for a channel that already has a Box folder mapped.

CHANNEL_ALREADY_MAPPED error response.

If the intention is to start using a new folder, use GET to retrieve the id of the mapping and then UPDATE method to update the target Box folder.

Channel was not found

The API will return this error if the Slack bot associated with the integration is not able to retrieve information about the channel.

CHANNEL_NOT_FOUND error response.

Ensure that the partner_item is correct (make sure you provide slack_org_id for org installations and slack_workspace_id for workspace ones). If the channel is private, ensure that the Slack bot has been added to the channel.

Channel not suitable for Custom File Storage (CFS)

Slack Connect channels (cross enterprise channels) are currently not supported as a part of Box as a Content Layer for Slack.

CHANNEL_NOT_SUITABLE_FOR_CFS error response.

Box folder externally owned

Box folder selected for mapping must be owned by the enterprise that the Admin is part of.

BOX_FOLDER_EXTERNALLY_OWNED error response.

Custom File Storage (CFS) disabled

The API will return this error upon trying to create the mapping for an enterprise that has Box for Slack installed but has not enabled Box as a Content Layer for Slack. For more details see this article on how to enable Box as Content Layer for Slack.

Box enterprise mismatch

The API will return this error when there is a mismatch between the Admin’s enterprise and Box for Slack configuration. Check out this article on how to enable Box for Slack.

Conclusions

Integration Mappings API allows the Admin to easily manage Slack channel and Box folder mappings in their enterprise. It allows for greater flexibility, allowing the teams to drift away from the default folder structure created by Box for Slack. Admins can at any time modify the mapping, changing the Box folder or access management options for a channel. Switching back to default behaviour is as easy as deleting the mapping and uploading a file.

Thanks for reading the article, Box Partner Integrations Team hopes you managed to find all the answers you looked for.

If you want to submit feedback, please use Box Pulse and follow Box Developers profile on Twitter to stay up-to-date!

--

--