Jamf Pro — Integration Setup
Prerequisites
- A Jamf Pro instance (cloud-hosted,
https://<your-instance>.jamfcloud.com) - A Jamf Pro account that can create API Roles and Clients (Jamf Pro 10.49 or later)
- CMDash Essentials tier or above
Step 1: Create an API Role
Jamf's modern API uses roles rather than per-account permissions, so grant the read privileges CMDash actually uses and nothing else.
- Log in to Jamf Pro.
- Go to Settings → System → API Roles and Clients → API Roles.
- Click New.
- Name it
CMDash Read-Only. - Add exactly these privileges:
- Read Computers
- Read Computer Inventory Collection
- Click Save.
Least privilege: CMDash only ever issues
GETrequests against the computers-inventory collection. Do not grant write, delete, or command-sending privileges — nothing in this integration can use them, and a credential that can wipe a Mac is a materially different risk to hold.
Step 2: Create an API Client
- Go to Settings → System → API Roles and Clients → API Clients.
- Click New.
- Name it
CMDash. - Assign the CMDash Read-Only API role created above.
- Set an Access Token Lifetime. 30 minutes is fine — CMDash re-authenticates per sync.
- Click Enable API Client, then Save.
- Click Generate Client Secret and copy both the Client ID and the Client Secret.
The client secret is shown once. Generating a new one invalidates the previous secret immediately.
Step 3: Connect in CMDash
- Navigate to Integrations in your CMDash dashboard.
- Find Jamf Pro and click Connect.
- Enter:
- Instance — the subdomain only. For
https://acme.jamfcloud.com, enteracme. - API Token — the bearer token issued for your API client, stored as this connection's access token and sent as
Authorization: Bearer <token>.
- Instance — the subdomain only. For
- Click Save & Test Connection.
Why a token and not a client ID/secret pair: CMDash's OAuth plumbing resolves one server-wide client credential per provider, which is correct for a single platform tenant (Azure, Falcon) and wrong for Jamf, where every customer has their own instance and their own credentials. A per-connection API token is the honest shape for a per-tenant secret.
What Syncs
| Data Type | Jamf Pro API | Behaviour on failure |
|---|---|---|
| macOS fleet inventory — hostname, OS version, FileVault state, management connectivity, last check-in | GET /api/v1/computers-inventory (sections GENERAL, OPERATING_SYSTEM, DISK_ENCRYPTION) | Fails the sync — this is the only dataset |
How the numbers are computed
- Managed coverage is the percentage of computers whose Jamf management framework is responding (
remoteManagement.managed). A Mac enrolled but not responding does not count as managed. - Disk encryption reads the boot partition specifically (
bootPartitionEncryptionDetails), not the first partition Jamf returns. A Mac has more than one partition and the recovery partition is never encrypted, so reading the first would report an entire fleet as unencrypted. - Only a fully encrypted boot volume counts. Jamf reports
ENCRYPTINGwhile conversion is in progress, and a disk mid-conversion is not yet protected. - A computer Jamf reports no FileVault state for is recorded as unknown, never as unencrypted, and is excluded from both sides of the encryption-coverage percentage. "We cannot see this device" and "this device is unencrypted" are different claims.
- A computer that has never checked in is recorded with an epoch
lastSeenAt, never with "now".
Troubleshooting
- 401 Unauthorized: The client secret was regenerated (which invalidates the previous one), or the API client was disabled.
- 403 Forbidden: The API role is missing Read Computers or Read Computer Inventory Collection. Both are required; the first alone returns records with empty sections.
- Connection test fails with a DNS or network error: Check the Instance value. Enter only the subdomain (
acme), not the full URL and notacme.jamfcloud.com. - Encryption coverage is lower than expected: Macs mid-conversion (
ENCRYPTING) are counted as not-yet-encrypted, by design. Check whether a recent FileVault policy is still rolling out. - Encryption coverage is computed over fewer devices than your fleet size: that is intended. Only computers whose FileVault state Jamf actually reports are in the denominator.
Rate Limits & Sync Behavior
| Setting | Value |
|---|---|
| Sync frequency | Every 4 hours by default (syncInterval is configurable per connection) |
| Pagination | page/page-size, 200 records per page, capped at 5,000 records per sync |
| Rate limit handling | Routed through CMDash's shared token-bucket limiter, which paces requests across the page walk |
| Circuit breaker | Repeated failures open the breaker and the sync is skipped rather than hammering a struggling instance |
| Failed sync retry | Job queue retries 3 times with exponential backoff (starting at 30s) — see docs/developers/dead-letter.md |
Credential Rotation
Jamf API client secrets do not expire, but the access tokens minted from them do.
To rotate:
- In Jamf Pro: Settings → System → API Roles and Clients → API Clients → CMDash → Generate Client Secret. This invalidates the previous secret immediately, so update CMDash promptly.
- In CMDash: Settings → Integrations → Jamf Pro → Edit.
- Enter the new API Token and Save.
Known Limitations
- macOS only.
computers-inventoryis Jamf Pro's Mac collection. iPhones and iPads live behind/api/v1/mobile-devices, which this integration does not read — so an iOS-heavy fleet will show a smaller device count in CMDash than in Jamf. Adding mobile devices means a second fetch, not a wider mapping. - Jamf School and Jamf Now are not supported. Both are separate products with different APIs.
- No screen-lock or password-policy signal. Jamf exposes these through configuration-profile and policy resources rather than the inventory collection. CMDash reports nothing rather than inferring a lock policy from an unrelated field.
- No incidents or vulnerabilities. Jamf is a management plane, not a detection product. Claiming those signals would put a checkmark on the catalog page that this integration cannot back.
- The 5,000-computer ceiling is a truncation, not a sample. A fleet larger than that is walked in
idorder and cut off; coverage percentages are then computed over the truncated set and the sync log carries a warning. Contact support if your fleet exceeds this.