Available in PaperCut MF only.

Device script API reference

NOTE
  • Device scripting is currently in Percolator, so bear on mind that it will be refined before launch. If you have any feedback or recipe requests, check out the Project Myrtle Percolator page.

  • You can also use Print scripting to define and fine tune your printing policies.

Device scripts are segments of code that run when either a user logs in to a device, a print job is released at the device, or a copy, scan, or fax job has been completed. The script is defined using the concept of a "hook". A hook is a JavaScript function that is defined by you, the script writer. It is also commonly referred to as an entry point or method. A number of device hooks (entry points) are available and each differ by the point in the workflow when they are called. For example, a hook early in the workflow has the ability to influence behavior later in the flow, while scripts late will correspondingly have access to additional information that would not be available earlier.

NOTE

This APIApplication Programming Interface (API) is a set of routines, protocols, and tools for building software and applications. An API expresses a software component in terms of its operations, inputs, outputs, and underlying types, defining functionalities that are independent of their respective implementations, which allows definitions and implementations to vary without compromising the interface. reference describing all the properties and functions available to device scripts. Many of these inputs and functions reference JavaScript objects (e.g. String, Boolean, Date etc.). A good JavaScript reference will assist with making use of and formatting these objects. For more information about JavaScript, see:

IMPORTANT

If you are using version 19.2.6, 20.1.5, 21.2.9, or 22.0.0 and later, you must enable Print Scripting. Go to the Enabling Print Scripting and Device Scripting KB article for more information.Hi

Script hooks (entry points)

The available device hooks are:

Device workflow hooks
HookDescription
deviceLoginHook(inputs, actions)

Use this hook for either:

  • Determining any access rights that are normally set on login (i.e. color copy).

  • Setting configuration changes that will apply to the rest of the login session (filter shared accounts).

Point of Call: Immediately after a user has entered their login credentials/PIN/card swipe for authentication.

Limitations: Cannot analyze any jobs (copy/scan/fax/ held print jobs) at this point.

Use cases for this hook Generally, use this hook for any "Session" actions such as:

  • Block login

  • Prevent users from performing color copy

  • Filtered shared accounts for the rest of the login session

TIP

During percolator, some device types do not support this hook for guest access. For more information, see Known issues with device scripting.

deviceJobLogHook(inputs, actions)

Use this hook to analyze and process a copy/fax/scan job after the job has been completed. Think of it as a post job processing hook that allows you to change the job's properties (ie change the cost, add a comment).

Point of Call: Once the device has sent through a list of job logs for processing.

Limitations: This hook can't be used to block device function jobs (as the job has already finished).

Use cases:

  • Color copy quotas for students at a school that wants to block their students from doing large amounts of color copying.

  • Encourage the use of specific devices for color printing by charging a different amount per device (for example, discount the cost on the devices you want users to use).

TIP

During percolator, some device types do not support this hook. For more information, see Known issues with device scripting.

devicePrintReleaseHook(inputs, actions)

Use this hook to analyze and block release of held print jobs at the device.

Point of Call: Immediately after the user tries to release held print job(s) at the device.

Limitations:

Use case: Prevent the release of jobs charged to a particular account at some devices. For example, a University could prevent the release of jobs charged to the Arts department from any printer outside the Arts building.

All hooks have access to user, device, and utilities information. In addition, each hook has access to specific information, such as device job information for deviceJobLogHook. The scripts have access to these through the two function arguments:

  • inputs - access to the job, user, and device information. inputs are read-only and any modification to variables do not affect the job.

  • actions - Access to perform actions that can influence the job processing, e.g. tochange the job cost. All actions (also known as side-effects) must be performed via the available actions.

All available inputs and actions are listed below.

Script Inputs

User Info (inputs.user)

User Info Script Reference (inputs.user)
Property/Method Description
inputs.user.username

(string) The username of the user that has logged into the device.

inputs.user.fullName

(string) The full name of the user who has logged into the device.

inputs.user.email

(string) The email address of the user that has logged into the device.

inputs.user.office

(string) The office of the user that has logged into the device.

inputs.user.department

(string) The department of the user that has logged into the device.

inputs.user.restricted

(boolean) Determines if the user is restricted.

inputs.user.balance

(number) The user's current account balance.

inputs.user.getBalance(accountName)

(number) The user's current account balance. When a user has multiple personal accountsA personal account is the individual user's account that is charged by default. Each user has their own personal account., the user's current account balance.

Parameters:

  • accountName (string) -This is an optional parameter to specify the personal account name. If not specified, it retrieves the user's total account balance.

inputs.user.isInGroup(groupName)

Determines if the user belongs to the given group name (as defined on the Groups tab).

Parameters:

  • groupName (string) - The name of the group to check. NOTE: The group name is case-sensitive.

inputs.user.getProperty(propName)

Return a value as a string associated with a persistent custom-defined property saved on the user, or null if there is no such value.

Parameters:

  • propName (string) - The name/key of a user property to look up.

For more information about using storage properties, see Custom-defined persistent properties (storage).

inputs.user.getNumberProperty(propName)

A convenience method to return a value as a number associated with a persistent custom-defined property saved on the user, or null if there is no such value.

Parameters:

  • propName (string) - The name/key of a user property to look up.

For more information about using storage properties, see Custom-defined persistent properties (storage).

inputs.user.defaultSharedAccountName

(string) Gets the default shared accountA shared account is an account that is shared by multiple users. For example, in business, shared accounts can be used to track printing costs by business unit, project, or client. Organizations like legal firms, engineering firms, or accounting offices often have long lists of accounts, projects, clients, or matters. In a school or university, shared accounts can be used to track printing by departments, classes, or subjects. name for a user (if configured). If not configured, returns an empty string ("").

inputs.user.autoChargeToSharedAccountName

(string) If the user has an autocharge to shared account, returns the name of that shared account. If there is no autocharge to shared account, returns an empty string ("").

inputs.user.canChargeToPersonalAccount

(boolean) Determines if the user can charge to their personal account. Device and printer overrides supersede this setting.

inputs.user.canOnlyChargeToPersonalAccount

(boolean) Determines if the user can charge only to their personal account (ie if the Account Selection setting in the Admin web interface is:

  • Automatically charge to personal account

  • Charge to personal account with confirmation.

Device and printer overrides supersede this setting.

inputs.user.canSelectSharedAccount

(boolean) Determines if the user has permission to select a shared account.

inputs.user.canSelectAccountFromList

(boolean) Determines if the user can select a shared account from a list. Device and printer overrides supersede this setting.

inputs.user.canSelectAccountUsingPin

(boolean) Determines if the user can select a shared account using PIN codes. Device and printer overrides supersede this setting.

inputs.user.isInternal

(boolean) Determines if the user is an internal user.

inputs.user.primaryCardNumber

(string) Returns the primary card number if configured. If not configured, returns an empty string ("").

inputs.user.secondaryCardNumber

(string) Returns the secondary card number if configured. If not configured, returns an empty string ("").

inputs.user.cardPin

(string) Returns the card PIN for a user if configured. If not configured, returns an empty string ("").

Device Info (inputs.device)

Device Info Script Reference (inputs.device)
Property/Method Description
inputs.device.serverName

(string) The name of the server where the device is hosted.

inputs.device.deviceName

(string) The name of the device.

inputs.device.fullDeviceName

(string) The full name of the device in the format server/device.

inputs.device.isDisabled

(boolean) Determines if this device is currently disabled.

inputs.device.groups

(Array) An array of all the device groups that this device is a member of.

inputs.device.isInGroup(groupName)

(boolean) Determines if the device belongs to a particular device groupDevice groups allow administrators to tag or group devices by attributes. Group names are user definable and can represent any attribute appropriate for device management. For example, you can group devices by device type, location, make, function, owner, age, and so on. You can report by device group and also send notifications per device group..

Parameters:

inputs.device.getProperty(propName)

Return a value as a string associated with a persistent custom-defined property saved on the device, or null if there is no such value.

Parameters:

  • propName (string) - The name/key of a device property to look up.

For more information about using storage properties, see Custom-defined persistent properties (storage).

inputs.device.getNumberProperty(propName)

A convenience method to return a value as a number associated with a custom-defined property saved on the device, or null if there is no such value.

Parameters:

  • propName (string - The name/key of a device property to look up.

For more information about using storage properties, see Custom-defined persistent properties (storage).

Utilities (inputs.utils)

Utilities Script Reference (inputs.utils)
Method Description
inputs.utils.formatBalance(amount)

Formats the balance amount based on the server currency settings. Returns a string.

Parameters:

  • amount (number) - the amount to format.

inputs.utils.formatCost(amount)

Formats the cost amount (e.g. a job cost) based on the server currency settings.

Returns a string.

Parameters:

  • amount (number) - the amount to format.

inputs.utils.formatNumber(amount, decimals)

Formats a number with the given number of decimal places.

Returns a string.

Parameters:

  • amount (number) - the amount to format.

  • decimals (number) - The number of decimal places to format.

inputs.utils.getProperty(propName)

Return a value as a string associated with a persistent custom-defined global property, or null if there is no such value.

Parameters:

  • propName (string) - The name/key of a global property to look up.

For more information about using storage properties, see Custom-defined persistent properties (storage).

inputs.utils.getNumberProperty(propName)

A convenience method to return a value as a number associated with a persistent custom-defined global property, or null if there is no such value.

Parameters:

  • propName (string) - The name/key of a global property to look up.

For more information about using storage properties, see Custom-defined persistent properties (storage).

Device Job Info (inputs.job)

NOTE

These inputs are available only with deviceJobLogHook.

Device Job Info Script Reference (inputs.job)
Property/Method Description
inputs.job.copies

(number) The number of copies. The totalPages attribute already takes the copies into account.

inputs.job.date

(date) The date/time of the copy, scan, or fax job.

inputs.job.paperSizeName

(string) The paper size name (e.g. Letter, Tabloid, A4, A3).

inputs.job.isGrayscale

(boolean) Determines if the copy, scan, or fax job is grayscale (i.e. contains no color).

inputs.job.isColor

(boolean) Determines if the copy, scan, or fax job is color (i.e. contains at least one color page).

inputs.job.isDuplex

(boolean) Determines if the copy, scan, or fax job is duplex.

inputs.job.totalGrayscalePages

(number) The total number of grayscale pages in the copy, scan, or fax job.

inputs.job.totalColorPages

(number) The total number of color pages in the copy, scan, or fax job.

inputs.job.totalPages

(number) The total number of pages in the copy, scan, or fax job.

inputs.job.totalSheets

(number) The total number of sheets of paper produced by the copy, scan, or fax job.

inputs.job.selectedSharedAccountName

(string) The full name of the selected shared account. If no shared account is selected then an empty string is returned ("").

inputs.job.username

(string) The username of the user that performed the copy, scan, or fax job.

inputs.job.isSimplex

(boolean) Determines if the copy, scan, or fax job is simplex.

inputs.job.isFax

(boolean) Determines if it's a fax job.

inputs.job.isScan

(boolean) Determines if it's a scan job.

inputs.job.isCopy

(boolean) Determines if it's a copy job.

inputs.job.duplexPages

(number) The number of duplex pages.

inputs.job.isInvoiced

(boolean) Determines if the copy, scan, or fax job is invoiced.

inputs.job.cost

(number) The cost of the job. The cost returned is the cost of the job after all other cost adjustments have been applied.

inputs.job.calculateCostForDevice(deviceName)

(number) Calculates the cost of this job on another device. This can be used in combination with actions.job.setCost to first calculate the job using another cost model and then applying a new cost.

This returns the cost of the job.

Parameters:

  • deviceName (string) - The name of the device to calculate the cost of the job for. Enter the device name only (without the server name).

inputs.job.comment

(string) The comment for the copy, scan, or fax job.

inputs.job.documentName

(string) The document name.

Held job Info (inputs.heldJob)

NOTE

These inputs are available only with devicePrintReleaseHook.

Held Job Info Script Reference (inputs.heldJob)
Property/Method Description
inputs.heldJob.documentName

(string) Name of the document.

inputs.heldJob.clientMachineOrIP

(string) The machine name or IP address of the client workstation where the job was printed. If both the machine name and the IP address are known, the machine name is returned.

inputs.heldJob.isColor

(boolean) Determines if the job is color (i.e. contains at least one color page).

inputs.heldJob.isDuplex

(boolean) Determines if the job is duplex.

inputs.heldJob.isGrayscale

(boolean) Determines if the job is grayscale (i.e. contains no color).

inputs.heldJob.cost

(number) The cost of the job.

inputs.heldJob.totalPages

(number) The total number of pages in the print job.

inputs.heldJob.printerName

(string) The printer name.

inputs.heldJob.date

(date) The date/time the job was printed.

inputs.heldJob.fullPrinterName

(string) The full name of the printer including the server name, in the format server\printer.

inputs.heldJob.username

(string) The username of the user that printed the job.

inputs.heldJob.selectedSharedAccountName

(string) The full name of the selected shared account. If no shared account is selected then an empty string is returned ("").

inputs.heldJob.isSimplex

(boolean) Determines if the job is simplex.

inputs.heldJob.copies

(number) The number of copies.

inputs.heldJob.printerServerName

(string) The name of the server the print queueA print queue displays information about documents that are waiting to be printed, such as the printing status, document owner, and number of pages to print. You can use the print queue to view, pause, resume, restart, and cancel print jobs. is hosted on.

inputs.heldJob.isChargeToPersonalAccount

(boolean)Determines if the job is being charged to personal account.

inputs.heldJob.isChargeToSharedAccount

(boolean) Determines if the job is being charged to a shared account.

inputs.heldJob.isInvoice

(boolean)Determines if the job is being invoiced.

inputs.heldJob.comment

(string) Returns the comment. If there is no comment, an empty string is returned ("").

inputs.heldJob.paperSizeName

(string) The paper size name (e.g. Letter, Tabloid, A4, A3).

Script Actions

User actions (actions.user)

NOTE

These actions are available with all hooks.

User Actions Script Reference (actions.user)
Method Description
actions.user.onCompletionSaveProperty(propName, value[, options])

Creates a custom-defined persistent user property with a specific value. This operation is performed when the hook has finished running.

Parameters:

  • propName (string) - the name/key of the property to set.

  • value (string) - the property value. Note: Numbers are converted to a string.

For more information about using storage properties, see Custom-defined persistent properties (storage).

actions.user.onCompletionIncrementNumberProperty(propName, value[, options])

A convenience method that increments the value of a custom-defined persistent user property. This operation is performed when the hook has finished running.

Parameters:

  • propName (string) - the name/key of the property to set.

  • value (number) - the amount to increment by. A negative number will decrement.

For more information about using storage properties, see Custom-defined persistent properties (storage).

Device actions (actions.device)

NOTE

These actions are available with all hooks.

Device Actions Script Reference (actions.device)
Method Description
actions.device.onCompletionSaveProperty(propName, value[, options])

Creates a custom-defined persistent device property with a specific value. This operation is performed when the hook has finished running.

Parameters:

  • propName (string) - the name/key of the property to set.

  • value (string) - the property value. Note: Numbers are converted to a string.

For more information about using storage properties, see Custom-defined persistent properties (storage).

actions.device.onCompletionIncrementNumberProperty(propName, value[, options])

A convenience method that increments the value of a custom-defined persistent user property. This operation is performed when the hook has finished running.

Parameters:

  • propName (string) - the name/key of the property to set.

  • value (number) - the amount by which to increment. A negative number will decrement.

For more information about using storage properties, see Custom-defined persistent properties (storage).

Utility actions (actions.utils)

NOTE

These actions are available with all hooks.

Utility Actions Script Reference (actions.utils)
Method Description
actions.utils.sendEmail(recipient, subject, body)

Sends an email to an email address or username.

Parameters:

  • recipient (string) - either the email address or username of the email recipient.

  • subject (string) - subject text of the email.

  • body (string) - body text of the email.

actions.utils.sendEmail(recipients, subject, body)

Sends an email to one or many email addresses or usernames.

Parameters:

  • recipients (array of strings) - either the email addresses or usernames of the email recipients.

  • subject (string) - subject text of the email.

  • body (string) - body text of the email.

Example: to send an email to many email addresses or usernames

actions.utils.sendEmail( ["Administrator", "support-staff@myuniversity.edu"], "Oh no!", "we're out of credit!");

actions.utils.onCompletionSaveProperty(propName, value[, options])

Saves a global value as a string associated with a persistent custom-defined property. This operation is performed once the hook has finished running.

Parameters:

  • propName (string) - the name/key of the property to set.

  • value (string) - the property value. Note: Numbers are converted to a string.

For more information about using storage properties, see Custom-defined persistent properties (storage).

actions.utils.onCompletionIncrementNumberProperty(propName, value[, options])

A convenience method to increment a global number value associated with a persistent custom-defined property. This operation is performed once the hook has finished running.

Parameters:

  • propName (string) - the name/key of the property to set.

  • value (number) - the amount to increment by. A negative number will decrement.

For more information about using storage properties, see Custom-defined persistent properties (storage).

Log Actions (actions.log)

NOTE

These actions are available with all hooks.

Log Actions Script Reference (actions.log)
Method Description
actions.log.info(message)

Logs an informational message to the Application Log.

Parameters:

  • message (string) - the informational message in the Application Log.

actions.log.warning(message)

Logs an warning message to the Application Log.

Parameters:

  • message (string) - the warning message in the Application Log.

actions.log.error(message)

Logs an error message to the Application Log.

Parameters:

  • message (string) - the error message in the Application Log.

actions.log.debug(message)

Logs a message to the server's text-based log file ([app-path]/server/logs/server.log). This is helpful to diagnose problems with device scripts.

Parameters:

  • message (string) - the message to be logged.

Login Actions (actions.login)

NOTE

These actions are available only with deviceLoginHook.

Login Actions Script Reference (actions.log)
Method Description
actions.login.denyLoginAccess()

Block the user from logging in to the device.

Note: This action takes priority over the bypassLoginFilters action.

actions.login.bypassLoginFilters()

Allows a user to bypass any configured login filtersFilters allow you to control attributes of the print settings by either forcing a particular attribute or denying a a print job that does not meet specific criteria. There are two types of print filters: conversions and restrictions. and restrictionsRestrictions are a type of print filter that ensures jobs meet certain criteria (denying those that don't). For example, you can restrict access to one or more printer, define a maximum number of pages allowed in a single job, or allow only duplex. and access a device.

Note: This action will not work if the action denyLoginAccess is also called.

actions.login.denyCopyAccess()

Block both color and grayscale copying on login. This feature is not supported for all device types so make sure you test before using in a live environment.

actions.login.denyColorCopyAccess()

Block color copying on login. This feature is not supported for all device types so make sure you test before using in a live environment.

Note: This action takes priority over bypassColorCopyFilters.

actions.login.bypassColorCopyFilters()

Allows a user to bypass any configured color copying filters and restrictions and grants them color copying access.

Note: This action will not work if denyColorCopyAccess if also called.

actions.login.setAvailableSharedAccounts(parentNames)

Restrict the shared accounts available at the device by creating a whitelist of approved accounts. A user who logs into the device can charge only to their shared accounts if those accounts have been whitelisted.

Parameters:

  • parentNames (Array) - A list of parent shared account names.

Note: This action takes effect on the “Account Selection” screen. Please review recipe “Restrict selectable shared accounts on device” to address corner cases.

This action accepts only parent shared accounts. Any child accounts will be implicitly included in the whitelist when the parent account is listed.

Example: To allow for only Science related shared accounts to be selected on the device:

actions.job.setAvailableSharedAccounts( ["Biology", "Chemistry", "Physics"]);

In the above example, a user who belongs to two faculties and can charge to both “Biology” and “Arts” shared accounts, but will only be able to charge to “Biology” when accessing this device (as “Arts” has not been whitelisted).

Job actions (actions.job)

NOTE

These actions are available only with deviceJobLogHook.

Job Actions Script Reference (actions.job)
Method Description
actions.job.setCost (cost)

Sets the cost of the job.

Note: If there are other cost adjustments configured (e.g. user cost overrides), these will be applied before the deviceJobLog hook has started running.

Parameters:

  • cost (number) - The cost of the job. Must be greater than or equal to 0.

actions.job.addComment (comment)

Appends a comment to the job. This is logged to the database and is available in the job logs and reports. If the job already has a comment (e.g. set by the user with the advanced client) then this appends to the existing comment.

Parameters:

  • comment (string) - The comment to add to the print job.

Held Print Job actions (actions.heldJob)

NOTE

These actions are available only with devicePrintReleaseHook.

Held Print Job Actions Script Reference (actions.job)
Method Description
actions.heldJob.blockRelease(message)

Block the user from releasing a held print job and display a customizable message on the device screen to notify the user as to why the job was blocked from release. If the user releases multiple held print jobs at the same time, then calling this action on at least one of those held print jobs will subsequently block the other jobs from being released.

Parameters:

  • message (string) - The message displayed on the screen when the job gets blocked from release.

actions.heldJob.blockRelease()

Block the user from releasing a held print job. A default message will be displayed on the device screen to notify the user that the held print job was denied due to print restrictions. If the user releases multiple held print jobs at the same time, then calling this action on at least one of those held print jobs will subsequently block the other jobs from being released.

Custom-defined persistent properties (storage)

Device scripts have the ability to store or save information between executions. They allow you to implement advanced logic that takes advantage of not just the current job event information, but any information that has been stored by previous script events. Properties can also be used to share data between different scripts. Some ideas that can be implemented with device script properties include:

  • Rate limits – knowledge of previous jobs in the given period need to be stored/known.

  • Detecting duplicate events/situations over time.

  • Detecting repeatable user behavior. e.g. how many times a user uses duplex in a row.

  • Shared settings between scripts . e.g. Global defined configuration variables/settings.

Properties are key-value pair storage that are associated with a user or device, or optionally can be global. Keys are Strings that uniquely define the property. Values are stored as strings and are any data that can be converted to and from a string. The maximum length of a key is 70 characters, and the value is 1,000 characters.

Working with properties

Properties are fetched via the getProperty call on the associated source. For example, to fetch a property stored for:

  • the user associated with the login or job (depending on the hook), use inputs.user.getProperty("my-key")

  • the device, use inputs.device.getProperty(),

  • global properties, use inputs.utils.getProperty().

There is also a set of convenience methods called getNumberProperty() if dealing exclusively with a number.

By default, properties are saved (to the database) only after the hook is completed.

You can also set the values of properties. For example, to set a property on the user, use:

actions.user.onCompletionSaveProperty("my-key", "my-value")

TIP

Global properties:

Global properties are stored as PaperCut config settings so any privileged SysAdmin can edit them. You can find your properties via Options > Actions > Config editor (Advanced). All script properties are prefixed with script.user-defined. and are searchable by name. Global properties are a great way to define editable configuration values that are shared between scripts.

TIP

Device properties

Device properties are stored as hidden PaperCut NG/MF config settings. They can be set or read using either the Server commands (server-command) or the The XML Web Services API. All script properties are prefixed with script.user-defined. Device properties are a great way to define editable configuration values that are unique to specific devices (e.g. custom cost information) that can be used in device scripts. To set a device property use a server-command similar to:

server-command set-printer-property device flatbed advanced-config.script.user-defined.default-coverage 45

You can then use these properties in your device script via your device script. You can also use get-printer-property to read values.

TIP

User properties

User properties are stored as hidden PaperCut NG/MF config settings. They can be set or read using either the Server commands (server-command) or the The XML Web Services API. All script properties are prefixed with script.user-defined. User properties are a great way to define editable configuration values that are unique to specific users (e.g. custom cost information) that can be used in device scripts. To set a user property use a server-command similar to:

server-command set-user-property user1 print-script-property.default-coverage 45

This server-command and subsequent Web Services call is automatically prefixed with script.user-defined, so we don't need to specify it in the command.

You can then use these properties in your device script via your device script. You can also use get-user-property to read values.

Implementing Counters (Advanced)

There are two ways to implement a counter (e.g. a page number count). One approach is to get the current value, increment, then save. However, on high volume networks, another event might overwriting the value. Device scripts provide a convenient method that avoids this called onCompletionIncrementNumberProperty(). See the recipe "Impose a daily color copy limit" for an example.

Device script requirements (advanced)

These notes are intended for advanced developers "pushing the limits" of device script functionality. All device scripts must conform to the following technical requirements:

  1. Timeouts: All scripts' execution logic should complete within 5 seconds of CPU time. Failure to comply (for example, due to an infinite loop), results in the script terminating and raising a runtime error. Five seconds is adequate as even the most advanced example recipes complete within a few milliseconds.

  2. Idempotent: All scripts should remain idempotent. It's expected to provide the same output given the same input. Side-effects based off logic other than the inputs are not recommended. For example, logic based off the result of Math.random() would violate this principle.

Device Script Frequently Asked Questions