Hello Jamf Nation! Today we’ll be diving into the recent deprecation of the computers inventory endpoints in the Classic API. This guide will help you transition your existing code to use the new Jamf Pro API computer inventory endpoints, which offer enhanced capabilities including sorting, filtering, and pagination.
Key Differences
Endpoint Structure
Classic API: /JSSResource/computers
Jamf Pro API: /api/v1/computers-inventory
Data Format
Classic API:
XML-based requests and responses (default)
JSON responses available but XML required for PUT/POST
Jamf Pro API:
JSON-based for all operations
More structured and consistent data types
Clearer property naming conventions
New Features in Jamf Pro API
1. Section-Based Data Retrieval
The Jamf Pro API allows you to request specific sections of computer data. If no section parameter is supplied, only the “General” section will be returned, with other sections including a null value. If the data you’re looking for is missing, make sure to specify the corresponding section within the request.
GET /api/v1/computers-inventory?section=GENERAL§ion=HARDWARE
You can also provide a list of sections for using commas to separate the values. The following request is equivalent to the one above and saves some characters. Saving characters can be important if you're using a complex RSQL filter.
GET /api/v1/computers-inventory?section=GENERAL,HARDWARE
For a full list of the sections available, check out the API reference documentation on the Developer Portal.
2. RSQL Filtering
The Jamf Pro API supports powerful RSQL filtering. Some of the existing capabilities in the Classic API, such as the ability to obtain a device via serial number have been maintained via RSQL filtering. Check out the examples below, and see our full guide on filtering with RSQL here.
# Find computers by serial number
GET /api/v1/computers-inventory?filter=hardware.serialNumber=="C02L29ECF8J1"
# Find computers by udid
GET /api/v1/computers-inventory?filter=udid=="6ac0ea2a-b4ff-4fe7-93d5-eccdd14bb1a3"
# Complex filtering with multiple conditions
GET /api/v1/computers-inventory?filter=general.name=="*Lab*";hardware.make=="Apple"
3. Pagination
Forget the days of needing to iterate over every device one API request at a time. Pagination allows you to control result size and navigate through large datasets with ease. Default page size is 100, but can be customized to a maximum of 2000 results per page. If no page or page-size parameter are provided, the first 100 results will be returned.
GET /api/v1/computers-inventory?page=0&page-size=100
4. Sorting
When working with large datasets, make sure to use the same sorting preferences throughout all requests. Changing the sorting preferences will change which data results are returned on which page, creating opportunities for missing results. See the example below to sort results using multiple criteria:
GET /api/v1/computers-inventory?sort=general.name:asc,general.reportDate:desc
Code Example: Obtaining Computer Inventory Data via Jamf Pro API
Below we’ve constructed a sample Python script which models many of the basic functions needed to work with the Jamf Pro API, including how to handle authentication, pagination and section query parameters.
#!/usr/bin/env python3
import requests
import json
from typing import List, Dict, Any
from urllib.parse import urljoin
class JamfProAPI:
def __init__(self, url: str, username: str, password: str):
"""
Initialize the Jamf Pro API client
Args:
url: Jamf Pro URL (e.g., 'https://your.jamf.server')
username: API username
password: API password
"""
self.base_url = url.rstrip('/')
self.username = username
self.password = password
self.token = None
def authenticate(self) -> None:
"""Authenticate and get bearer token"""
auth_url = urljoin(self.base_url, '/api/v1/auth/token')
response = requests.post(
auth_url,
auth=(self.username, self.password),
headers={'Accept': 'application/json'}
)
response.raise_for_status()
self.token = response.json()['token']
def get_computers_inventory(self, sections: List[str] = None, page: int = 0,
page_size: int = 100) -> Dict[str, Any]:
"""
Retrieve computer inventory data with pagination and optional section filtering
Args:
sections: List of sections to retrieve (e.g., ['GENERAL', 'HARDWARE'])
If None, returns GENERAL section by default
page: Page number (0-based)
page_size: Number of records per page (default 100, max 2000)
Returns:
Dict containing results and total count
"""
if not self.token:
self.authenticate()
endpoint = '/api/v1/computers-inventory'
url = urljoin(self.base_url, endpoint)
# Build query parameters
params = {
'page': page,
'page-size': page_size
}
# Add sections if specified
if sections:
for section in sections:
params['section'] = sections
headers = {
'Accept': 'application/json',
'Authorization': f'Bearer {self.token}'
}
response = requests.get(url, headers=headers, params=params)
response.raise_for_status()
return response.json()
def get_all_computers(jamf: JamfProAPI, sections: List[str] = None) -> List[Dict[str, Any]]:
"""
Retrieve all computers by handling pagination automatically
Args:
jamf: Initialized JamfProAPI instance
sections: List of sections to retrieve
Returns:
List of all computer records
"""
all_computers = []
page = 0
page_size = 100
while True:
# Get page of results
response = jamf.get_computers_inventory(sections=sections,
page=page,
page_size=page_size)
# Add results to master list
computers = response.get('results', [])
all_computers.extend(computers)
# Check if we've retrieved all records
total_count = response.get('totalCount', 0)
if len(all_computers) >= total_count:
break
# Move to next page
page += 1
return all_computers
def main():
# Example usage
jamf_url = 'https://your.jamf.server'
username = 'your-username'
password = 'your-password'
# Initialize API client
jamf = JamfProAPI(jamf_url, username, password)
# Example sections to retrieve
sections = [
'GENERAL',
'HARDWARE',
'OPERATING_SYSTEM',
'USER_AND_LOCATION'
]
try:
# Get all computers with specified sections
computers = get_all_computers(jamf, sections=sections)
print(f"Retrieved {len(computers)} computers")
# Example: Print some basic info for each computer
for computer in computers:
general = computer.get('general', {})
print(f"Name: {general.get('name')}")
print(f"Serial: {general.get('serialNumber')}")
print(f"Last Check-in: {general.get('lastContactTime')}")
print("---")
except requests.exceptions.RequestException as e:
print(f"Error accessing Jamf Pro API: {e}")
if __name__ == '__main__':
main()
Benefits of Using the Jamf Pro API
Better Performance: Request only the sections you need
Flexible Filtering: Complex queries using RSQL
Efficient Pagination: Handle large datasets more effectively
Consistent JSON: Modern data format with well-defined schemas
Future-Proof: All new features will only be available in the Jamf Pro API
Best Practices
Use RSQL filters instead of separate endpoints for different lookup types
Request only needed sections to improve performance
Implement pagination for large data sets
Use sorting to maintain consistent data ordering
Test thoroughly during migration to ensure data consistency
Additional Resources
Jamf Pro API Documentation
RSQL Filtering Guide
API Deprecation Documentation
Remember to test your code thoroughly when migrating from the Classic API to the Jamf Pro API, as there are significant differences in data structure and response formats. The new API provides more powerful and flexible ways to interact with computer inventory data while improving performance and maintainability.
Need more help getting started with your scripts? Ask the AI assistant! The sample code included above was generated by the Jamf AI assistant which can help you update your code as well. Please share any feedback, questions, or your own experiences around the migration to the Jamf Pro API.
... View more