Jamf Pro API Script to put a new device into the same static groups as an old one

Use case… we are replacing a computer. We want to add the new computer to the same static groups to which the old computer was assigned.

Requirement: We need to install a utility called “jq” to help parse the json formatted data returned by the Jamf Pro API. You can get it from https://stedolan.github.io/jq/

Create a text file. You can call it whatever you want, but in this example, we are calling it “devicelist.csv“. “.csv” stands for “comma-separated-values”. There can be many lines in the file. Each line has three values, each of which are separated by a comma. The fields are device_type,old_device_id,new_device_id. In theory, you could also use any device identifier that the Jamf Pro API allows, like serial numbers, uuid, or device_name, but if the device name includes a comma that would break the script since bash csv parsing is not very smart. An example line using device id numbers would look like…


When you run the script, computer 122 (new computer) will have the same static group memberships as those currently assigned to record number 6 (old computer).

Then save this script and make it executable. Edit the script to set INPUT to the path to the .csv file with the device list. change the jss_url setting to your Jamf Pro server and api_user to your username and password. The user will need read on computers and update on Static Computer Groups.

This might save you about 1,000 clicks, but it is probably not a good choice for a beginner API script. Making a mistake could cause some bad results if important things are scoped to your static groups. Try it a few times on some test devices before you start messing with user machines and go into Jamf Pro and check that the results are what you wanted. If you have a lot of devices you’re replacing, you might run it on some small groups of user machines before you run it on all of them.


# Purpose: Read Comma Separated CSV File with lines in the form
# computer | mobile_device, old_device_identifier, new_device_identifier
# Put the new device(s) into the same static groups as the corresponding old one
# ------------------------------------------
device_key="id"  # serialnumber | id | uuid
# End of settings

[ ! -f $INPUT ] && { echo "$INPUT file not found"; exit 99; }
echo "Getting API authorization token"
header='Content-Type: application/json'
uapi_token_json=$( curl --silent --show-error --header "${header}" --user "${api_user}" --request POST --url "${auth_url}" )
# echo '$uapi_token_json : ' $uapi_token_json
uapi_token=$( echo "${uapi_token_json}" | jq -r '.token' )
# echo $uapi_token

echo "Reading device list from file ${INPUT}"
# Note the current field separators
# Change field separators to , so we can split the fields
# Loop through the lines in the file...
while read device_type old_id new_id
	echo "Processing Device -- device_type: \"${device_type}\", old_id: \"${old_id}\", new_id: \"${new_id}\""
  # echo "Getting groups from ${url}"
  device_json=$( curl \
       --request GET \
       --silent --show-error \
       --header "Authorization: Bearer ${uapi_token}" \
       --header 'Accept: application/json' \
       --url "${url}" )
  #   echo "$device_json"
  # Get the group memberships from the json
  device_json2=$( echo "$device_json" | jq --compact-output -r '.results[0].groupMemberships' )
  #   echo "$device_json2"
  # Set the field separators back to normal so we can split the group membership list items
  # Loop through the group listing. We're base-64-ing the records so they don't split funny
  for row in $(echo "${device_json2}" | jq -r '.[] | @base64'); do
    # That gets you a group record... {
    #   "groupId": "1",
    #   "groupName": "All Managed Clients",
    #   "smartGroup": true
    # }
    # This function un-base-64s the record and extracts a field's value
    _jq() {
      echo ${row} | base64 --decode | jq -r ${1}
    # Call the above function to get the true|false value of the smartGroup field
    # If it is not a smart group then it is a static group, which is what we want. 
    if [[ $(_jq '.smartGroup') == 'false' ]]; then
      groupName=$( _jq '.groupName' )
      groupId=$( _jq '.groupId' )
      echo "Adding device ${device_key} ${new_id} to groupName: ${groupName}, groupId: ${groupId}..."
      # echo "$xml"
      curl  \
       --request PUT \
       --silent --show-error \
       --user "${api_user}" \
       --header 'Content-Type: application/xml' \
       --data "${xml}" \
       --url "${url}"
done < $INPUT
# Set the field separators back to normal


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: