Here is a return to service script we use for resetting all our retail devices nightly if you don’t have access to jamf routines. We run this as a scheduled task from a windows server.
API permissions on the account i’m using for this: View Return To Service Configurations, Update Mobile Devices, Read Mobile Devices, Read Smart Mobile Device Groups, Read Static Mobile Device Groups, Delete Return To Service Configurations, Send Mobile Device Remote Wipe Command, Edit Return To Service Configurations, Send MDM command information in Jamf Pro API
import requests, json, os
from datetime import datetime
# =========================
# Config
# =========================
JAMF_URL = ""
CLIENT_ID = "" # API Client ID
CLIENT_SECRET = "" # API Client Secret
GROUP_ID = # Smart Group ID you want to RTS
DRY_RUN = False # ⚠️ Change to False to actually send RTS
LOG_FILE = r"C:\Jamf Scripts\RTS.log" # Where to write logs
# =========================
# Helpers
# =========================
def log(msg):
timestamped = f"[{datetime.now():%Y-%m-%d %H:%M:%S}] {msg}"
print(timestamped)
try:
with open(LOG_FILE, "a", encoding="utf-8") as f:
f.write(timestamped + "\n")
except Exception as e:
print(f"⚠️ Failed to write log file: {e}")
def get_token():
resp = requests.post(
f"{JAMF_URL}/api/oauth/token",
data={
"client_id": CLIENT_ID,
"client_secret": CLIENT_SECRET,
"grant_type": "client_credentials"
},
headers={"Accept": "application/json"}
)
resp.raise_for_status()
return resp.json()["access_token"]
def send_group_rts(token, group_id):
url = f"{JAMF_URL}/api/v1/mobile-device-groups/{group_id}/erase"
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
payload = {
"preserveDataPlan": True,
"disallowProximitySetup": True,
"clearActivationLock": True,
"returnToService": True
}
r = requests.post(url, headers=headers, data=json.dumps(payload))
if r.status_code in [200, 201, 202]:
log(f"✅ RTS command sent to group {group_id}")
else:
log(f"❌ RTS failed: {r.status_code} {r.text}")
# =========================
# Main
# =========================
def main():
try:
token = get_token()
if DRY_RUN:
log(f"🔎 Dry run only. Would send RTS to group {GROUP_ID}")
else:
send_group_rts(token, GROUP_ID)
except Exception as e:
log(f"💥 Script error: {e}")
if __name__ == "__main__":
main()
