Skip to main content
Deno 2 is finally here šŸŽ‰ļø
Learn more

Jamf School API for Deno

An unofficial, idiomatic API wrapper for Jamf School. Itā€™s designed to feel natural for anyone with basic web development experience to pick it up, and to be safe enough to trust in production.

If something doesnā€™t work as expected or you just want some help, please raise an issue on GitHub so we can improve the library and documentation for everyone!

Currently, only a limited (mostly read-only) subset of API features are supported.

Hereā€™s the documentation for the latest release.

Features

  • Designed for modern JavaScript
  • A low-level API wrapper and a higher-level object-oriented interface
  • Data validation means you always get the data youā€™re promised
  • Comprehensive documentation and easy-to-follow example
  • Only requires --allow-net=YOUR_SCHOOL.jamfcloud.com

Usage

Hereā€™s how to get your API credentials. Youā€™ll have to replace the token, ID, and URL in the examples.

This example will print the name of each registered device.

device_names.ts
import * as jamf from "https://deno.land/x/jamf_school@0.4.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.
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.ts
Show a more complex example

Restart all devices owned by anyone named ā€œRobertā€.

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

// The client can be instantiated with an API instead of credentials.
const api = jamf.createAPI({
  id: "YOUR_NETWORK_ID",
  token: "YOUR_API_TOKEN",
  url: "https://YOUR_SCHOOL.jamfcloud.com/api",
});

const client = jamf.createClient({ api });

// Using the API directly gives you control over exactly what requests
// are made. All the data returned is validated, of course.
const deviceData = await api.getDevices({ ownerName: "Robert" });

// If you have a client, objects can be created from API data directly.
const devices = deviceData.map((data) => client.createDevice(data));

// Everything is promise-based, so you can do things concurrently.
// Methods that perform actions (like restart) will reject on failure.
await Promise.allSettled(devices.map((device) => device.restart()));

Changelog

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

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).
Older versions

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