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

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