Addigy can be used to automatically upload files from end user’s devices to your organization’s Slack workspace.
Slack API Bot Scope Permissions
Before proceeding, review your Slack workspace safety guidelines to determine the necessary bot permissions. Once granted, use tokens carefully, as Slack Bot permissions vary depending on API requests given to the bot.
For file uploads, Slack recommends two permission scopes for your bot:
-
files:read – Grants access to read files.
-
files:write – Allows file uploads and removal of files your app controls.
NOTE: You can set these under Apps > OAuth & Permissions in your Slack app settings
The following Slack article provides more detail about working with files: SLACK API: Working with files
Uploading Files Via New API Method
As of March 11, 2025, newly created Slack apps can no longer use the files.upload API method. Existing apps should migrate to the more reliable approach using files.getUploadURLExternal and files.completeUploadExternal, especially for large file uploads.
For more details on the deprecation: files.upload retires in March 2025, replaced by sequenced Web API methods
The script provided below uses the new method to collect Addigy logs from a device and upload them to Slack, but it can be modified to upload any file(s) from an end user’s device.
Please note that the following variables must be updated to match your organization’s Slack token and the desired channel ID:
slack_token="YOUR SLACK TOKEN"
slack_channel="YOUR SLACK CHANNEL ID"
Additionally, the slack_message variable can be modified to display a custom message about the file(s) being uploaded.
This script can be run as a Saved Script on individual machines (via GoLive) or on multiple machines at once (via the Devices page). For more information about running scripts through Addigy, see the following: Creating and Running Scripts on Your Devices (Saved Scripts)
#!/bin/bash
# Script ID: SUP01CHSXYDWQQ25
## DO NOT EDIT ##
## DEVICE INFORMATION VARIABLES ##
device=$(hostname | cut -d. -f1) # Device Name
serial=$(ioreg -c IOPlatformExpertDevice -d 2 | awk -F\" '/IOPlatformSerialNumber/{print $(NF-1)}') # Serial Number
org_id=$(/Library/Addigy/go-agent agent orgid) # Org ID
## LOG INFORMATION & FILE CREATION VARIABLES ##
current_date_time=$(date) # Current Date & Time
# File & Directory Names
file_name="Log Upload | ${device} | ${serial} | ${current_date_time}.tar.gz"
file_dir="${device} | ${serial} | ${org_id} | ${current_date_time}"
file_path="./$file_name"
# Addigy Logs
Addigy_logs_zip="Addigy-Logs-${device}.zip"
Addigy_logs_dir="Addigy Logs | ${serial}"
## END OF LOG INFORMATION & FILE CREATION VARIABLES ##
## SLACK VARIABLES ##
slack_token="YOUR SLACK TOKEN"
slack_channel="YOUR SLACK CHANNEL ID"
slack_message="Addigy Logs:
Device Name: ${device}
Serial Number: ${serial}
OrgID: ${org_id}
Date: ${current_date_time}"
## Step 0: Performing the log process ##
echo "CREATING TEMP DIRECTORIES...."
# Create a TEMP Directory for Final TAR GZ File for Slack Upload
if [ -d "$file_dir" ]; then
rm -rf "$file_dir" # Remove the directories if they exist and create new ones
fi
mkdir "$file_dir"
echo "DIRECTORY CREATED: $file_dir"
# Create a TEMP Directory for Addigy Logs
if [ -d "$Addigy_logs_dir" ]; then
rm -rf "$Addigy_logs_dir" # Remove the directories if they exist and create new ones
fi
mkdir "$Addigy_logs_dir"
echo "DIRECTORY CREATED: $Addigy_logs_dir"
echo "FINISHED CREATING THE TEMP DIRECTORIES...."
echo "## BEGIN OF ADDIGY LOG CAPTURE LOGS ##"
# Checking for the Addigy LOG DIR
if [ -d "/Library/Addigy/logs/" ]; then
echo "Addigy Log Directory Exist..."
if [ "$(ls -A /Library/Addigy/logs/)" ]; then
echo "Addigy Log Files exist in /Library/Addigy/logs/"
# Copy over Addigy logs to the TEMP DIR
sudo cp -R /Library/Addigy/logs/* "${Addigy_logs_dir}" 2>/dev/null
echo "Moving Adidgy DIR to the main directory..."
# ZIP everything inside apple TEMP DIR
zip -r "${Addigy_logs_zip}" "${Addigy_logs_dir}"/* > /dev/null 2>&1
# Check if ZIP file exists before moving
echo "Moving Apple ZIP File to the main directory..."
if [ -f "$Addigy_logs_zip" ]; then
if mv "$Addigy_logs_zip" "$file_dir"; then
echo "Addigy Logs ZIP File Move was successful!"
else
echo "Addigy Logs ZIP File Move failed."
fi
else
echo "Addigy Logs ZIP File does not exist."
fi
else
echo "No files found in Addigy Log Directory"
fi
else
echo "Addigy Log Directory does not exist."
fi
# Archive logs
echo "ARCHIEVEING LOGS...."
tar -czvf "${file_name}" "${file_dir}" 2>/dev/null
echo "## END OF ADDIGY LOG CAPTURE ##"
# Get the file length
file_length=$(stat -f %z "$file_path")
## SLACK PROCESS ##
echo ""
echo "## BEGIN OF SLACK BOT FILE UPLOAD ##"
## BEGIN OF SLACK BOT FILE UPLOAD ##
## Step 1: Request an upload URL from Slack ##
echo "Requesting upload URL..."
UPLOAD_REQUEST=$(curl -s -X POST "https://slack.com/api/files.getUploadURLExternal" \
-H "Authorization: Bearer $slack_token" \
-F "filename=$file_name" \
-F "length=$file_length")
# Grabbing the upload URL
UPLOAD_URL=$(echo "$UPLOAD_REQUEST" | awk -F'"upload_url":"' '{print $2}' | awk -F'"' '{print $1}' | sed 's/\\//g')
# Check if UPLOAD_URL is null
if [ "$UPLOAD_URL" == "null" ]; then
echo "Error getting upload URL: $UPLOAD_URL"
exit 1
fi
# Outputting the Upload URL
echo "Received upload URL: $UPLOAD_URL"
# Grabbing the File ID
FILE_ID=$(echo "$UPLOAD_REQUEST" | awk -F'"file_id":"' '{print $2}' | awk -F'"' '{print $1}')
# Ensure the file ID is in the correct format
if [[ ! "$FILE_ID" =~ ^[F][A-Z0-9]{8,}$ ]]; then
echo "Error: Invalid file ID format: $FILE_ID"
exit 1
fi
# Check if FILE_ID is null
if [ "$FILE_ID" == "null" ]; then
echo "Error: File ID is null."
exit 1
fi
# Performing the First Check for FileID
echo "File ID: $FILE_ID"
## Step 2: Upload the file to the provided upload URL ##
echo "Uploading file..."
UPLOAD_RESPONSE=$(curl -s -X POST "$UPLOAD_URL" \
-F "file=@$file_path" \
-F "initial_comment=$slack_message" \
-F "channels=$slack_channel" \
-H "Authorization: Bearer $slack_token")
## Step 3: Finalize the file upload in Slack ##
echo "Finalizing upload..."
FINALIZE_RESPONSE=$(curl -s -X POST "https://slack.com/api/files.completeUploadExternal" \
-H "Authorization: Bearer $slack_token" \
-H "Content-Type: application/json; charset=utf-8" \
-d "{\"files\": [{\"id\": \"$FILE_ID\"}], \"channel_id\": \"$slack_channel\", \"initial_comment\": \"$slack_message\"}")
if [[ "$(echo "$FINALIZE_RESPONSE" | awk -F'"ok":' '{print $2}' | awk -F',' '{print $1}' | tr -d ' }"')" != "true" ]]; then
echo "Error finalizing upload: $FINALIZE_RESPONSE"
exit 1
else
echo "File upload finalized in Slack!"
fi
## Step 4: FINAL CHECK AND CLEAN UP ##
echo "Final Check for File Info...."
FILE_INFO=$(curl -s -X GET "https://slack.com/api/files.info?file=$FILE_ID" \
-H "Authorization: Bearer $slack_token")
# Grabbing the File ID & Creation & TimeStamp
final_file_id_check=$(echo "$FILE_INFO" | awk -F'"file":{"id":"' '{print $2}' | awk -F'"' '{print $1}')
final_file_creation_check=$(echo "$FILE_INFO" | awk -F'"created":' '{print $2}' | awk -F',' '{print $1}' | tr -d ' }"')
final_file_upload_check=$(echo "$FILE_INFO" | awk -F'"timestamp":' '{print $2}' | awk -F',' '{print $1}' | tr -d ' }"')
# Outputting Final Check for File ID, Creation, & Timestamp
echo "FILE ID: $final_file_id_check"
# Both values might be identical if the file was created and uploaded immediately.
# NOTE: However, if you upload an older file, "created" might be earlier than "timestamp".
echo "FILE Creation Timestamp: $(date -r "$final_file_creation_check")"
echo "FILE Upload Timestamp: $(date -r "$final_file_upload_check")"
# Checking Slack Channel Information
echo "Final Check for Slack Channel Info...."
CHANNELS=$(curl -s -X GET "https://slack.com/api/conversations.list" \
-H "Authorization: Bearer $slack_token")
# Checking Correct Slack channel
Channel_Info=$(echo "$CHANNELS" | grep -o '"id":"[^"]*"' | grep "$slack_channel")
# Extracting Slack Channel ID
final_channel_id_check=$(echo "$Channel_Info" | awk -F'"id":' '{print $2}' | awk -F',' '{print $1}' | sed 's/"//g')
# Outputting Channel ID and Name
echo "Slack Channel ID: $final_channel_id_check"
echo "## END OF SLACK BOT FILE UPLOAD ##"
## END OF SLACK PROCESS FILE UPLOAD ##
## Step 5: Clean up ##
rm -rf "${file_dir}" # Use the correct path for removal
rm "${file_name}" # Remove the archive file after upload
exit 0
The following output is expected after running the script:

The file(s) will appear as a new message in the Slack channel like so:
