Skip to main content
Question

Warranty information available in Apple Business Manager. Getting it into Jamf Pro

  • February 20, 2026
  • 4 replies
  • 52 views

RemcoVerburgh
Forum|alt.badge.img

Since November 2025 you can find the warranty information for your Mac devices in Apple Business Manager. You can call this information using API calls. Is there any information if Jamf is going to make an Jamf integration? This warranty information would be a cool feature to have in Jamf. As an MSP it would be great for Life Cycle Management for our customers.

I’ve seen no information from Jamf jet.

Sofar I've been working on local scripting in python to get the ABM warranty information in Jamf as an Extension Attribute. For Computers I've succeeded I'm however not successful yet for mobile devices. The Jamf Classic and Pro API’s won’t let me update Extension Attributes for mobile. So I'm stuc.

Anybody there who would like to help? Or can somebody tell me how to update an extension attribute for mobile, if it is possible and not blocked in api.

Kind Regard Remco. 

 

4 replies

Chubs
Forum|alt.badge.img+23
  • Jamf Heroes
  • February 20, 2026

Easiest/best method in the interim is a GSX account and poll that stuff directly from there. 
 

Also, the pro API will let you update EAs for mobile - you have to procreate the EA names in JAMF and then reference them in your API call to make status changes. 
 

Let me know if you want to see my script that does this. Oh and I’ve also gotten the API stuff from A working in bash too if you’d like to see that in order to stick with native builds of things. 


RemcoVerburgh
Forum|alt.badge.img
  • Author
  • New Contributor
  • February 20, 2026

GSX account would be great but we are in Europe and getting these gsm accounts for all our customers is simply not possible. GSX is more for fleets over 1000 devices. If you can provide a script or point out how to make the api update calls that would be great. II’ve got it working for Macs but somehow you can’t use it for mobile.


dletkeman
Forum|alt.badge.img+17
  • Jamf Heroes
  • February 20, 2026

I just saw this yesterday in Jamf Ideas.  Upvote them all if you like.  Just search for warranty or click the link below:

https://ideas.jamf.com/ideas/search?query=warranty


Chubs
Forum|alt.badge.img+23
  • Jamf Heroes
  • February 20, 2026

GSX account would be great but we are in Europe and getting these gsm accounts for all our customers is simply not possible. GSX is more for fleets over 1000 devices. If you can provide a script or point out how to make the api update calls that would be great. II’ve got it working for Macs but somehow you can’t use it for mobile.

#!/bin/bash
########################################################
# Mobile Extension Attribute Change
# Changes extension attribute value on mobile device
# Author: Jarred Wheeler
# v.01 10/2024
#
# Jamf Variables
# 4: Jamf Pro URL
# 5: Extension Attribute Name
# 6: API Client ID
# 7: API Client Secret
########################################################

########################################################
# Basic Variables
########################################################
#API Variables
url="$4"
eaName="$5"
client_id="$6"
client_secret="$7"
path="api/v2/mobile-devices"
apiEA="updatedExtensionAttributes"
IFS=','
read -ra optinArray <<< "$8"

#Device Variables
loggedInUser=$( scutil <<< "show State:/Users/ConsoleUser" | awk '/Name :/ && ! /loginwindow/ { print $3 }' )
loggedInUID=$(id -u $loggedInUser)
deviceSerial="placeholder"
serialCheck=""
deviceWorkflow=""

########################################################
# API Functions
########################################################

getAccessToken() {
response=$(curl --silent --location --request POST "${url}/api/oauth/token" \
--header "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "client_id=${client_id}" \
--data-urlencode "grant_type=client_credentials" \
--data-urlencode "client_secret=${client_secret}")
current_time=$(date +%s)
access_token=$(echo "$response" | plutil -extract access_token raw -)
token_expires_in=$(echo "$response" | plutil -extract expires_in raw -)
token_expiration=$(($current_time + $token_expires_in - 1))
}

checkTokenExpiration() {
current_time=$(date +%s)
if [[ token_expiration -ge current_time ]]
then
echo "Token valid until the following time: " "$token_expiration"
else
echo "No valid token available, getting new token"
getAccessToken
fi
}

invalidateToken() {
responseCode=$(curl -w "%{http_code}" -H "Authorization: Bearer ${access_token}" $url/api/v1/auth/invalidate-token -X POST -s -o /dev/null)
if [[ ${responseCode} == 204 ]]
then
echo "Token successfully invalidated"
access_token=""
token_expiration="0"
elif [[ ${responseCode} == 401 ]]
then
echo "Token already invalid"
else
echo "An unknown error occurred invalidating the token"
fi
}

json_array() {
echo '['
while [ $# -gt 0 ]; do
x=${1//\\/\\\\}
echo \"${x//\"/\\\"}\"
[ $# -gt 1 ] && echo ', '
shift
done
echo ']'
}

########################################################
# User Prompt Functions
########################################################
askSerial ()
{
while :; do
if [[ $deviceSerial = "" ]] || [[ $deviceSerial = "placeholder" ]]
then /bin/launchctl asuser $loggedInUID sudo -iu $loggedInUser whoami
deviceSerial=$(/bin/launchctl asuser "${loggedInUID}" sudo -iu "${loggedInUser}" /usr/bin/osascript<<EOL
tell application "System Events"
activate
with timeout of 900 seconds
set answer to text returned of (display dialog "Enter Mobile Device Serial Number" with title "Mobile Device Profile Change" default answer "")
end timeout
end tell
EOL)
if [[ $? = "1" ]]
then echo "user chose cancel"
exit 0
else if [[ $deviceSerial = "" ]]
then /bin/launchctl asuser $loggedInUID sudo -iu $loggedInUser whoami
noSerialProvided=$(/bin/launchctl asuser "${loggedInUID}" sudo -iu "${loggedInUser}" /usr/bin/osascript<<EOL
tell application "System Events"
activate
with timeout of 900 seconds
set theDialogText to "No serial provided. Please re-run the policy"
display dialog theDialogText buttons {"Exit"} default button "Exit" cancel button "Exit"
end timeout
end tell
EOL)
if [[ $noSerialProvided = "" ]]
then echo "user chose cancel"
exit 0
fi
fi
fi
else deviceSerial=$(echo $deviceSerial | tr '[:lower:]' '[:upper:]' | tr -d ' ')
break
fi
done
echo "Chosen device serial: $deviceSerial"
verifySerial
}

verifySerial ()
{
while :; do
if [[ $serialCheck = "false" ]] || [[ $serialCheck = "" ]]
then /bin/launchctl asuser $loggedInUID sudo -iu $loggedInUser whoami
serialCheck=$(/bin/launchctl asuser "${loggedInUID}" sudo -iu "${loggedInUser}" /usr/bin/osascript<<EOL
tell application "System Events"
activate
with timeout of 900 seconds
set answer to text returned of (display dialog "Re-enter Mobile Device Serial Number" with title "Mobile Device Serial Verification" default answer "")
end timeout
end tell
EOL)
serialCheck=$(echo $serialCheck | tr '[:lower:]' '[:upper:]' | tr -d ' ')
if [[ $serialCheck = "" ]]
then echo "user chose cancel"
exit 0
fi
else break
fi
done
doubleCheck
}

doubleCheck () {
if [[ $serialCheck != $deviceSerial ]]
then verifyPopup=$(/bin/launchctl asuser "${loggedInUID}" sudo -iu "${loggedInUser}" /usr/bin/osascript<<EOL
tell application "System Events"
activate
with timeout of 900 seconds
set theDialogText to "Serials do not match. Would you like to try again?"
display dialog theDialogText buttons {"Exit", "Try Again"} default button "Try Again" cancel button "Exit"
end timeout
end tell
EOL)
if [[ $verifyPopup = "" ]]
then echo "user chose cancel"
exit 0
else deviceSerial="placeholder"
serialCheck=""
askSerial
fi
fi
mobileWorkflow
exit
}

# Prompt for Device opt-in as the user
mobileWorkflow () {
/bin/launchctl asuser $loggedInUID sudo -iu $loggedInUser whoami
deviceWorkflow=$(/bin/launchctl asuser "${loggedInUID}" sudo -iu "${loggedInUser}" /usr/bin/osascript<<EOL
set theArray to the paragraphs of "$(printf '%s\n' "${optinArray[@]}")"
set chosenWorkflow to choose from list theArray with prompt "Please select an update group to move the device into. Click Cancel to stop."
chosenWorkflow
EOL)
echo $deviceWorkflow
# Soft exit if user cancels
if [[ $deviceWorkflow = "" ]] || [[ $deviceWorkflow = "false" ]]
then echo "$loggedInUser Canceled process... Exiting"
exit 0
fi
echo "Chosen prestage: $deviceWorkflow"
changeUpdateGroup
}

########################################################
# API Run Functions
########################################################
changeUpdateGroup() {
checkTokenExpiration
eaValue="$deviceWorkflow"
deviceID=$(curl -X GET --url "${url}/${path}/detail?section=GENERAL&page=0&page-size=100&filter=serialNumber%3D%3D%20"${deviceSerial}"" -H 'accept: application/json' -H 'content-type: application/json' -H "Authorization: Bearer $access_token" | grep "mobileDeviceId" | awk -F'"' '{print $4}')
jsonData=$(
cat <<EOF
{
"${apiEA}": [
{
"name": "${eaName}",
"type": "STRING",
"value": [
"${eaValue}"
]
}
]
}
EOF
)

checkUG=$(curl -X GET --url "${url}/${path}/${deviceID}/detail" -H 'accept: application/json' -H 'content-type: application/json' -H "Authorization: Bearer $access_token" | grep -A 2 "Update Ring"| grep "value" | awk -F'"' '{print $4}')
if [[ $checkUG == $eaValue ]]
then sameUpdateGroup=$(/bin/launchctl asuser "${loggedInUID}" sudo -iu "${loggedInUser}" /usr/bin/osascript<<EOL
tell application "System Events"
activate
with timeout of 120 seconds
set theDialogText to "${deviceSerial} is already a member of ${prestageName}."
display dialog theDialogText buttons {"Exit"} default button "Exit" with title "No Changes Made"
end timeout
end tell
EOL)
echo "Device is already a member of the desired prestage"
exit 0
fi
changeUG=$(curl -X PATCH --url "${url}/${path}/${deviceID}" -H 'accept: application/json' -H 'content-type: application/json' -H "Authorization: Bearer $access_token" -d "${jsonData}")
checkUG=$(curl -X GET --url "${url}/${path}/${deviceID}/detail" -H 'accept: application/json' -H 'content-type: application/json' -H "Authorization: Bearer $access_token" | grep -A 2 "Update Ring"| grep "value" | awk -F'"' '{print $4}')
echo $checkUG

########################################################
# User verification notification
########################################################
if [[ $eaValue == $checkUG ]]
then completePopup=$(/bin/launchctl asuser "${loggedInUID}" sudo -iu "${loggedInUser}" /usr/bin/osascript<<EOL
tell application "System Events"
activate
with timeout of 120 seconds
set theDialogText to "${deviceSerial} has successfully been moved to the ${eaValue} update group. Please check for updates to download the latest available iOS/iPadOS for this group."
display dialog theDialogText buttons {"Exit"} default button "Exit" with title "Update Group Move Completed"
end timeout
end tell
EOL)
else failedPopup=$(/bin/launchctl asuser "${loggedInUID}" sudo -iu "${loggedInUser}" /usr/bin/osascript<<EOL
set theAlertText to "Error Moving Prestages"
set theAlertMessage to "${deviceSerial} migration to the ${eaValue} update group was unsuccessful. Please submit a ticket if there's an issue."
display alert theAlertText message theAlertMessage as critical buttons {"Exit", "Email EET-Apple", "Submit a Ticket"} default button "Submit a Ticket" cancel button "Exit" giving up after 120
set the button_pressed to the button returned of the result
if the button_pressed is "Submit a Ticket" then
open location "https://stjude.service-now.com/sp?id=sc_cat_item&sys_id=287252614f9e96004ce80ad14210c7c9&sysparm_category=null&catalog_id=e0d08b13c3330100c8b837659bba8fb4&referrer=popular_items"
end if
if the button_pressed is "Email EET-Apple" then
open location "mailto:eet-apple@stjude.org"
end if
EOL)
fi
}

checkTokenExpiration
askSerial

Now keep in mind I wrote this to be used from Self Service, so it has prompts and stuff in it.

You can use this as a springboard though to do what you want.  Just make sure your mobile extension attributes are precreated.