Platform API fundamentals

Authentication, scope levels, regions, permissions, pagination, and errors. These apply to every API behind the Platform API Gateway.

Overview

One integration, one token, one permission model, and one set of request conventions cover every API behind the Platform API Gateway.

This page covers the shared mechanics. Individual API pages cover what is specific to them, such as resource paths and required permissions.

TopicWhat it covers
AuthenticationGetting and using an access token
Scope levelsOrganization, platform environment, and tenant
Regions and data residencyWhich host to call, and where your data lives
Request contextThe headers that identify your tenant or environment
Capability permissionsHow permissions are named and granted
Pagination, sorting, and filteringWorking through collections
ErrorsStatus codes and what they mean
VersioningHow API versions appear in paths

To create an integration and make a first call, see Getting started.


Authentication

The gateway uses OAuth 2.0 client credentials across its entire surface. You create an integration in Jamf Account, exchange its client ID and secret for a short-lived access token, and send that token with every request.

Client credentials

Every integration you create in Jamf Account holds a client_id and a client_secret. Treat the secret like a password:

  • It appears once, at creation. Store it in a secrets manager immediately.
  • Regenerating the secret is the only way to replace a lost one.
  • Integrations are valid for six months. Build rotation into your deployment process.

Use the client_secret_post client authentication method, sending credentials in the request body as form fields.

Request an access token

Send a POST to the token endpoint with Content-Type: application/x-www-form-urlencoded:

curl --request POST \
  --url https://us.api.jamfcloud.com/auth/token \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'grant_type=client_credentials' \
  --data-urlencode 'client_id=<your_client_ID>' \
  --data-urlencode 'client_secret=<your_client_secret>'
ParameterValue
grant_typeclient_credentials
client_idYour integration's client ID
client_secretYour integration's client secret

A successful request returns:

{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "expires_in": 900,
  "refresh_expires_in": 0,
  "token_type": "Bearer",
  "not-before-policy": 0
}

Token lifetime

Access tokens are valid for 900 seconds (15 minutes). refresh_expires_in is 0, so when a token expires you request a new one with the same client credentials.

For anything long-running, refresh on a timer based on expires_in. A 15-minute token expires partway through a large pagination loop.

Use the token

Pass the token as a Bearer token in the Authorization header:

Authorization: Bearer <your_access_token>

Scope levels

Every integration is scoped to one level, chosen when you create it. That level applies to every token the integration issues, and it decides which APIs you can reach and which permissions are available to grant.

Scope levelWhat it reaches
Organization managementJamf Account APIs: audit events, licensing, partner operations such as deal registration and distributor actions, and SSO configuration
Platform environmentPlatform APIs, plus the product APIs of the tenants inside that environment
TenantProduct APIs for the specific instances you select

Platform APIs available at environment scope: blueprints, compliance benchmarks, devices, device groups, device actions, declaration reporting, audit events, and AI policies.

Product APIs available at tenant scope: Jamf Pro, including the Classic API, along with Jamf Protect and Jamf Security Cloud.

A platform environment is a defined group of tenants that your organization has across the Jamf platform. It links resources and capabilities across products, which is why platform APIs work at that level.

📘

Jamf groups most organizations' tenants into an environment automatically, based on how your organization is set up, so no action is needed. Some organizations include tenants purchased or set up in a way that doesn't map cleanly to one environment; those organizations can group tenants manually in the platform environments UI in Jamf Account. If a tenant doesn't appear in your environments at all, contact Jamf Support.

Choosing a level

Pick platform environment for cross-product workflows. The platform APIs and the shared capability model are available at this level.

Pick tenant to confine an integration to one product's data. Capability permissions span products, so tenant scope is what draws that boundary.

Pick organization management for account administration across your whole organization.

📘

An environment-scoped token carries no tenant ID claim, so product APIs that resolve their context from that claim require a tenant-scoped integration. If a product endpoint returns 403 under an environment-scoped token, create one scoped to the tenant.


Regions and data residency

The gateway is deployed in three regions. Which host you call depends on your scope level and the region your product instances are hosted in.

Scope levelBase URL
Organization managementhttps://api.jamfcloud.com
Platform environmenthttps://{region}.api.jamfcloud.com
Tenanthttps://{region}.api.jamfcloud.com

{region} is one of:

RegionCovers
usUnited States
euEurope
apacAsia Pacific

Organization management uses the bare host, which always routes to the US region.

Tokens are region-locked

Request your token from the same host you send API requests to. A token issued by the US endpoint returns 401 at the EU endpoint, and the same applies in reverse.

Scope levelToken endpoint
Organization managementhttps://api.jamfcloud.com/auth/token
Platform environmenthttps://{region}.api.jamfcloud.com/auth/token
Tenanthttps://{region}.api.jamfcloud.com/auth/token

Product availability by region

Most APIs are available in all three regions. One exception applies:

ProductRegional availability
Jamf Security CloudCommercial customers in us, eu, and apac. Education customers in eu and apac.

US-hosted Jamf Safe Internet tenants, which some education customers use for data residency, are outside the supported set for gateway integrations.


Request context

Your token identifies your organization. For environment-scoped and tenant-scoped requests, name the context explicitly in a header:

HeaderSend it forValue
X-Tenant-IdTenant-scoped requestsThe UUID of the product instance
X-Environment-IdPlatform environment-scoped requestsThe UUID of the platform environment
NoneOrganization management requestsThe organization comes from the token

Copy either ID from the Integration details panel in Jamf Account by clicking the relevant pill.

⚠️

This changed at GA. During the public beta, tenant and environment IDs were path segments (/tenant/{tenantId}/). Production accepts the header form only. If you built against the beta, see Updating your Jamf Pro integrations.


Capability permissions

Permissions are organized by capability, meaning what you are trying to do. devices is one capability spanning the whole platform, so it covers device inventory in every product at once. The full permission surface appears in one list.

Format

{capability}:{action}

The capability comes first in kebab-case, followed by the action in lowercase.

PermissionGrants
devices:readRead device inventory
devices:updateModify device records
blueprints:deployDeploy a blueprint
device-groups:readRead device groups
destructive-device-actions:executeErase a device, unmanage it, or remove its MDM profile
audit:readRead audit events

Actions

The gateway supports six actions. Actions are lowercase and case-sensitive.

ActionMeaning
createCreate a new resource
readRetrieve a resource
updateModify an existing resource
deleteRemove a resource
deployPush a configuration to devices
executeRun an action or command
⚠️

Grant every action your integration uses. devices:update covers writes only. Add devices:read if your integration reads a record before modifying it. Some endpoints require two capabilities together.

Each API's reference pages list the permissions their operations require. For the full capability list and the old-to-new privilege mapping, see the Jamf Pro permissions map.


Pagination, sorting, and filtering

Collection endpoints are paginated and accept the same query parameters.

ParameterDefaultNotes
page0Zero-based
page-size100Minimum 1. Some APIs declare a maximum, so check the endpoint's reference page
sortVaries by APIComma-separated, with :desc for descending, e.g. model:desc,name
filterEmpty, meaning all resultsRSQL expression

Filtering with RSQL

The filter parameter takes an RSQL expression. Each endpoint's reference page lists the fields it allows in a query, and dates use ISO 8601 format.

filter=name=="*iPhone*" and lastInventoryUpdateTime>="2026-01-31T18:09:00.000Z"

Comparison operators:

OperatorMeaning
==Equals. An asterisk acts as a wildcard, as in name=="*iPhone*"
!=Not equals, and it also accepts wildcards
=lt= or <Less than
=le= or <=Less than or equal to
=gt= or >Greater than
=ge= or >=Greater than or equal to
=in=Matches any value in a list, as in model=in=(ValueA,ValueB)
=out=Excludes every value in a list

String comparisons are case-insensitive. Arguments containing spaces need quoting, single and double quotes work interchangeably as long as you stay consistent, and a backslash escapes special characters. Null values fall outside every comparison, while empty strings are included.

Combine clauses with and:

filter=deviceType=="MOBILE" and name=="*Managed*"

Response envelopes

Paginated responses on the platform APIs carry full metadata:

{
  "page": 0,
  "pageSize": 100,
  "totalCount": 4213,
  "totalPages": 43,
  "hasNext": true,
  "hasPrevious": false,
  "results": []
}

Some product APIs return a smaller envelope, such as totalCount and results only. Check the reference page for the endpoint you are calling to confirm its shape.

💡

A 15-minute token expires partway through a large pagination loop. Refresh on a timer based on expires_in.


Errors

Two responses have gateway-specific behavior.

StatusWhat it means
401 UnauthorizedThe token expired, is malformed, or came from a different region than the endpoint you called
403 ForbiddenThe integration lacks a capability permission, the API requires a different scope level, or the version segment is unrecognized

Reading a 403

The gateway returns 403 for three separate conditions. Check them in this order:

  1. Check your permissions. Compare the capability the endpoint requires against what your integration was granted in Jamf Account.
  2. Check your scope level. Platform APIs need environment scope, and some product APIs need tenant scope.
  3. Check the version segment in your path. Unrecognized versions return 403 by design, to avoid confirming which paths exist.

A typo in a version segment therefore returns 403 rather than 404.


Versioning

Every endpoint path carries a version segment:

/{api}/v{n}/{resource-path}

The version is required. Each API versions independently, and the move to general availability left every existing version in place, so beta integrations keep the version numbers they already use.


Related articles