Jamf Sync - SS67/project-docs GitHub Wiki
Yes, Jamf has its own vocabulary, and it maps almost one to one onto what you just did with Entra. Learn the mapping and the whole Intune experience transfers:
| Entra term | Jamf term |
|---|---|
| App registration | API Client |
| API permission | API Role (a named bundle of privileges) |
| Application (client) ID | Client ID |
| Secret Value, shown once | Client Secret, also shown once, same trap |
| Admin consent | Assigning the role to the client |
| Graph endpoint | Jamf Pro API on your instance URL |
Setup lives in Jamf Pro under Settings, API Roles and Clients. Admin creates a Role with privileges, creates a Client, attaches the role, enables it, and generates the secret. Auth is OAuth client credentials, functionally identical to what you tested last week. The only per tenant piece is the instance URL, typically https://company.jamfcloud.com.
Case description for the Jamf admin:
"Requesting a read only API Client in Jamf Pro for automated asset inventory sync into Freshservice. Please create an API Role named aap-fresh-asset-sync-read with the Read Computers privilege only, create an API Client with that role, enable it, and share the Client ID and Client Secret through <your secret channel, not the ticket>. Note the secret displays only once at generation. Also confirm the instance base URL and the client's access token lifetime setting. No write privileges needed."
The token lifetime line matters: Jamf lets admins set it per client and some set it very short. Your collector fetches per run anyway, but knowing the number avoids confusion when a token dies mid pagination test.
Verification, same two call pattern as Intune:
TOKEN=$(curl -s -X POST "https://${JAMF_URL}/api/oauth/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=${CLIENT_ID}" \
-d "client_secret=${CLIENT_SECRET}" \
-d "grant_type=client_credentials" | python3 -c "import sys,json;print(json.load(sys.stdin)['access_token'])")
curl -s -H "Authorization: Bearer ${TOKEN}"
"https://${JAMF_URL}/api/v1/computers-inventory?page=0&page-size=5§ion=GENERAL§ion=HARDWARE"
| python3 -m json.tool
Data terminology worth knowing before you browse output: the endpoint is computers-inventory, paginated with page and page-size rather than nextLink, and a section parameter selects data blocks per device, GENERAL, HARDWARE, USER_AND_LOCATION, OPERATING_SYSTEM among others. Identity keys are serial number and udid, and macOS serials are clean by nature, no blocklist drama expected. USER_AND_LOCATION carries the assigned user, Jamf's equivalent of your owner attribution goal.
Design wise, one sentence and we park it: Jamf is the Intune pattern with macOS swapped in, jamf_* field group, same enricher role, same gap report against Discovery Agent coverage (worth confirming the agent even runs on your Macs, if not, Jamf may end up lifecycle owner for the class, a decision for that workstream's design doc, not this chat). When access lands, it gets its own file set and tracker per the portfolio rule.