Skip to content

Platform API GA Migration

Neil Martin edited this page Sep 16, 2026 · 7 revisions

Platform API GA Migration

The Jamf Platform API reached general availability on 2026-09-03 and the public beta is over. This page covers the changes a beta platform profile needs.

Three changes per profile: the base URL, the credentials, and the scope key. Setting a platform profile up for the first time needs only jamf-cli platform setup and Scope; Setup Guide walks through the wizard.

The counts on this page describe the documented build. jamf-cli commands -o json reports the current answer for the binary you have.

pro command names moved in v1.29.0 for a reason unrelated to GA. Jamf Pro resource names now come from the API's own OpenAPI tags and URL paths instead of spec filenames, which retired 100 former names; this page uses the new ones. Every old spelling resolves and prints a deprecation warning until 2027-03-09. A pro command this page does not name is a rename, not a gateway refusal: Pro Command Renames has the mapping.

Console-side instructions (registering an integration, the permission picker) are at Getting started with the Platform API. The Terraform provider's Preparing for the Platform API GA guide covers the Jamf Account side in more depth, including the permission model and the scope levels.

Migration checklist

# 1. Find every profile still pointed at the retired gateway host.
jamf-cli config list -o json | jq -r '.[] | select(.url | test("apigw\\.jamf\\.com")) | .name'

# ...and see the whole picture: NAME | AUTH-METHOD | DEFAULT | ENVIRONMENT-ID | URL
jamf-cli config list
jamf-cli config path        # where the file lives, if you prefer to edit it directly

# 2. Register a replacement API integration in Jamf Account (account.jamf.com).
#    Beta credentials were revoked at GA and a beta client cannot be migrated.
#    Record what the old integration could reach BEFORE replacing it, so you can
#    pick the equivalent permissions.

# 3. Re-run setup. It does all three changes interactively and writes a fresh
#    profile: GA host, new credentials, and the scope level.
jamf-cli platform setup --profile-name platform-prod

# 4. Confirm.
jamf-cli config validate --connectivity
jamf-cli -p platform-prod pro categories list
jamf-cli -p platform-prod pro blueprints list

# 5. Check whether anything you script is now refused on a gateway profile.
jamf-cli commands -o json | jq -r '.[] | select(.gateway=="unserved") | .command'

Editing the profile by hand instead of re-running setup means three keys:

Change From To
url https://{region}.apigw.jamf.com https://{region}.api.jamfcloud.com
client-id / client-secret beta integration a GA integration registered in Jamf Account
scope key tenant-id environment-id, unless you want single-product access

There is no state to migrate and no config-file schema change beyond those keys.

Two notes on reading config list while you audit. The table, CSV and plain output carry an environment-id column and no tenant-id one, so a tenant-scoped profile shows its scope only under -o json, where tenant-id is still reported. The JSON fields are omitted when empty, so environment-id appears for a profile that has one: its absence from a row describes that profile alone.

Base URL

The GA gateway is https://{region}.api.jamfcloud.com, with us, eu or apac for the region. Supply the host only. Every namespace is served at the root and the beta's /api path segment is gone: a request carrying it gets the gateway's plain-text 404 page not found in place of a JSON error.

profiles:
  platform-prod:
    url: https://eu.api.jamfcloud.com   # was https://eu.apigw.jamf.com
    auth-method: platform
    client-id: keychain:jamf-cli/platform-prod-client-id
    client-secret: keychain:jamf-cli/platform-prod-client-secret

The CLI refuses the old host by name, from the profile's stored URL, before any token exchange:

$ jamf-cli -p platform-eu-old pro categories list
{
  "error": "usage",
  "exitCode": 2,
  "exitCodeName": "usage",
  "message": "https://eu.apigw.jamf.com is the retired Jamf Platform gateway and does not serve the GA API paths.\nSet url: https://eu.api.jamfcloud.com in this profile (jamf-cli config path prints the file), or re-run `jamf-cli platform setup`."
}

Exit code 2 (usage): a retired host is a configuration mistake in the profile you invoked, the same class as a bad flag or a missing URL. Exit 8 covers a policy refusal, where the invocation and the profile are both fine and the published API does not carry the endpoint.

The CLI leaves the URL alone instead of rewriting it, so fix the profile. jamf-cli config validate reports the retired host as well, which finds a stale profile without running a command against it.

apigw.jamf.com is retired, so this change and the credential swap have to land together.

Scope

An API integration is created at one of three levels in Jamf Account, and its credential works with that level alone:

Level Profile key What it reaches
Organization neither key Jamf Account (platform account-licenses, platform sso-connections, platform sso-domains, the distributor-* commands) and AI Governance
Platform environment environment-id a group of tenants across product types. Prefer this; also the only level platform audit accepts
Tenant tenant-id one Jamf Pro / School / Protect / Security Cloud tenant (the legacy level)

Public-beta integrations were tenant-scoped, so most existing profiles carry tenant-id. Register the GA replacement at environment level unless you want single-product access:

    # tenant-id: 0f9c…          # remove
    environment-id: 4b21…

Both are settable per invocation (--environment-id, --tenant-id) and by environment variable (JAMF_ENVIRONMENT_ID, JAMF_TENANT_ID), which is the CI/CD route (see CI/CD & Scripting). A level supplied on the command line or in the environment replaces the profile's, so JAMF_ENVIRONMENT_ID=… jamf-cli -p tenant-profile … means "use this environment".

jamf-cli platform setup asks for the environment ID first and stops there once it has one. The two levels cannot be combined.

Three things to know:

  • Supplying both levels at once is refused, in the environment as well as on the command line, before any request is sent. Exit code 2:

    --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
    

    The message names the flags whichever way the conflict arrived, so a CI job that set JAMF_ENVIRONMENT_ID and JAMF_TENANT_ID together sees flag names it did not pass. Unset one of the variables.

  • Sending the wrong level for the credential is a 403 OWNERSHIP_FORBIDDEN, even when both identifiers belong to you. Sending neither, on a credential that expects one, is 400 REQUEST_CONTEXT_NOT_PROVIDED, and the CLI adds a note naming the level that endpoint wants.

  • Organization scope has no ID, so the gateway host itself selects platform auth for it. JAMF_URL=https://us.api.jamfcloud.com plus a client ID and secret, with no scope ID, is a valid organization-scoped setup.

A customer with several tenants and no platform environment keeps a profile per tenant.

The scope travels in a header

At the beta, the scope was a path segment: /api/{namespace}/{version}/tenant/{tenantId}/{resource}. At GA it is a request header, X-Environment-Id or X-Tenant-Id, and nothing at all for organization scope. The CLI handles this. There is no flag or profile key for it, and nothing to change in a profile beyond the scope key.

Two consequences. Anything of your own that builds gateway URLs by hand needs the same change. And an organization-scoped credential sends no scope header, which the gateway reports as an absent context on any endpoint that requires one.

The two scope mistakes give different answers, separated by whether a header went out at all. A tenant-scoped credential against platform audit, which accepts environment scope only, sends X-Tenant-Id and gets

[INVALID_REQUEST_CONTEXT_TYPE] Request context type 'tenant' is invalid. Expected any of 'environment'.

An organization-scoped credential sends no header, and the gateway reports the context as absent:

[REQUEST_CONTEXT_NOT_PROVIDED] The request context could not be detected.

note: this command's API declares environment scope, and this invocation is organization-scoped.
This invocation sent no scope header, which is what organization scope looks like on the wire. Set
an environment ID on the profile (or JAMF_ENVIRONMENT_ID), or use an integration created at that
level.

Both exit 1: the gateway answered a request the CLI sent. The CLI derives the note on the second from the scope levels that endpoint's spec declares. The gateway's own message on the first names both the level sent and the level accepted.

Credentials and permissions

Credentials are registered in Jamf Account's Platform API integrations UI. One OAuth 2.0 model covers the platform, replacing one credential set per product.

jamf-cli platform setup

It prompts for region, client ID and secret, and the scope, validates the credentials against the gateway, probes the scope ID, and stores the secrets in the system keychain (see Secrets & Keychain). It closes by naming which Platform API resources that scope level reaches. Setup checks no capability permissions: you grant those per command when you create the integration.

jamf-cli security setup still owns the three Jamf Security Cloud Radar credential pairs (Risk, Device Lifecycle, SSE), which are unrelated to the gateway and unaffected by GA. Both setup commands merge into a profile, so one profile can carry both credential sets and running them in either order is safe.

Permissions are organised by capability and action (device-groups:read, compliance-benchmarks:create) instead of by Jamf Pro privilege name. The two vocabularies are independent: the GA consolidation folded several Jamf Pro privileges into one capability, the computer and mobile pairs collapsed into single device-level permissions, and Jamf Account no longer offers the old names. The Jamf Pro permissions map is the reference for the full mapping.

Two consequences before you grant anything. An action covers itself alone, so a command that reads a record before writing it needs both. And erase, unmanage and pro platform-devices delete sit under destructive-device-actions:execute, split out of device-actions:execute, so those three can 403 on a credential that executes every other device action.

Reading a 403

A 403 names the permission in the vocabulary of the API that answered. On a gateway profile:

$ jamf-cli -p platform-prod security content-categories list
list: API request failed with status 403 Forbidden, traceId 88ae8ec070c9cf808506b8e04db866e6
(method=GET, url=https://eu.api.jamfcloud.com/securitycloud/v1/categories): [BAD_PERMISSIONS]
The given token was not authorized to access the requested resource.
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
$ echo $?
5

The section and permission name are what Jamf Account's picker prints. You search that picker by name, and the names differ from the slugs (computer-inventory-collection-settings is "Device inventory collection settings"). The slug is printed beside each one because the gateway's own errors and the command catalog use it.

The same command on a Jamf Pro instance profile reports Jamf Pro privilege names (Required privilege(s): Read Categories, Read Self Service), which is what you grant there.

A platform 403 has a second cause. On a gateway OWNERSHIP_FORBIDDEN, the hint says the credential's scope level does not match the header sent, the grants are already correct, and the fix is one line of the profile.

A platform command's permission failure exits 5 (permission_denied). Scripts keying on exit codes should expect 5 there. See Error Handling & Exit Codes.

Sizing an integration without provoking 403s

jamf-cli commands -o json carries the requirement per command, in both forms:

Field What it holds
privileges Jamf Pro API-role privilege names (Read Categories) for a Pro or Classic command; for a Platform command this is already the capability list
gatewayPrivileges the capability permissions the gateway requires for that Pro or Classic endpoint (categories:read)
gatewayPermissions the same requirement in Jamf Account's own words, as Organizational context > Categories: Read (categories:read)
api which API serves it: pro, pro-classic, platform-gateway or radar

Work from gatewayPermissions when creating the integration. The Platform API integrations UI is the only place an integration can be created, its picker lists named permissions with a checkbox per action, and the capability slug appears nowhere in it.

The permissions for a set of commands are a query:

jamf-cli commands -o json | jq -r '
  .[] | select(.command | test("^pro blueprints ")) | .gatewayPermissions[]?
' | sort -u
Deployment > Blueprints: Delete (blueprints:delete)
Deployment > Blueprints: Deploy (blueprints:deploy)
Deployment > Blueprints: Read (blueprints:read)
Deployment > Blueprints: Update (blueprints:update)

Each row is per command, so widening the filter can list one permission twice with different actions ticked: Categories: Create from create, Categories: Create, Read, Update from apply. Tick the union.

Three limits on those fields:

  • An absent list means the requirement is unrecorded. A command outside the published API declares no capability, as do the unauthenticated Jamf Pro endpoints (pro health-check, pro jamf-pro-version) and the hand-written commands, which assemble their own paths. Watch pro platform-devices delete: the catalog lists nothing for it, and the endpoint it calls requires destructive-device-actions:execute.
  • A --name, --serial or --udid lookup resolves the identifier through the resource's collection first, so those invocations also need its read permission. The catalog lists the permissions a command uses on every invocation, which keeps delete <id> from asking you to grant a read it never makes. apply reads on every invocation, and its row says so.
  • One permission, one row. Categories: Create, Read, Update is one row of the picker with three boxes ticked.

Commands refused on a gateway profile

Some Jamf Pro and Classic endpoints sit outside the gateway's published API. On a gateway profile the CLI refuses those commands before sending a request, with exit code 8.

Regenerate the list for the binary you have. The verdict is baked in, so this needs no profile and no credential:

jamf-cli commands -o json | jq -r '.[] | select(.gateway=="unserved") | .command'

# With the reason each one carries:
jamf-cli commands -o json | jq -r '.[] | select(.gateway=="unserved") | .command + "\t" + .gatewayBasis'

A refused row carries three fields: gateway (unserved), gatewayBasis (unpublished, meaning the endpoint is absent from the published API and may still answer, or probe, a recorded wire probe that found no route) and gatewayDetail, the sentence the refusal prints. All 59 refused commands in this build carry unpublished, so JAMF_CLI_ALLOW_UNPUBLISHED applies to each of them.

59 entries in this build (one of them a bare group node for a resource refused in full, so 58 runnable commands):

Refused Subcommands Count
pro mobile-devices apply-redemption-code, clear-passcode, clear-restrictions-password, delete-user, disable-lost-mode, enable-lost-mode, lock, log-out-user, play-lost-mode-sound, refresh-cellular-plans, request-mirroring, restart, settings, shutdown, stop-mirroring, unlock-user-account 16
pro computer-inventory disable-remote-desktop, enable-remote-desktop, lock, restart, set-auto-admin-password, set-recovery-lock, settings, shutdown 8
pro api-integrations apply, client-credentials, create, delete, get, list, update 7
pro classic-computer-configs the group itself, plus apply, create, delete, get, list, update 7
pro api-authentication current, invalidate-token, keep-alive, list, oauth-token, token 6
pro api-roles apply, create, delete, get, list, update 6
pro jamf-pro-initialization initialize, initialize-database-connection, platform-initialize 3
pro api-role-privileges list, search 2
pro environment-type get 1
pro macos-managed-software-updates list 1
pro mdm commands 1
pro sso-oauth-session-tokens list 1

The other ~1,700 commands are unaffected. Pro and Classic still route through the gateway.

The gateway's two published specs now sit at the same version: Jamf Pro API 11.32.0 (478 paths, 704 operations) and Classic API 11.32.0 (270 paths, 589 operations). That settles pro classic-computer-configs: it is the one Classic resource the published spec omits, and it is omitted at the current version, not a stale one, so the resource is dead rather than awaiting publication. Your Jamf Pro instance 404s /computerconfigurations too. Earlier builds published Classic 11.28.0 against Pro 11.31.0 and said so in the refusal, which left the absence ambiguous.

The remedy for each is a second profile. These endpoints exist on your Jamf Pro instance, so keep an oauth2 profile alongside the platform one and select it with -p for the affected commands (see Configuration & Profiles). No refused command in this build has a successor that ships in the same binary, so the instance profile is the whole of the answer.

MDM device actions are refused

The gateway carries the mobile-device and computer resources without the write method those actions need, and gatewayDetail says so:

The gateway's Jamf Pro API 11.32.0 declares GET on this path but not POST.

So 24 device actions are refused on a gateway profile:

Product Lost on a gateway profile
Mobile devices lock, restart, shutdown, enable/disable lost mode, play lost mode sound, clear passcode, clear restrictions password, unlock user account, log out user, delete user, apply redemption code, refresh cellular plans, request/stop mirroring, send settings
Computers lock, restart, shutdown, enable/disable remote desktop, set recovery lock, set auto admin password, send settings

Move a workflow to a gateway profile and you lose all of them, with no sign of it until you run the command. Keep an oauth2 profile against the instance for anything that locks, wipes, restarts or unlocks a device.

Two exceptions:

  • pro computer-inventory erase and pro computer-inventory remove-mdm work on a gateway profile. They send a different, published path. Their targeting, confirmation, -n, --dry-run support and Find My PIN body are unchanged.
  • pro mdm commands, the generated command that posts to that path, is refused for the same reason and has its own row in the table.

A withdrawal can take part of a command group

Most rows above cover part of a resource. pro macos-managed-software-updates is the smallest case: list is refused and send-updates is served, so the resource's own --help carries no caveat and only the refused subcommand's does. Check --help on the individual subcommand. A refused one says so in its first paragraph, and a resource refused in full says so on the group (pro classic-computer-configs, the one group node on the list).

The refusal message

An endpoint on the list may still answer today. The route is transitional, and the refusal names an instance profile as the way forward:

$ jamf-cli -p platform-prod pro api-roles list
jamf-cli pro api-roles list is not part of the Jamf Platform gateway's published API

Not declared by the gateway's Jamf Pro API 11.32.0.

The gateway still routes some endpoints its published API omits, so this one may answer
today — that is transitional, and a workflow built on it will break without notice. It is
refused here rather than later, when the gateway's 403 BAD_PERMISSIONS would be
indistinguishable from a missing API-role privilege.

Run it against a Jamf Pro instance directly — a profile whose url is your instance and whose
auth-method is oauth2 or token.

Published surface: Jamf Pro API 11.32.0, Classic API 11.32.0.
hint: auth-method platform against the gateway, from profile "platform-prod"
$ echo $?
8

--help carries the same caveat:

$ jamf-cli pro api-roles list --help
Get roles with Search Criteria

Through the Jamf Platform gateway: outside the published API and refused. Not declared by
the gateway's Jamf Pro API 11.32.0. The gateway may still route it today, but that is
transitional. Requires a profile pointed at a Jamf Pro instance (auth-method oauth2 or
token).

Exit code 8. Exit 2 covers a bad flag, an unknown subcommand, a missing URL, a missing credential, the retired gateway host and a scope conflict, so a wrapper that skips refused commands and fails on everything else keys on 8:

jamf-cli -p platform-prod pro api-roles list
case $? in
  0) ;;
  8) echo "refused on this credential: skipping" >&2 ;;
  *) exit 1 ;;
esac

App Installers is no longer on the list. All 23 commands under pro app-installers, pro app-installers-titles and pro app-installers-deployments work on a gateway profile like any other Pro command.

The reverse direction

A Platform-only command (pro blueprints, platform ai-policies, security ztna-apps, and so on) on an instance profile is refused the same way, also with exit 8. The message names the profile, its resolved auth method, and jamf-cli platform setup:

jamf-cli pro blueprints list is served by the Jamf Platform API, which the active
credentials do not reach

The resolved credentials authenticate against a Jamf Pro instance (auth-method oauth2, from
profile "prod"). Platform API commands need a platform gateway credential: a client ID and
secret from a Jamf Platform API integration, against https://{region}.api.jamfcloud.com.

Set one up with `jamf-cli platform setup`, then re-run with -p <that profile>.

Both directions key on the resolved credentials instead of on a profile, so a CI job using JAMF_* environment variables gets the same refusal, and the hint names the variables:

hint: auth-method platform against the gateway, from the JAMF_CLIENT_ID / JAMF_CLIENT_SECRET
environment variables

The stopgap: JAMF_CLI_ALLOW_UNPUBLISHED

Setting JAMF_CLI_ALLOW_UNPUBLISHED=1 downgrades an unpublished refusal to a warning and sends the request:

$ JAMF_CLI_ALLOW_UNPUBLISHED=1 jamf-cli -p platform-prod pro api-roles list
warning: jamf-cli pro api-roles list is not part of the Jamf Platform gateway's published
API, and JAMF_CLI_ALLOW_UNPUBLISHED is set — sending it anyway.
Not declared by the gateway's Jamf Pro API 11.32.0.
The gateway routes it today; that is transitional and it will stop answering without notice,
at which point the failure arrives as a bare 403 BAD_PERMISSIONS. This is a stopgap, not a
supported mode — move the workflow onto a Jamf Pro instance profile.

403 BAD_PERMISSIONS is byte-identical for a path the gateway does not route and one your credential holds no grant for, so neither the variable nor the failure tells you which of the two you hit.

Terms:

  • It is a stopgap. Once a route is withdrawn, the command fails with a bare 403 BAD_PERMISSIONS and the variable makes no difference.
  • The warning reaches stderr on every affected invocation. Neither --quiet nor --no-hints suppresses it.
  • It covers unpublished refusals, which is all 59 in this build. A refusal carrying gatewayBasis: probe stands, since letting it through buys a 403.
  • It is value-parsed, like JAMF_CLI_NO_HINTS, so JAMF_CLI_ALLOW_UNPUBLISHED=0 leaves the refusal in place and a runner that exports it can turn it off without unsetting it.
  • It changes nothing about the endpoint. Use a second oauth2 profile for anything scheduled, and the variable for a one-off job you are already migrating.

New at GA

Additive, and live now.

  • A new platform top-level namespace, for surfaces that are not Jamf Pro surfaces: Jamf AI Governance (platform ai-policies, platform ai-tools), Jamf Account (platform account-licenses, platform deal-registrations, platform distributor-configuration, platform distributor-purchase-orders, platform distributor-quotes, platform sso-connections, platform sso-domains) and the platform audit event log (platform audit). Jamf Account is organization-scoped and US-only, which is a property of the API and not a rollout gap; the CLI refuses a non-US profile before sending. platform audit accepts environment scope only. See Jamf Platform Commands.
  • App Installers on the gateway: 23 commands under pro app-installers-titles, pro app-installers-deployments, pro app-installers global-settings and pro app-installers get (whether the feature is available, and which features the Cloud Services Connection enables).
  • Jamf Security Cloud through the gateway: security dns-zones, dns-search-domains, dns-custom-hostname-mappings, the ztna-* family, content-categories, device-groups, the uem-* family and enrollment-activation-profiles. These take gateway credentials, not the Radar application pairs. Every security command names the API that serves it in its short description, as (Security Cloud · platform gateway) or (Security Cloud · Radar API), so security <TAB> shows it. See Jamf Security Cloud Commands.
  • Platform API commands under pro keep their names: pro blueprints, pro compliance-benchmarks, pro platform-devices, pro platform-device-groups, pro ddm-reports. See Platform API Commands.
  • -n, --dry-run is honoured on platform and Security Cloud writes, printing the method, resolved path and body to stderr.
  • -v labels retried requests with the attempt number and the wait, which separates a slow call from a retry sequence.

Troubleshooting

Symptom Cause and resolution
… is the retired Jamf Platform gateway (exit 2) Set url: to https://{region}.api.jamfcloud.com, or re-run jamf-cli platform setup.
404 page not found, no JSON body A path reached the gateway that it does not route, often from a url carrying a path segment. Supply the host only.
403 OWNERSHIP_FORBIDDEN environment-id supplied for a tenant-scoped integration, or the reverse. The hint names the scope mismatch.
400 REQUEST_CONTEXT_NOT_PROVIDED No scope sent, on an endpoint that expects one (an organization-scoped credential). Add environment-id or tenant-id. Exit 1.
400 INVALID_REQUEST_CONTEXT_TYPE The level sent is not the level that endpoint accepts; the message names both. platform audit accepts environment only, so a tenant-scoped credential earns this. An organization-scoped one sends no header and gets REQUEST_CONTEXT_NOT_PROVIDED instead. Exit 1.
permission denied (HTTP 403) with a permission hint The integration lacks that permission. Grant it in Jamf Account by the section and name the hint prints. Exit 5.
403 BAD_PERMISSIONS with no permission named The endpoint has no recorded capability, or the namespace is not entitled for this tenant. Check the integration's permissions and the tenant's entitlements.
request blocked at the Jamf gateway edge (HTTP 403) CloudFront's WAF refused the request ahead of the gateway, so the trigger is in the request itself. Known ones: file:// anywhere in the request body (legitimate in some Classic payloads), .pkg upload content, and a burst of writes. Retry a single request cold; a .pkg upload needs an instance profile. Exit 5.
… is not part of the Jamf Platform gateway's published API (exit 8) Expected. Use the successor the message names, if it names one, or run it against a Jamf Pro instance profile (see Commands refused on a gateway profile). JAMF_CLI_ALLOW_UNPUBLISHED=1 is the stopgap.
… is served by the Jamf Platform API, which the active credentials do not reach (exit 8) A platform command on an instance profile. Use -p <platform profile>.
--environment-id and --tenant-id are mutually exclusive (exit 2) Both levels supplied. Pass only the one this credential was created for. The message names the flags even when the pair came from JAMF_ENVIRONMENT_ID / JAMF_TENANT_ID.
Authentication fails outright with credentials that used to work Beta credentials, revoked at GA. Register a replacement integration in Jamf Account and re-run jamf-cli platform setup.

See also

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