> ## Documentation Index
> Fetch the complete documentation index at: https://docs.serval.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Jamf

> Connect Jamf Pro to Serval to query Apple device inventory, manage users and groups, send MDM commands, and ingest your computer fleet into Serval's asset inventory.

## About Jamf

Jamf Pro is Apple-focused mobile device management (MDM) for macOS, iOS, iPadOS, and tvOS fleets. Connecting Jamf to Serval lets your team query device inventory, manage users and groups, send MDM commands (lock, erase, OS update), manage departments and sites, and ingest your full computer inventory into Serval's asset system - all through Serval workflows that call the Jamf Pro API and Classic API on your behalf. Serval only ever sends authenticated requests to the exact Jamf domain you configure.

**Authentication:** Jamf Pro API client (OAuth 2.0 client credentials). You create an API role and API client in Jamf Pro and give Serval the client ID, client secret, and your Jamf Pro hostname. Serval stores the client ID and an encrypted copy of the secret, exchanges them for short-lived bearer tokens against your own Jamf instance, and refreshes tokens automatically - no browser-based sign-in, no user-level consent, no refresh token. Token lifetime is whatever you configure on the API client in Jamf Pro.

**Data sync:** On demand. There is no always-on background sync or webhook from Jamf - workflows call the Jamf APIs when they run (subject to each workflow's approval procedure). For asset inventory, schedule the included **Ingest Jamf Computers** workflow to pull your full computer fleet into Serval.

## What the Jamf integration enables

| Capability                          | Description                                                                                                                                                                                                                                                                          |
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Computer management                 | View, search, and retrieve details for managed computers - look up by user, ID, or serial number; read full inventory sections; retrieve FileVault recovery keys (requires approval); get managed/unmanaged device statistics; and list Automated Device Enrollment (ADE) instances. |
| User management                     | Find users by email, ID, or username; list all users; and create user accounts - both standard (end-user) accounts and Jamf Pro administrator accounts require approval to create.                                                                                                   |
| Group management                    | Create and manage static computer, user, and mobile device groups - create groups, add computers to static groups, list static user groups, and delete groups (mutating actions require approval).                                                                                   |
| MDM commands                        | Send MDM commands to managed computers and devices - device lock, erase device, schedule OS update, enable/disable Remote Desktop, Bluetooth settings, unlock/delete user account, inventory update, and more. All MDM command workflows require approval.                           |
| Organization                        | Create and read departments, create sites, and list all sites for organizing resources in Jamf Pro. Creating departments and sites requires approval.                                                                                                                                |
| Asset inventory ingestion           | The **Ingest Jamf Computers** workflow paginates through your entire computer fleet and pulls hardware, OS, storage, security, and user details into Serval's asset inventory.                                                                                                       |
| Full API access in custom workflows | Custom Serval workflows can call any Jamf Pro API endpoint (JSON) and any Classic API endpoint (JSON or XML) with typed request/response schemas, using the credentials you configured.                                                                                              |

Anything defined in the [Jamf Pro API](https://developer.jamf.com/jamf-pro/reference/jamf-pro-api) or the [Jamf Classic API](https://developer.jamf.com/jamf-pro/reference/classic-api) can be accessed through Serval.

## Get your credentials

Serval authenticates with a Jamf Pro **API client**: an API role defines the privileges Serval will have, and an API client (assigned that role) provides the client ID and secret you'll paste into Serval. See Jamf's official guide, [API Roles and Clients](https://learn.jamf.com/en-US/bundle/jamf-pro-documentation-current/page/API_Roles_and_Clients.html), for full details.

<Steps>
  <Step title="Open API roles and clients">
    Log in to Jamf Pro and open **Settings**, then search for "API roles and clients" (under **System**).
  </Step>

  <Step title="Create an API role">
    On the **API Roles** tab, click **+ New**. Name the role (e.g. "Serval"), select the privileges you want Serval to have, and click **Save**. You can reuse an existing role instead.

    You control exactly what Serval can do through this role - grant only the privileges for the capabilities you plan to use, and leave out the rest. You can always add more privileges to the role later without reconnecting in Serval.
  </Step>

  <Step title="Create an API client">
    On the **API Clients** tab, click **+ New**. Name the client (e.g. "Serval Integration"), assign the API role(s) you just created, optionally set a custom access-token lifetime, confirm the client is **Enabled**, and click **Save**.
  </Step>

  <Step title="Generate the client secret">
    Click **Generate client secret** and copy both the **Client ID** and the **Client Secret** immediately - Jamf shows the secret only once. You'll paste both into Serval.
  </Step>
</Steps>

<Warning>
  Jamf displays the client secret only at generation time. If you lose it, you'll need to generate a new one - which invalidates the old secret.
</Warning>

<Note>
  API roles in Jamf Pro cover both the Pro and Classic APIs. Several Serval workflows and health checks (listing users, computer groups, and departments; creating users and static groups) use the Classic API, so grant the corresponding read/create privileges when building the role.
</Note>

## Connect in Serval

<Steps>
  <Step title="Enter your API Domain">
    **API Domain** (required) - your Jamf Pro hostname, with no https\:// and no trailing path. Works for both Jamf-hosted (yourcompany.jamfcloud.com) and self-hosted (jamf.yourcompany.com) instances; self-hosted servers listening on a non-standard port can include it (jamf.yourcompany.com:8443). The form requires a hostname with at least one dot, plus an optional :port, and rejects anything else with: "Enter a valid Jamf Pro hostname with an optional port (e.g., yourcompany.jamfcloud.com or jamf.yourcompany.com:8443)".
  </Step>

  <Step title="Enter your Client ID">
    **Client ID** (required) - the API client's client ID from Jamf Pro. Stored and shown back in plaintext on the edit screen.
  </Step>

  <Step title="Enter your Client Secret">
    **Client Secret** (required) - the secret you copied when you clicked **Generate client secret** in Jamf Pro. Entered as a password field; after saving, Serval displays it masked (bullets plus the last 4 characters).
  </Step>
</Steps>

<Warning>
  **Editing the connection later:** API Domain and Client ID come pre-filled with their stored values, and Client Secret is shown masked. Leave the pre-filled Client ID in place - submitting the form with that field cleared overwrites the stored Client ID and breaks the connection until you re-enter it. The masked Client Secret is kept unchanged if you don't touch it. To rotate the secret, click the pencil icon on Client Secret, paste the complete new secret (and update the Client ID too if it changed), then click **Update**. Serval automatically re-runs the health checks after you save changes.
</Warning>

## Verifying the connection

Six health checks run against your instance to verify connectivity and privileges, and they re-run automatically whenever you update the connection settings. Each check is an API call that exercises a specific privilege, so all six run regardless of which privileges your API role grants - a check whose privilege you left off the role will simply fail with a permission hint. This is expected if you intentionally scoped the role down, and you can safely ignore failures for capabilities you don't plan to use.

* **Test Jamf Connection** - verifies Serval can authenticate with your Jamf Pro instance by performing the token exchange and calling a lightweight endpoint that also reports your Jamf Pro version.
  * Success: "Successfully authenticated with Jamf Pro at \[domain] (version \[number])"
  * Failure: "Unable to connect to Jamf Pro at \[domain]." followed by a status-specific hint - invalid credentials (401): "The OAuth client credentials are invalid or expired. Please verify your Client ID and Client Secret in the Jamf integration settings."; not authorized (403): "The OAuth client is not authorized to access Jamf. Please ensure the client has been granted the necessary permissions in Jamf Pro."; server errors (500/502/503): "Jamf returned a server error during authentication. This is likely a temporary issue - please try again later."

* **List Jamf Computers** - checks that Serval can list computer inventory records via the Jamf Pro API (first page of 10).
  * Success: "Successfully listed computers from Jamf Pro (\[number] total)"
  * Failure: "Unable to list computers from Jamf Pro." followed by a status-specific hint - 401: "The Jamf API credentials may be invalid or expired. Please verify the OAuth client credentials are correct."; 403: "The Jamf OAuth client may not have the required permissions. Please check that the necessary privileges are granted."; 404: "The requested Jamf resource was not found. This may indicate missing permissions or incorrect API domain configuration."; 500/502/503: "Jamf returned a server error. This is likely a temporary issue with Jamf's API - please try again later."

* **List Jamf Mobile Devices** - checks that Serval can list mobile device inventory records via the Jamf Pro API (first page of 10). Passes with a count of 0 if you manage no mobile devices.
  * Success: "Successfully listed mobile devices from Jamf Pro (\[number] total)"
  * Failure: "Unable to list mobile devices from Jamf Pro." followed by the same status-specific hints as the computers check.

* **List Jamf Users** - checks that Serval can list user accounts via the Classic API (there is no Pro API endpoint for listing users), so your API role's privileges must cover Classic API user reads.
  * Success: "Successfully listed \[number] users from Jamf Pro"
  * Failure: "Unable to list users from Jamf Pro." followed by the same status-specific hints as the computers check.

* **List Jamf Computer Groups** - checks that Serval can list computer groups via the Classic API.
  * Success: "Successfully listed \[number] computer groups from Jamf Pro"
  * Failure: "Unable to list computer groups from Jamf Pro." followed by the same status-specific hints as the computers check.

* **List Jamf Departments** - checks that Serval can list departments via the Classic API.
  * Success: "Successfully listed \[number] departments from Jamf Pro"
  * Failure: "Unable to list departments from Jamf Pro." followed by the same status-specific hints as the computers check.

<Tip>
  If the connection test passes but the users, computer groups, or departments checks fail with a permission hint, your API role is missing Classic API privileges. Those three checks read users, computer groups, and departments through the Classic API - add the corresponding read privileges to the role in Jamf Pro.
</Tip>

## Gotchas and troubleshooting

<AccordionGroup>
  <Accordion title="API role privileges drive everything - including Classic API access">
    Every workflow and health check is limited by the privileges on the API role assigned to your API client. A 403 from a health check means the role is missing a privilege. The user, computer group, and department health checks (and several workflows, such as creating users and static groups) use the Jamf Classic API, so grant the corresponding read/create privileges when building the role - API roles in Jamf Pro cover both the Pro and Classic APIs.
  </Accordion>

  <Accordion title="API Domain is a hostname with an optional port">
    Enter only the hostname - no https\:// prefix and no path. Self-hosted Jamf Pro servers listening on a non-standard port (commonly 8443) can append it, e.g. jamf.yourcompany.com:8443. The form rejects anything else with: "Enter a valid Jamf Pro hostname with an optional port (e.g., yourcompany.jamfcloud.com or jamf.yourcompany.com:8443)".
  </Accordion>

  <Accordion title="Confirm the API client is enabled">
    A newly created API client must be set to **Enabled** in Jamf Pro before saving. A disabled client fails the connection test with an authentication error even when the Client ID and Secret are correct.
  </Accordion>

  <Accordion title="The client secret is shown once in Jamf Pro">
    Jamf displays the client secret only at generation time. Copy it immediately when you click **Generate client secret**. If you lose it, generate a new secret in Jamf Pro and update the integration in Serval - generating a new secret invalidates the old one.
  </Accordion>

  <Accordion title="Editing the connection: keep the Client ID filled, paste the full secret when rotating">
    On the edit screen, API Domain and Client ID are pre-filled with their stored values and Client Secret is shown masked (bullets plus its last 4 characters). Leave the pre-filled Client ID in place - do not clear the field before submitting, or the stored Client ID will be overwritten and the connection will break until you re-enter it. The masked Client Secret is kept unchanged if you don't touch it, so you only need to re-enter it when rotating credentials: click the pencil icon on Client Secret, paste the complete new secret (and the new Client ID if it changed), then click **Update**. Serval automatically re-runs the health checks after every update, so a credential mistake shows up immediately.
  </Accordion>

  <Accordion title="Requests are pinned to your configured domain">
    Serval will only send authenticated requests to the exact hostname you entered as API Domain - the comparison is case-insensitive and exact, with no wildcard or subdomain matching, and the port must match too (a domain without a port means the standard HTTPS port 443). If your Jamf Pro instance moves to a new hostname or port (e.g. a jamfcloud.com rename or a migration to a custom domain), workflows and health checks will fail until you update the API Domain in the integration settings.
  </Accordion>
</AccordionGroup>

***

Need help? Contact **[support@serval.com](mailto:support@serval.com)** for assistance with your Jamf integration.
