Automating Device Assignments in Apple School Manager at West Virginia University
I’ve been wanting to do a proper writeup on this project for a while now, and after presenting it at a Rocketman Tech Launchpad session and getting some really great questions and feedback, it felt like the right time to sit down and put it all together.
The Problem
At West Virginia University, our IT support structure is decentralized. That’s a nice way of saying we have a lot of moving parts. My team supports over 15 Jamf Pro sites, and each one of those has its own and sometimes multiple Automated Device Enrollment configurations. That means we also need 15+ MDM server locations inside Apple School Manager just to keep everything organized and flowing to the right place.
Up until we implemented this automation, the way we handled device assignments was pretty manual. When Apple shipped devices to the university, a shipment notification email would come in, a Jira ticket would get generated, and a member of our service desk would identify who purchased the device, figure out which support unit they belong to, and then manually assign the device to the correct MDM server in Apple School Manager.
That process worked, and I want to give credit to the service desk because they did a solid job with it. But it was prone to the kinds of issues you’d expect from a manual workflow. Human error, timing issues, split shipments where devices show up in ASM at different times, and occasionally devices just getting missed entirely. We also had devices coming in through our cellular contract that bypassed the shipment notification process altogether, so those were basically invisible until someone noticed.
To catch those stragglers, we set up a “Default Assignment” MDM server location. Every device that wasn’t explicitly assigned somewhere would land there and enroll into a default Jamf Pro site. The user would get a notification that their device wasn’t configured correctly, which at least gave us a safety net. It’s been working well for a few years, but I always knew there had to be a better way.
The Opportunity
When Apple released the new Business/School Manager API at WWDC, I immediately started digging into the documentation. The API gave us the ability to search for devices in specific server locations, pull device information, and most importantly, move devices between server locations programmatically.
I realized I could build something that would automatically figure out who purchased a device, determine which support unit they fall under, and move the device to the correct MDM server location, all before the user even gets their hands on it. No one would need to manually look up purchasers or determine support units. The entire assignment process could just happen.
How It Works
There are two main parts to this workflow, and I built the entire thing inside our Azure tenant.
Part 1: Data Collection
This is the foundation of everything, because this is how we link a purchaser to a device.
We still rely on shipment notification emails from Apple, but instead of a human reading them, I have an Azure Logic App doing it. The Logic App monitors a mailbox and triggers when a new email arrives matching the shipment notification format. It parses out all the data we care about:
- Apple Sales Order Number
- Email Recipient (this is the purchaser)
- PO Number
- Web Order Number
- Apple Delivery Number
- Apple Customer Number
- Carrier Name and Tracking Number
Realistically, the only two fields we absolutely need are the Email Recipient and the Apple Sales Order Number. But I wanted to capture everything because it gives us a much better method of historical record keeping than just leaving emails sitting in a mailbox.
All of that parsed data gets written to an Azure Storage Table. The Partition Key is the same for all entries (“ASM”), and the Apple Sales Order Number is used as the Row Key. This makes lookups fast and straightforward when we need to find a specific order later on.
That’s it for data collection. Simple, but it’s the most important piece.
Part 2: Processing Devices
This is where the automation actually happens. It’s a Python script running inside an Azure Automation Account as a runbook.
Finding new devices: Remember that Default Assignment location? That’s our starting point. The script queries the ASM API to check if there are any devices sitting in that MDM server location. If there’s nothing there, the script exits because there’s nothing to process. If there are devices, we grab the serial numbers and start working through them one by one.
Linking devices to orders: For each device, we make an API call to Apple School Manager to get the device’s details. The key piece of information here is the Order Number. The Order Number on the device object in ASM matches the Apple Sales Order Number from the shipment notification email. That’s our link.
Finding the purchaser: With the order number in hand, we search our Azure Storage Table for the matching entry. If there’s no match, the script logs it and sends a notification to our Teams channel so someone on the team knows there’s a device that needs manual attention. If we do find a match, we pull the Email Recipient field, and that’s our purchaser.
Determining the support unit: This is where it gets a little more involved, and I need to thank the Windows side of my team for making this possible. They built out a system using Administrative Units in Entra ID to group users by their support units. So once we have the purchaser’s email, we perform a lookup in Entra to find the user and look at which Administrative Unit they belong to.
Once we have the user’s Administrative Unit, we query another Azure Storage Table that maps Administrative Units to support units. And once we have the support unit, we can hit one more Storage Table that maps support unit names to ASM Server IDs.
I set up the server mapping table so that the support unit name is the Row Key and the ASM Server ID is stored alongside it. This means if a unit changes names or we add a new one, it’s just a new row in the table. No code changes needed.
Moving the device: With the correct Server ID identified, we use the ASM API to create a device activity that moves the device from the default location to its proper MDM server. From there, it automatically populates in the correct Jamf Pro site for Automated Device Enrollment.
Notifications and Visibility
Every run of this automation sends a consolidated summary to a Microsoft Teams channel via webhook. The notification is formatted as an Adaptive Card that breaks down exactly what happened: which devices were processed, who the purchasers were, what sites they were assigned to, and whether any devices hit errors that need manual follow-up.
If the script encounters a critical error, a separate error notification goes out so the team knows something went wrong and can investigate.
All of this is also logged within the runbook execution itself, so we have full traceability for anything that happens.
Performance Considerations
Apple’s API has rate limits, so I built in proper handling for that. The script respects Retry-After headers on 429 responses and uses exponential backoff for retries. There’s also a small delay between processing each device to stay well within the limits.
I also added caching for order lookups. If multiple devices share the same order number (which happens with bulk purchases), the script only queries the Storage Table and Entra once for that order and reuses the result. This cut down on both API calls and processing time significantly.
Where Things Stand
This workflow has been running and reliably processing devices. It handles the majority of our device assignments automatically, and the ones it can’t figure out still land in the default assignment site where they’re flagged for manual review.
The result is that devices are getting assigned to the correct Jamf Pro sites before users even receive them. What used to be a manual process that depended on someone reading an email, looking up a purchaser, and clicking through Apple School Manager is now something that just happens in the background.
What I’d Tell You If You’re Thinking About This
If your environment has similar challenges with device assignment and you have access to the ASM/ABM API, I’d genuinely encourage you to look into automating it. The API documentation from Apple is solid, and if you’re already in Azure, the pieces fit together pretty naturally.
The other thing I’d recommend is starting in a read-only mode. I ran this for a while where it would go through the entire process but only log what it would have done instead of actually moving devices. That gave me the confidence that the logic was solid before flipping it on.
If you’ve got questions or want to talk through how something like this might work in your environment, feel free to reach out. I’m always happy to talk about this stuff.