Skip to main content

Jamf School API for Deno

Create Jamf School automations, quickly and easily.

An unofficial, idiomatic API wrapper for Jamf School. It’s designed to be easy for IT professionals with JavaScript experience to learn, and to be safe enough to trust in production.

Features

  • High level interface for simple automations
  • Low-level API wrapper for fine-grained control
  • Strict data validation completely removes hard-to-catch bugs
  • Only requires --allow-net=YOUR_SCHOOL.jamfcloud.com

If you want some help or want to make a suggestion, open an issue on GitHub so we can make this project better for everyone.

Get started

To interface with the API, you’ll need a client. Clients have a lot of methods to get objects from the API.

Objects are a snapshot of their data at the point in time they were created, and always assume that they’re up to date. They have properties you can access, and methods you can call to act on themselves or get other objects.

Here’s how to get your API credentials - you’ll need those in order to use this library.

device_names.js
import * as jamf from "https://deno.land/x/jamf_school@0.5.0/mod.ts";

const client = jamf.createClient({
  id: "YOUR_NETWORK_ID",
  token: "YOUR_API_TOKEN",
  url: "https://YOUR_SCHOOL.jamfcloud.com/api",
});

// See the docs for everything clients can do.
// https://doc.deno.land/https/deno.land/x/jamf_school@0.5.0/mod.ts#Client
const devices = await client.getDevices();

for (const device of devices) {
  console.log(device.udid, device.name);
}

Now run that script.

deno run --allow-net=YOUR_SCHOOL.jamfcloud.com device_names.js

For some more useful and well documented examples, check out the examples directory.

For über-nerds, there’s also a lower-level API wrapper available. Here’s the documentation.

Changelog

Each entry explains what changed and links to a pull request that has more details.

A brief note on API stability: as this project has not reached 1.0.0 yet, names and imports may change between updates. I want to create a polished library that feels great to use. Doing that requires constantly re-evaluating past decisions and designing other solutions.

Version 0.5.0

  • Breaking: Reorganized module exports (#79)
    Import mod.ts for the client stuff, and api.ts for the low-level API stuff. This keeps the documentation much cleaner.

  • Breaking: Renamed DeviceGroup.isSmartGroup (#77)
    Removed the stutter from the name (now DeviceGroup.isSmart).

  • Added support for profiles (#76)
    Due to limitations with the API, it isn’t possible to get only profiles assigned to particular devices or device groups.

  • Exposed more properties on objects (#77, #82, #86)
    This includes, but is not limited to, Device.ownerName, DeviceGroup.count, and User.getClasses().

  • Optimized Add & Edit object methods (#81)
    API calls are skipped in cases where nothing would change. This was previously applied inconsistently, now it is a defined behaviour where appropriate.

Older versions

Version 0.4.1

  • Added User.restartDevices() (#73)
    Users contain devices, so this makes the API more consistent.

  • Fixed DeviceGroup.restartDevices() (#75)
    The documentation claimed that failing to restart devices wouldn’t throw, but it actually did.

Version 0.4.0

  • Added methods to edit a User/UserGroup/Device/DeviceGroup (#58, #61, #62)
    Update multiple properties using an API, or more easily with the respective objects’ set methods.

  • Added methods to set User/Device locations (#63, #66)
    Move individual users and devices, or move in bulk with Location objects. Search the docs for ‘move’ or ‘location’.

  • Added Client.getUserByUsername (#58)
    Usernames are inherently unique, so this makes it a reliable way to fetch users.

  • Added locationId & ownerId property to relevant objects (#66)
    Makes it easier to use the objects and allows for better optimization.

  • Added DeviceGroup.restartDevices() & Location.restartDevices() (#70)
    These methods make simple restart-scripts much easier to write, but they don’t provide detailed results (failure to restart will not result in an exception).

  • Renamed API.assignDeviceOwner (#58)
    Now it’s more consistent: API.setDeviceOwner

  • Relaxed signature of Client.getDevicesInGroups (#58)
    The only property of the DeviceGroup objects used was id, and this update is aiming to make this style general.

  • Improved how objects are displayed in the console (#60)
    console.log(someDevices) no longer results in Device {}! Indentation doesn’t work properly due to some internal Deno stuff.

  • Breaking: Methods that returned Promise<this> now return Promise<void> (#68)
    Returning this is unexpected and encourages worse code than returning nothing at all.

Version 0.3.2

  • Improved the implementation of Device.enrollment (#56)
    This should be marginally faster. The “manual” type now also includes a pending property (currently always false).

Version 0.3.1

  • Added Device.enrollment (#53)
    It’s an object instead of a string. See the docs for more information.

  • Added Client.getUserByName (#53)
    Returns null if there are no users with the name, fails if multiple users have it.

Version 0.3.0

  • Added support for apps (#15)
    This includes Client.getApps, Client.getAppsById, and Device.getApps. See the documentation for more information (the App interface).

  • Added support for locations (#40)
    Locations can get the data that belongs to them, and all objects can now get their location.

  • Specified the behaviour of toString and toJSON methods (#49)
    These methods can now be used reliably now that their behaviour is consistent and obvious.

Version 0.2.1

  • Suggest identifiers for APIGetDevicesOptions.modelIdentifier (#34)
    This uses the list curated in SeparateRecords/apple_device_identifiers to suggest strings, and still allows any string to be assigned to the property.

Version 0.2.0

  • Breaking: Changed how clients are instantiated with an API (#8)
    The API object must now be passed in as an api property on an object.

  • Added methods to set device ownership (#10, #16)
    API.assignDeviceOwner and Device.setOwner. The documentation contains examples.

  • Various schema improvements and corrections (#10, #20)
    More data is now included. To the best of my knowledge, the current schemas are complete.

  • Schemas don’t fail when additional properties are returned (#19)
    Release builds of schemas are now resilient against additional properties being added, but will still fail if any required properties are omitted.

  • Handle authentication errors with a better message (#24)
    Previously, authentication errors were lumped in with other errors, which made them confusing to read.

  • Changed how data is validated (#7)
    Technical change, but a good increase in real-world performance.

Version 0.1.0

  • Initial release
    Includes basic API support for devices, device groups, users, and user groups, as well as an object-oriented layer to simplify using the API.

License and Disclaimer

JAMF is a trademark beloning to JAMF Software, LLC. This project’s development is not affiliated with JAMF Software, LLC.

There is a copy of the project’s license (MIT) located in the root of the repository and in the module entrypoint (mod.ts).