Skip to content

Platform API Commands

Neil Martin edited this page Sep 18, 2026 · 17 revisions

Platform API Commands

Platform API commands operate on shared Jamf Platform services: blueprints, compliance benchmarks, DDM reports, and unified device management.

Most of them sit under jamf-cli pro and need platform gateway authentication (auth-method: platform). jamf-cli platform setup writes a gateway profile; see Setup Guide#Jamf Pro Quick Start: Platform Gateway (Recommended).

For shared CLI patterns (apply, scaffold, pagination, dry-run), see CLI Patterns.

The Platform API reached general availability on 2026-09-03. The base URL is https://{region}.api.jamfcloud.com (no /api segment), and the pre-GA {region}.apigw.jamf.com host is retired: a profile still naming it is refused by name before any request is sent. Public-beta credentials stopped working at GA, so register a replacement API integration in Jamf Account. Platform API GA Migration carries the migration, the error messages verbatim and the refused-command list.

Scope: prefer --environment-id. A Jamf Platform API integration is created at one of three levels, and a credential works with the level it was created at: organization (no ID, selected by the gateway host alone), platform environment (--environment-id / JAMF_ENVIRONMENT_ID, the level to prefer), and tenant (--tenant-id / JAMF_TENANT_ID, the legacy level: one Jamf Pro / School / Protect / Security Cloud tenant per profile). Supplying two at once is refused, in the environment as well as in a profile. The scope travels in an X-Environment-Id / X-Tenant-Id request header.

Three families live under platform. Jamf AI Governance, Jamf Account (licensing, partners, SSO) and platform audit are scoped at the organization or environment level and name no Jamf Pro tenant, so they sit in a top-level platform namespace. See Jamf Platform Commands. platform audit reads the platform event log; pro audit runs health checks against a Jamf Pro instance.

Platform commands are always visible in pro --help, and return an error with setup instructions when platform auth is not configured. Running one against an instance profile is refused with exit code 8, naming the profile, its resolved auth method and platform setup.

Identifiers: positional <id>, names via --name. Unlike Protect and School (which take a positional <name>), Platform commands take the resource ID positionally and resolve names through a --name flag. A name passed positionally goes to the API as an ID and 404s; passing both <id> and --name is rejected. The exceptions are blueprints clone <source-name> <new-name>, compliance-benchmarks export <title> / clone <source-title> <new-title>, and platform-device-groups add-members / remove-members <name> (all names positionally), platform-devices get/delete <id|serial> (either, auto-detected), and ddm-reports device <deviceId> (ID only, no --name). apply takes no identifier on any resource: the input is the desired state and carries its own name (title on a benchmark).

Shared behaviour of Platform commands

Behaviour Detail
Request bodies --from-file accepts JSON or YAML, and is optional: leave it off and the body is read from stdin, so --scaffold | edit | apply pipes end to end. An empty pipe is not a body (a CI runner hands every process one), and a named --from-file that is empty is an error. --set key=value (repeatable, dot notation for nested keys) overlays onto that body, or builds one on its own, and errors when a path segment already holds a non-object, leaving the body untouched: --set settings.banner.enabled=true over a body whose settings is a string answers cannot set nested key under non-object field "settings". Classic --set differs: it builds the whole body and cannot be combined with a file. --scaffold prints an example body and needs no auth.
Name lookup --name lists the collection and matches client-side, accumulating matches across every page before deciding. A name repeated either side of a 100-item page boundary is an ambiguity error, and a name matching an item the list returns no ID for is reported as that.
Output flags --out-file, --select, --compact, --quiet and --no-hints work on every command. --select and --compact narrow rows for every column format.
Enum fields --help lists the allowed values for every enum-constrained request field, one line per dotted path. A [] suffix on the path constrains each element of an array. --scaffold renders an enum as "", so --help is where the legal set lives.
-n, --dry-run Honoured on every generated Platform write: it prints the method, the resolved path and the request body to stderr and returns. Name resolution runs first, so the preview reports the real path. The preview comes before any confirmation prompt, so -n on a destructive command works under --no-input without also pre-authorising the real thing. A hand-written platform write with no per-command preview is refused under -n: blueprints apply, compliance-benchmarks apply and platform-device-groups apply answer 412 [DRY_RUN] refused POST …: --dry-run is set and this command has no preview mode and exit 1, while blueprints delete, deploy and undeploy print a preview.
Empty lists An empty collection prints [], never null, so | jq '.[]' is safe on a tenant with nothing in it: pro categories list --filter 'name=="zzz-no-such"' | jq -r '.[].name' prints nothing and exits 0.
Piped-body ceiling A piped body is capped at 10MB. The generated commands and pro platform-device-groups patch / patch-members refuse one over the cap (stdin body exceeds 10MB; use --from-file for a larger payload). The hand-written readers truncate at the same ceiling without reporting it (blueprints apply, compliance-benchmarks apply, platform-device-groups apply, blueprints components configuration-profile and configuration-profile-plist), and a truncated YAML document still parses, so a long document loses its trailing fields and reports success. Verified 2026-09-11 on blueprints apply. Use --from-file for anything near the cap.
A 403 Exits 5, and names the capability permission it wanted plus the section and permission name Jamf Account's Platform API integration picker shows for it, since that picker is searched by name and displays no slug. A 403 carrying OWNERSHIP_FORBIDDEN is a scope mismatch (an environment ID against a tenant-scoped credential, or the reverse) and says so, the grants being correct there.

A missing grant looks like this, with the name Jamf Account's picker shows:

hint: grant the Jamf Platform API integration these permissions in Jamf Account:
Secure enterprise access > Content categories: Read (content-categories:read).
Names are as the permission picker shows them:
https://developer.jamf.com/platform-api/reference/jamf-pro-permissions-map
# What does this command need?
jamf-cli commands -o json \
  | jq '.[] | select(.command=="pro blueprints create") | {api, privileges}'

Scope from environment variables (CI)

A gateway profile is optional. A JAMF_URL on the *.api.jamfcloud.com gateway host selects platform auth on its own (there is no auth-method environment variable), and the scope level is whichever ID variable you set, or none:

# platform environment (preferred)
JAMF_URL=https://eu.api.jamfcloud.com \
JAMF_ENVIRONMENT_ID=<uuid> JAMF_CLIENT_ID=<id> JAMF_CLIENT_SECRET=<secret> \
  jamf-cli pro blueprints list

# tenant (legacy)
JAMF_URL=https://eu.api.jamfcloud.com \
JAMF_TENANT_ID=<uuid> JAMF_CLIENT_ID=<id> JAMF_CLIENT_SECRET=<secret> \
  jamf-cli pro categories list

# organization: no ID at all, the gateway resolves it from the access token
JAMF_URL=https://us.api.jamfcloud.com \
JAMF_CLIENT_ID=<id> JAMF_CLIENT_SECRET=<secret> \
  jamf-cli platform account-licenses list

Supplying both IDs is a usage error (exit 2), and the message names the flags even when the pair came from the environment:

--environment-id and --tenant-id are mutually exclusive: an API integration is created at
one level, and its credential only works with that level's header

config add-profile refuses the same pair at profile-creation time, naming the three levels:

--environment-id and --tenant-id are mutually exclusive: an API integration is created at
one level (organization, platform environment, or tenant) and its credential only works
with that level's header

The CLI cannot catch the wrong level before sending, a gateway token being opaque and carrying no scope, so the gateway's answer is the only signal. Reaching an environment-only surface with an organization or tenant credential answers 400 [INVALID_REQUEST_CONTEXT_TYPE] Request context type 'tenant' is invalid. Expected any of 'environment'. and exits 1. (The gateway calls an organization credential's context 'tenant'; confusing, and that is what it prints.)

Aliases

Command Alias
blueprints bp
compliance-benchmarks cb
platform-devices pdev
platform-device-groups pdg
ddm-reports ddm

Blueprints (bp)

Manage deployment blueprints: define configurations and deploy them to device groups.

# List all blueprints
jamf-cli pro blueprints list
jamf-cli pro blueprints list --sort name:asc --search "staging"

# Get a blueprint by UUID, or by name with --name
jamf-cli pro blueprints get 0f0e6b0c-1f2a-4c3d-9e8f-7a6b5c4d3e2f
jamf-cli pro blueprints get --name "macOS Standard"

# Create or update a blueprint
jamf-cli pro blueprints apply --from-file blueprint.json --yes

# Print a JSON scaffold template
jamf-cli pro blueprints apply --scaffold

# Export a blueprint (round-trippable to apply)
jamf-cli pro blueprints export --name "macOS Standard" -o yaml > blueprint.yaml

# Clone a blueprint (the one command that takes names positionally)
jamf-cli pro blueprints clone "macOS Standard" "macOS Standard - Test"

# Deploy / undeploy
jamf-cli pro blueprints deploy --name "macOS Standard"
jamf-cli pro blueprints undeploy --name "macOS Standard"

# Get deployment status report
jamf-cli pro blueprints report --name "macOS Standard"

# Delete a blueprint
jamf-cli pro blueprints delete --name "macOS Standard" --yes

Only a v1.31.1 YAML export round-trips. Earlier releases rendered each component's configuration as a sequence of integer bytes and lower-cased its keys, which apply cannot read back. -o json was correct throughout. apply refuses the older file rather than sending it:

component com.jamf.ddm.passcode-settings: configuration is not an object
A YAML export written by jamf-cli 1.31.0 or earlier rendered it as a byte sequence. Re-export the blueprint with this version and apply that file

Re-export any YAML blueprint you have kept. A stored JSON export is unaffected.

Blueprint Scope Management

blueprints scope is a Platform API command and shares nothing with the Classic scope subcommands on policies and configuration profiles: it scopes a blueprint to device groups only, and it was not changed by v1.30.0. The Classic ones moved to a positional <id> with --name as the alternative in that release. See Jamf Pro Commands.

# List device groups in a blueprint's scope (positional UUID, or --name)
jamf-cli pro blueprints scope list 0f0e6b0c-1f2a-4c3d-9e8f-7a6b5c4d3e2f
jamf-cli pro blueprints scope list --name "macOS Standard"

# Add device groups to scope (--computer-group / --mobile-device-group by name, or --group-id by UUID; all repeatable)
jamf-cli pro blueprints scope add --name "macOS Standard" --computer-group "All Macs"

# Remove device groups from scope
jamf-cli pro blueprints scope remove --name "macOS Standard" --computer-group "Test Devices"

Blueprint Components

Blueprint components are the DDM declarations that make up a blueprint step. Each component has a unique identifier (e.g. com.jamf.ddm.passcode-settings).

# List all available components
jamf-cli pro blueprints components list

# Get a component's current API definition by identifier
jamf-cli pro blueprints components get "com.jamf.ddm.passcode-settings"

# Print a ready-to-use JSON scaffold for a component (no auth required)
# Accepts full identifiers or short names
jamf-cli pro blueprints components scaffold passcode-settings
jamf-cli pro blueprints components scaffold com.jamf.ddm.software-update-settings

# Convert a .mobileconfig file to a configuration-profile component
jamf-cli pro blueprints components configuration-profile --from-file profile.mobileconfig

# Download an existing profile from Jamf Pro and convert it, by Classic ID or by name
jamf-cli pro blueprints components configuration-profile --id 42
jamf-cli pro blueprints components configuration-profile --name "My Restrictions"
jamf-cli pro blueprints components configuration-profile --name "Managed Restrictions" --type mobile

# Strip Apple default values before converting (reduces noise from UI-generated profiles)
jamf-cli pro blueprints components configuration-profile --from-file profile.mobileconfig --strip-defaults

# Convert a raw preference domain plist to a configuration-profile component
jamf-cli pro blueprints components configuration-profile-plist \
  --from-file com.apple.dock.plist --payload-type com.apple.dock

Import Classic Profile as Blueprint

import-profile downloads a Classic API configuration profile from Jamf Pro, converts compatible payloads to native DDM components, and creates a blueprint. Conversion is the default; --legacy skips it.

# Import a macOS config profile (DDM conversion happens without a flag)
jamf-cli pro blueprints import-profile "Passcode Policy"

# Import a mobile device config profile
jamf-cli pro blueprints import-profile "Managed Restrictions" --type mobile

# Override the blueprint name
jamf-cli pro blueprints import-profile "FileVault Settings" --blueprint-name "FV Blueprint"

# Strip Apple defaults from payloads (useful for profiles with many UI-set keys)
jamf-cli pro blueprints import-profile "My Restrictions" --strip-defaults

# Skip DDM conversion: wrap everything in a single configuration-profile component
jamf-cli pro blueprints import-profile "My Restrictions" --legacy

# Set (or override) the blueprint scope. Blueprints require at least one device group (repeatable)
jamf-cli pro blueprints import-profile "Software Update" --computer-group "All Managed Macs"
jamf-cli pro blueprints import-profile "Managed Restrictions" --type mobile --mobile-device-group "Student iPads"

# Send payloads that blueprints hard-disables anyway (the API will reject them)
jamf-cli pro blueprints import-profile "My Restrictions" --include-unsupported

# Identify the profile by its Classic API ID instead of its display name
jamf-cli pro blueprints import-profile 42
jamf-cli pro blueprints import-profile --name "Passcode Policy"

Identifying the profile. Jamf Pro allows duplicate profile display names, so import-profile also takes a Classic API ID. It reads the positional argument as an ID when every character is a digit and as a display name otherwise, so a profile whose display name is all digits (e.g. "2024") must be looked up with --name. A name matching more than one profile prompts you to pick; under --no-input the command errors and lists the matching IDs. components configuration-profile takes an --id flag for the same job.

Scope override and the empty-scope guard. --computer-group / --mobile-device-group (both repeatable) set the blueprint scope, overriding the profile's own. Blueprints require at least one device group, so a profile whose scope resolves to no groups (all computers, individual devices, buildings, or departments) fails with an error naming the problem, and one of these flags fixes it.

Disabled payload types are skipped. Blueprints hard-disables a fixed set (certificates, VPN, SSO, web clips, fonts, and others), and those are dropped with a warning. --include-unsupported sends them anyway, and the API rejects them.

Supported DDM conversions (applied whenever import-profile finds the payload):

Legacy Payload DDM Component
com.apple.mobiledevice.passwordpolicy com.jamf.ddm.passcode-settings
com.apple.applicationaccess (safari keys) com.jamf.ddm.safari-settings
com.apple.applicationaccess (deferral keys) com.jamf.ddm.software-update-settings
com.apple.applicationaccess (RSR keys) com.jamf.ddm.software-update-settings
com.apple.SoftwareUpdate com.jamf.ddm.software-update-settings

Payloads with no DDM mapping are wrapped in a com.jamf.ddm-configuration-profile component. Some of these "Legacy payload" components can only be managed through the blueprints API and appear read-only in the Jamf Pro UI. import-profile carries the scope over, target device groups only: individual computers, buildings, departments, limitations and exclusions cannot be imported to blueprints.

Payload type delivery

The com.jamf.ddm-configuration-profile component takes a fixed registry of payloadType values standalone, and the API reference overstates it. A type outside that registry earns a message naming the whole component, with no payload, key or reason:

{"httpStatus":400,"errors":[{"code":"VALIDATION_FAILURE",
  "field":"steps[0].components[2].configuration",
  "description":"Failed to validate configuration."}]}

Wire-probing every payload type Apple publishes, plus Jamf Pro's own spellings, found 74 accepted standalone, 22 disabled, and 40 unknown to the registry, well-documented ones included: com.apple.MCX, com.apple.Safari, com.apple.SoftwareUpdate, com.apple.Terminal, com.apple.TimeMachine, com.apple.systemuiserver, com.apple.mail.managed, .GlobalPreferences. Apple publishing a schema says nothing about what the registry knows.

import-profile and components configuration-profile model that:

  • An out-of-registry type is wrapped. import-profile delivers a payload whose type the registry does not know as com.apple.ManagedClient.preferences (Application & Custom Settings), which the API accepts for every domain probed, third-party ones like com.microsoft.Word included, and which is the correct legacy delivery for those domains. No settings are lost.
  • Jamf Pro's non-canonical spelling is rewritten. Jamf Pro writes its User Preferences payload as com.apple.preferences.users (Apple's filename), and the registry knows com.apple.preference.users. One character fails a whole profile.
  • MCX unwrapping is offline and narrow. import-profile unwraps an Application & Custom Settings payload to a standalone payload when a DDM converter will consume its inner domain, or the registry accepts that domain. Classification needs no network call. --legacy keeps MCX intact.

Note: A type missing from the registry is benign: import-profile MCX-wraps it and delivers it. Guessing one in is not, so the CLI's list stays conservative.

Compliance Benchmarks (cb)

Manage mSCP (macOS Security Compliance Project) compliance benchmarks. compliance-benchmarks handles benchmark CRUD (create/apply, get, list, clone, delete, export). Baseline and rule reference data live under baselines/rules; compliance monitoring lives under benchmark-reports.

# List available mSCP baselines (the starting point for new benchmarks)
jamf-cli pro baselines list

# List all benchmarks
jamf-cli pro compliance-benchmarks list

# Get a benchmark by ID, or by title with --name
jamf-cli pro compliance-benchmarks get <benchmark-id>
jamf-cli pro compliance-benchmarks get --name "CIS macOS 15"

# Create a benchmark from a portable JSON/YAML file (group names, not IDs)
jamf-cli pro compliance-benchmarks apply --from-file benchmark.json
jamf-cli pro compliance-benchmarks apply --from-file benchmark.yaml

# Print a JSON scaffold template for the input format
jamf-cli pro compliance-benchmarks apply --scaffold

# Generate a scaffold pre-populated with all rules from a specific baseline
# (pass the baseline ID from 'baselines' list)
jamf-cli pro compliance-benchmarks apply --scaffold-from-baseline "<baseline-id>"

# Export a benchmark as portable JSON/YAML (group IDs replaced with names).
# export and clone take titles positionally
jamf-cli pro compliance-benchmarks export "CIS macOS 15"
jamf-cli pro compliance-benchmarks export "CIS macOS 15" -o yaml > benchmark.yaml

# Clone a benchmark with a new title
jamf-cli pro compliance-benchmarks clone "CIS macOS 15" "CIS macOS 15 - Staging"

# Clone and override target device groups
jamf-cli pro compliance-benchmarks clone "CIS macOS 15" "CIS macOS 15 - Test" \
  --computer-group "Test Devices"

# Delete a benchmark (positional ID, or --name for the title)
jamf-cli pro compliance-benchmarks delete --name "CIS macOS 15" --yes

Note: Benchmarks cannot be updated after creation, so apply is create-only. To modify one, export it, delete the old one, edit the exported file, and re-apply. Use clone to copy an existing benchmark under a new title. export produces a portable format with names in place of device group IDs, so its output is safe to apply to a different instance.

Targeting OS versions

A benchmark definition can pin the OS versions it applies to with a selectedOsVersions list. Each entry has an osType and osVersion. It appears in apply --scaffold output, and export/clone preserve it:

{
  "title": "My Benchmark",
  "sourceBaselineId": "<baseline-id>",
  "rules": [ { "enabled": true, "id": "<rule-id>" } ],
  "selectedOsVersions": [
    { "osType": "MAC_OS", "osVersion": 26 }
  ],
  "target": {
    "deviceGroups": [
      { "name": "<device-group-name>", "deviceType": "COMPUTER", "groupType": "SMART" }
    ]
  },
  "enforcementMode": "MONITOR"
}

Compliance Baselines & Rules (baselines, rules)

The mSCP baselines and their rules are read-only reference data, exposed as their own resources and not as subcommands of compliance-benchmarks. Use a baseline ID when scaffolding a benchmark with compliance-benchmarks apply --scaffold-from-baseline.

# List available mSCP baselines
jamf-cli pro baselines list

# List all mSCP rules
jamf-cli pro rules list

# List the rules provided by a specific baseline
jamf-cli pro rules list --baseline-id <baseline-id>

Baseline IDs are slugs (cis_lvl1), so --baseline-id 1 is a 404.

Benchmark Reports (benchmark-reports)

Compliance reporting for existing benchmarks. Each subcommand takes a benchmark ID (from compliance-benchmarks list) positionally, or a benchmark title via --name, resolved against compliance-benchmarks.

# Per-rule compliance stats for a benchmark (passed / failed / unknown counts)
jamf-cli pro benchmark-reports rules <benchmark-id>
jamf-cli pro benchmark-reports rules --name "CIS macOS 15"
jamf-cli pro benchmark-reports rules <benchmark-id> --rule-search "firewall" --sort passed:desc

# Devices for a benchmark, optionally filtered to a single rule
jamf-cli pro benchmark-reports devices <benchmark-id>
jamf-cli pro benchmark-reports devices --name "CIS macOS 15" --rule-id <rule-id> --sort deviceName:asc

# Overall compliance percentage for a benchmark
jamf-cli pro benchmark-reports compliance-percentage <benchmark-id>
jamf-cli pro benchmark-reports compliance-percentage --name "CIS macOS 15"

Platform Devices (pdev)

Unified device inventory and management through the Platform API. Identify a device by UUID or serial number; the CLI works out which you passed (UUIDs contain hyphens, serials do not).

# List all devices
jamf-cli pro platform-devices list
jamf-cli pro platform-devices list --sort name:asc --filter "osType==MACOS"

# Get a device by serial number or UUID
jamf-cli pro platform-devices get C02X1234
jamf-cli pro platform-devices get "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

# Update device attributes
jamf-cli pro platform-devices update C02X1234 --from-file device-update.json

# Delete a device (destructive)
jamf-cli pro platform-devices delete C02X1234 --yes

# List installed applications
jamf-cli pro platform-devices applications C02X1234

# List group memberships
jamf-cli pro platform-devices groups C02X1234

# List devices for a user
jamf-cli pro platform-devices user user-id-here

# Request a device check-in (non-destructive)
jamf-cli pro platform-devices check-in C02X1234

# Device actions (destructive, require --yes)
jamf-cli pro platform-devices erase C02X1234 --yes
jamf-cli pro platform-devices restart C02X1234 --yes
jamf-cli pro platform-devices shutdown C02X1234 --yes
jamf-cli pro platform-devices unmanage C02X1234 --yes

Platform Device Groups (pdg)

Manage device groups through the Platform API. Static groups support member management; filter criteria define smart groups.

# List all device groups
jamf-cli pro platform-device-groups list
jamf-cli pro platform-device-groups list --sort name:asc

# Get a device group by ID, or by name with --name
jamf-cli pro platform-device-groups get <group-id>
jamf-cli pro platform-device-groups get --name "All macOS Devices"

# Create or update a device group
jamf-cli pro platform-device-groups apply --from-file group.json --yes

# Print a JSON scaffold template
jamf-cli pro platform-device-groups apply --scaffold

# Export a group as YAML (round-trippable to apply)
jamf-cli pro platform-device-groups get --name "All macOS Devices" -o yaml

# Delete a device group
jamf-cli pro platform-device-groups delete --name "Test Group" --yes

# List group members (positional <id>, or --name)
jamf-cli pro platform-device-groups members --name "All macOS Devices"

# Add/remove members from a static group. These two take the group NAME
# positionally; --id is the repeatable device ID
jamf-cli pro platform-device-groups add-members "Manual Group" --id <device-id-1> --id <device-id-2>
jamf-cli pro platform-device-groups remove-members "Manual Group" --id <device-id-1>

# Disambiguate by device type when a computer group and a mobile device group share a name
jamf-cli pro platform-device-groups get --name "Engineering" --device-type COMPUTER
jamf-cli pro platform-device-groups get --name "Engineering" --device-type MOBILE

--device-type: a computer group and a mobile device group can carry the same name, which makes a bare name lookup ambiguous. Pass --device-type COMPUTER or --device-type MOBILE to narrow it. The flag is on the subcommands that resolve a group by name: get, delete, members, add-members, remove-members, patch, and patch-members.

Identifier shapes differ within this group: get, delete, members, patch, and patch-members take a positional <id> with --name for lookup; add-members and remove-members take the group <name> positionally.

DDM Reports (ddm)

Declarative Device Management reporting: check declaration deployment status across your fleet.

# The declaration report for one device (by device ID). --filter is required
jamf-cli pro ddm-reports device declarations <device-id> --filter 'active==true'

# Devices reporting a specific declaration. --filter is required
jamf-cli pro ddm-reports declaration devices "com.apple.configuration.passcode" --filter 'active==true' --sort declarationType,asc

# Everything, with the tautology that stands in for an unfiltered read
jamf-cli pro ddm-reports declaration devices "com.apple.configuration.passcode" \
  --filter 'active=in=(true,false)'

# Page through a large report (--page is 0-based; --size sets the page size)
jamf-cli pro ddm-reports device declarations <device-id> \
  --filter 'active=in=(true,false)' --page 1 --size 200

# Devices with failed/invalid declarations, and their error reasons
jamf-cli pro ddm-reports errors "com.apple.configuration.passcode"

Removed: ddm-reports declaration get and ddm-reports device get. The declaration-reporting API deprecated both endpoints in favour of a sibling on the same resource. Rewrite:

Was Now
pro ddm-reports declaration get <id> pro ddm-reports declaration devices <id> --filter …
pro ddm-reports device get <id> pro ddm-reports device declarations <id> --filter …

The successors declare filter required where the removed pair did not, so use --filter 'active=in=(true,false)' where you want everything. Both successors also take --page. The same two removals apply to school ddm-reports. The old names are gone from cobra: pro ddm-reports declaration get X exits 2 as a usage error, so a script still calling one fails with a usage error.

Paging and sorting differ from the platform lists. --page is zero-based and --size sets the page size (not --page-size), and --sort takes the comma form property,asc / property,desc, while every other Platform list uses property:asc.

--filter is required on device declarations and declaration devices: the API has no "return everything" mode for these reports, so cobra refuses the call before anything is sent, with required flag(s) "filter" not set and exit code 2. Filters use RSQL and apply to declarations already on the device (the report excludes PENDING declarations). Allowed fields:

  • device declarations: declarationIdentifier, active, validityState, declarationType, dateUpdated, channel
  • declaration devices: deviceId, channel, lastReportTime, active, validityState, declarationType, dateUpdated

For example, --filter 'validityState=="INVALID"' returns the failing declarations. The errors subcommand takes no --filter, since it already scopes to failed and invalid declarations.

Platform Reports

Report commands that aggregate Platform API data. These nest under pro report alongside the existing Pro reports.

# Blueprint deployment status across all blueprints
jamf-cli pro report blueprint-status

# Per-rule compliance stats for a benchmark
jamf-cli pro report compliance-rules "CIS macOS 15"

# Non-compliant devices for a benchmark
jamf-cli pro report compliance-devices "CIS macOS 15"

# DDM declaration health across all devices
jamf-cli pro report ddm-status

Auth Token

Print a valid Jamf Platform Gateway access token. The CLI refreshes the token when it has expired.

# Print token as JSON (includes expiry)
jamf-cli platform auth token

# Extract the token string for scripting
jamf-cli platform auth token --field token

# Force a fresh token exchange (ignores cache)
jamf-cli platform auth token --refresh

Output:

{
  "token": "eyJhbGciOi...",
  "expires_at": "2026-04-15T15:30:00Z"
}
Flag Description
--refresh Force a new token exchange, ignoring any cached token

Platform Audit Checks

With platform gateway auth active, pro audit includes platform-specific checks:

# Run all audit checks (platform included when configured)
jamf-cli pro audit

# Run only platform checks
jamf-cli pro audit --checks platform

Platform checks cover: undeployed blueprints, deployment failures, stale blueprints, benchmark updates needed, monitor-only benchmarks, empty platform scope, and failed DDM declarations.

jamf-cli Wiki


Products

  • Jamf Pro: jamf-cli pro
  • Jamf Platform API: jamf-cli pro (blueprints, benchmarks, DDM reports)
  • Jamf Platform: jamf-cli platform (AI Governance, Jamf Account, audit)
  • Jamf Protect: jamf-cli protect
  • Jamf School: jamf-cli school
  • Jamf Security Cloud: jamf-cli security

Clone this wiki locally