npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@pixlcore/xyops-sdk

v1.0.4

Published

An API client and job runtime helper library for xyOps.

Readme

xyOps SDK for Node.js

The xyOps SDK is a Node.js client library for xyOps, a workflow automation, job scheduling, and server monitoring platform. It provides a friendly JavaScript interface for two common use cases: controlling xyOps remotely through its REST API, and communicating with xyOps from inside a running job.

The package provides two independent interfaces:

  • api is a wrapper around the xyOps REST API. It handles request formatting, authentication, and response parsing for you. Use it from applications, services, command-line scripts, integrations, or even from inside an xyOps job. See API Client for details.
  • job is a runtime toolkit for Node.js code launched by xyOps. It reads the job input, provides access to parameters, data, files, secrets, performance metrics, and optional structured logging, and sends progress updates and final results back to xyOps. It handles the JSON-over-STDIO wire protocol for you. See Job Runtime SDK for details.

You can use either interface by itself, or use both together inside a job. Import them using CommonJS:

const { api, job } = require('@pixlcore/xyops-sdk');

Or using ESM:

import { api, job } from '@pixlcore/xyops-sdk';

The SDK is included with xySat (xyOps Satellite) v1.0.34 and later. This means your custom xyOps Event Plugins, and scripts running through the built-in Shell Plugin, can use the SDK automatically by requiring it, without a separate installation step.

Installation

npm install @pixlcore/xyops-sdk

Job Runtime SDK

The job interface is designed for a custom Node.js Event Plugin or a Node.js script running through the built-in Shell Plugin. It reads the job document from STDIN and writes newline-delimited XYWP JSON to STDOUT.

Basic Job

Always call and await job.read() before accessing job input:

const { api, job } = require('@pixlcore/xyops-sdk');

(async function() {
	await job.read();
	
	let params = job.getParams();
	console.log('My param: ' + params.myparam);
	
	job.finalSuccess('Job successful');
})();

If you are developing an ESM module, you can use import syntax with top-level await (with Node.js v22+):

import { api, job } from '@pixlcore/xyops-sdk';

await job.read();

let params = job.getParams();
console.log('My param: ' + params.myparam);

job.finalSuccess('Job successful');

Normal output that does not contain XYWP JSON is written to the job log. Every helper update is flushed immediately to STDOUT.

Once you call job.finalSuccess() or job.finalError(), the SDK disables further job updates. Make the final call the last operation in your script.

Reading Input

job.read

Async function which reads all JSON from STDIN and merges the job properties into the job object.

await job.read();
console.log(job.id);

For more details about what is included, see Job Input.

job.getParams

Returns all Event Plugin parameters.

let params = job.getParams();
console.log(params);

job.getParam

Returns one Event Plugin parameter by its name.

let mode = job.getParam('mode');

job.getFiles

Returns the input.files metadata array. Input files are already downloaded into the job's current working directory.

let files = job.getFiles();
for (let file of files) console.log(file.filename);

For more details, see Input Files.

job.getData

Returns all input.data, or one top-level value when you provide a key.

let data = job.getData();
let customerId = job.getData('customer_id');

job.getWorkflowData

Returns all shared workflow data, or one top-level value. Outside a workflow this returns an empty object or undefined for a missing key.

let shared = job.getWorkflowData();
let batchId = job.getWorkflowData('batch_id');

For more details, see Sharing Data Between All Nodes.

job.getServerData

Returns all user data for the current server, or one top-level value.

let serverData = job.getServerData();
let region = job.getServerData('region');

For more details, see Server User Data.

job.getSecrets

Returns all assigned Secret Vault variables.

let secrets = job.getSecrets();

For more details, see Secrets.

job.getSecret

Returns one assigned Secret Vault variable by its name.

let password = job.getSecret('DB_PASSWORD');

Do not print secrets to STDOUT or STDERR because ordinary output is captured in the job log.

Encrypting and Decrypting Values

These helpers let your job encrypt and decrypt its own values locally. They use the same encryption format used internally by xyOps: AES-256-GCM authenticated encryption, with a unique random salt and initialization vector for every call. The passphrase is processed with scrypt to derive the encryption key.

The value may be an object, array, string, number, boolean, or null. In other words, it can be any value which can safely make a JSON round trip. Values with special JSON behavior may not come back in their original form. For example, a Date becomes a string, properties containing undefined are omitted, and circular objects or values containing BigInt cannot be serialized.

You supply and manage the passphrase. A long, randomly-generated passphrase from an xyOps Secret Vault variable is strongly recommended. Do not hard-code it, write it to the job log, or store it beside the encrypted record.

Both helpers also accept optional additional authenticated data, or AAD. AAD is context which is authenticated along with the ciphertext but is not encrypted or included in the returned record. It is useful for binding an encrypted value to a particular customer, record, or purpose. For example, an AAD value such as customer:CUSTOMER_ID prevents that ciphertext from being successfully decrypted in a different customer context. AAD can be public, but decryption must receive the exact same string or Buffer. If you omit it during encryption, omit it during decryption too.

The return value is one Base64-encoded string containing the ciphertext and all encryption metadata. You can store it directly in a spreadsheet cell, text field, environment variable, or any other system which accepts plain strings. Internally, the binary encryption fields are also Base64-encoded before the entire record is encoded. This extra Base64 layer is for portability only and does not add encryption.

Because each encryption uses a random salt and initialization vector, encrypting the same value twice produces different strings.

job.encryptValue

Encrypts a JSON-serializable value using your passphrase and optional AAD, then returns a single Base64-encoded string.

await job.read();

let passphrase = job.getSecret('SECRET_PASSPHRASE');
if (!passphrase) return job.finalError('missing_passphrase', 'Encryption passphrase is not available');

let encrypted = job.encryptValue({
	username: 'jsmith',
	password: '12345'
}, passphrase);

The returned value is an opaque plain string which can be stored without any additional serialization. Pass it back to job.decryptValue() exactly as returned.

job.decryptValue

Accepts a Base64-encoded string previously returned by job.encryptValue(), then decrypts and returns the original JSON value.

let passphrase = job.getSecret('SECRET_PASSPHRASE');
let encrypted = job.getData('protected_value');

try {
	let value = job.decryptValue(encrypted, passphrase);
	console.log('Decrypted value for user: ' + value.username);
}
catch (err) {
	job.finalError('decrypt_failed', 'Could not decrypt the protected value');
}

This method throws an error if the input cannot be decoded, if the passphrase or AAD does not match, if the encrypted string was modified or damaged, or if the decrypted content is not valid JSON. Wrap calls in try / catch, and avoid logging the decrypted value or the underlying error if either could expose sensitive information.

Sending Output Data

job.addData

Adds freeform output data for downstream jobs. Multiple updates are shallow-merged by xyOps, and top-level arrays are concatenated.

job.addData({ records_processed: 125, result: 'ok' });

For more details, see Output Data.

job.addWorkflowData

Adds shared workflow data. xyOps merges it into the parent workflow when this sub-job completes.

job.addWorkflowData({ batch_id: 'batch-2026-07-12' });

For more details, see Workflow Data.

job.addServerData

Adds persistent user data for the server running the job. xyOps applies the shallow merge when the job completes.

job.addServerData({ last_backup: Date.now() });

For more details, see Server Data.

Attaching Files

job.addFile

Appends one output file path or glob pattern. xyOps uploads the matching files when the job completes and passes them to downstream jobs.

job.addFile('report.csv');

For more details, see Output Files.

job.addFiles

Appends multiple output file paths or glob patterns. Each item may also be an object with path and delete properties.

job.addFiles(['logs/*.log', { path: 'temp/*.json', delete: true }]);

For more details, see Output Files.

Tags and Actions

job.addTag

Appends one Tag ID to the current job.

job.addTag('important');

For more details, see Job Tags.

job.addTags

Appends multiple Tag IDs to the current job.

job.addTags(['nightly', 'backup']);

For more details, see Job Tags.

job.addAction

Appends one job action object. See Action Types for all supported properties.

job.addAction({
	condition: 'success',
	type: 'run_event',
	event_id: 'EVENT_ID',
	params: {},
	enabled: true
});

For more details, see Job Actions.

job.addActions

Appends multiple job action objects. See Action Types for all supported properties.

job.addActions([
	{ condition: 'complete', type: 'email', email: '[email protected]', users: [], enabled: true }
]);

For more details, see Job Actions.

Custom Job Content

These helpers add a custom report to the Job Details page. caption is optional in every call.

job.setTable

Displays tabular data.

job.setTable(
	'Import Results',
	['File', 'Rows'],
	[['customers.csv', 250], ['orders.csv', 840]],
	'Rows imported by file'
);

For more details, see Custom Content.

job.setHTML

Displays sanitized HTML. xyOps removes elements and attributes that are not allowed by its sanitization configuration.

job.setHTML('Summary', '<b>Backup complete</b>', 'Generated by the backup job');

For more details, see Custom Content.

job.setText

Displays plain text while preserving whitespace.

job.setText('Command Output', 'Processed: 125\nFailed: 0');

For more details, see Custom Content.

job.setMarkdown

Displays GitHub Flavored Markdown rendered and sanitized by xyOps.

job.setMarkdown('Summary', '**Backup complete**\n\nAll files were uploaded.');

Only one HTML, text, or Markdown content block is retained for a job.

For more details, see Custom Content.

Live Updates

job.setProgress

Updates the job progress. Pass a fraction from 0.0 through 1.0, or a percentage greater than 1.

job.setProgress(0.25);
job.setProgress(50);
job.setProgress(100);

job.setStatus

Sets the temporary status line shown while the job is running.

job.setStatus('Processing file 34 of 68...');

job.setLabel

Sets the label displayed beside the Job ID in completed job history.

job.setLabel('Nightly Customer Import');

Job Logging

job.logger

After you call and await job.read(), job.logger contains a ready-to-use pixl-logger instance. Logging is completely optional. The SDK creates the logger for you, but it does not write anything unless you call one of its logging methods.

pixl-logger writes one text row per event using bracket-delimited columns. For example, a debug message may look like this:

[1784059200.123][2026-07-14 10:20:00][worker01][12345][EVENT_ID][JOB_ID][debug][1][Starting database backup][]

The SDK configures these columns by default:

[
	'hires_epoch', 'date', 'hostname', 'pid', 'event',
	'job', 'category', 'code', 'msg', 'data'
]

The timestamps, hostname, process ID, Event ID, and Job ID are populated automatically. The shortcut methods also populate category, so you typically only need to provide a code, msg, and optional data. Objects passed as data are serialized as JSON.

await job.read();

job.logger.debug(1, 'Debug level 1 message');
job.logger.error('DB702', 'Database connection failed');
job.logger.transaction('backup_create', 'Created backup successfully', {
	files: 14,
	bytes: 5823411
});

The default debug level is 1. Calls to debug() with a higher level are silently skipped. Set a more verbose level once, immediately after reading the job:

await job.read();
job.logger.set('debugLevel', 9);

job.logger.debug(9, 'Detailed diagnostic message');

The logger initially writes to the unique path supplied by xyOps in job.log_file. If the logger writes to this path, xySat automatically uploads the file, attaches it to the job at completion, and deletes the local copy.

You can point the logger at a different file at any time:

job.logger.path = '/var/log/my-custom-log.log';

A custom path is not uploaded or deleted automatically. You are responsible for rotating or archiving that file. If you want the custom log attached to the job, add it explicitly:

job.addFile(job.logger.path);

You can replace the default columns with any set you need:

job.logger.columns = ['date', 'code', 'msg'];

You can also replace the default bracket-delimited serializer. This example writes a simple comma-separated row:

job.logger.serializer = function(cols, args) {
	return cols.join(',') + "\n";
};

By default, the SDK enables synchronous mode, so each row is written with fs.appendFileSync(). This is a safe default for ordinary job logging. If your job produces an extremely high volume of log rows, enable buffering to write rows in batches. Approximate time mode can reduce clock overhead as well:

await job.read();

job.logger.enableBuffer();
job.logger.approximateTime = true;

// Perform high-volume work and write log rows here.

job.finalSuccess('High-volume work complete');

See the pixl-logger documentation for the complete API, including print(), custom hooks, console echoing, buffering, rotation, and archiving.

Performance Metrics

job.perf

After you call and await job.read(), job.perf contains a running pixl-perf tracker. You can use it to measure named operations and increment arbitrary counters throughout your job:

await job.read();

job.perf.begin('db_backup');
// Perform the database backup.
job.perf.end('db_backup');

job.perf.begin('db_vacuum');
// Vacuum the database.
job.perf.end('db_vacuum');

job.perf.count('db_bytes_saved', 5000);
job.perf.count('dangling_pages', 8);

job.finalSuccess('Database maintenance complete');

Named timings are cumulative, so you can call begin() and end() with the same name multiple times. Counters also accumulate, and default to an increment of 1 when you omit the amount:

job.perf.count('records_processed');
job.perf.count('records_processed', 25);

For overlapping asynchronous operations that use the same metric name, keep the tracker returned by begin() and end that specific measurement:

let tracker = job.perf.begin('api_request');
await makeRequest();
tracker.end();

When you call job.finalSuccess() or job.finalError(), the SDK automatically summarizes the tracker and includes the metrics in the final job metadata for xyOps to display. If you do not add any named timings or counters, the SDK omits the tracker summary.

The SDK reports timings in seconds by default. To use a different time scale, call setScale() immediately after job.read() and before recording your own metrics. For example, use a scale of 1000 to report milliseconds:

await job.read();
job.perf.setScale(1000); // milliseconds

The scale represents how many units equal one second. Use 1 for seconds, 1000 for milliseconds, 1000000 for microseconds, or 1000000000 for nanoseconds. See the pixl-perf documentation for precision and advanced tracker options.

If you already have your own raw performance metrics and do not want to use pixl-perf, you can send them directly with job.write(). Values normally represent elapsed seconds:

job.write({ perf: { foo: 42, bar: 100 } });

For more details about accepted raw formats, see Perf Metrics.

Completing the Job

job.finalSuccess

Completes the job successfully with code 0. The message is optional and defaults to Success. Any user-added performance metrics are included automatically.

job.finalSuccess('Imported 250 records');

job.finalError

Completes the job with an error. The code defaults to 1, and the message defaults to Unknown Error. Any user-added performance metrics are included automatically.

job.finalError(999, 'Database connection failed');

An error code may be a number or string, but it must be truthy.

Low-Level Output

job.write

Writes one raw XYWP update immediately. The SDK adds xy: 1, serializes the object onto one line, and appends a newline. Prefer the specific helpers above when one is available.

job.write({ progress: 0.5, status: 'Halfway there...' });

Do not include a final code with job.write() and then continue sending updates. Prefer finalSuccess() or finalError() so the SDK also prevents accidental writes after completion.

Complete Job Example

const { api, job } = require('@pixlcore/xyops-sdk');

(async function() {
	try {
		await job.read();
		
		let eventId = job.getParam('event_id');
		job.setLabel('Event Inspector');
		job.setStatus('Loading event...');
		job.setProgress(10);
		
		let { err, data } = await api.getEvent({ id: eventId });
		if (err) return job.finalError(1, err.message || String(err));
		
		job.addData({
			event_id: data.event.id,
			event_title: data.event.title
		});
		
		job.setMarkdown(
			'Event Summary',
			'Loaded **' + data.event.title + '** successfully.'
		);
		job.setProgress(100);
		job.finalSuccess('Event loaded');
	}
	catch (err) {
		job.finalError(1, err.message || String(err));
	}
})();

When this code runs as an xyOps job, the API client automatically uses JOB_BASE_URL. You still need to make an API key available as XYOPS_API_KEY, typically through the xyOps Secret Vault.

API Client

Configuration

Set these environment variables before loading the SDK:

| Variable | Required | Description | |----------|----------|-------------| | XYOPS_BASE_URL | Yes, outside a job | Base URL of your xyOps conductor, such as https://xyops.example.com. | | XYOPS_API_KEY | Yes | An xyOps API Key with the privileges required by the APIs you call. | | JOB_BASE_URL | (Automatic) | Base URL supplied to running xyOps jobs. This is used when XYOPS_BASE_URL is not set. | | XYOPS_USER_AGENT | No | Replaces the default SDK HTTP User-Agent string. | | XYOPS_TIMEOUT | No | Time-to-first-byte timeout in milliseconds. Defaults to 30000. | | XYOPS_CONNECT_TIMEOUT | No | DNS and socket connection timeout in milliseconds. Defaults to 10000. | | XYOPS_IDLE_TIMEOUT | No | Socket idle timeout in milliseconds. Defaults to 30000. | | XYOPS_RETRIES | No | Number of automatic request retries. Defaults to 0. | | XYOPS_RETRY_DELAY | No | Initial delay between automatic retries in milliseconds. The delay doubles after each retry. Defaults to 50. | | XYOPS_RETRY_DELAY_MAX | No | Maximum delay between automatic retries in milliseconds. Defaults to 8000. | | XYOPS_ALLOW_UNAUTHORIZED | No | Set to any nonempty value to accept self-signed or otherwise unauthorized TLS certificates. This disables certificate verification for all SDK API requests. |

For example:

export XYOPS_BASE_URL="https://xyops.example.com"
export XYOPS_API_KEY="YOUR_API_KEY"

XYOPS_ALLOW_UNAUTHORIZED is intended for local development and testing. Do not enable it in production unless you understand the risks.

The client automatically sends the API key in the X-API-Key header.

Making a Request

API methods use camel case. The SDK converts the method name to the snake case xyOps API name, so api.getEvent() calls get_event:

const { api } = require('@pixlcore/xyops-sdk');

(async function() {
	let { err, data } = await api.getEvent({ id: 'emri0e0tnxibay5t' });
	
	if (err) {
		console.error(err);
		return;
	}
	
	console.log(data.event);
})();

The first argument is the API request object. Depending on the API, this may be automatically serialized as a query string, or passed as JSON POST data.

Responses and Errors

The API client does not throw by default. Every call resolves to the following object:

let { err, data, resp, perf } = await api.getEvent({ id: 'emri0e0tnxibay5t' });

| Property | Description | |----------|-------------| | err | An error object or message on failure. It will be false or undefined on success. | | data | Response data. Standard API responses are parsed into JavaScript objects. Downloads and streams may not include this. | | resp | The raw Node.js IncomingMessage response. | | perf | A pixl-perf request tracker. Call perf.metrics() for timing and counter details. |

Check err before using data:

let { err, data } = await api.getEvents();
if (err) return console.error(err);

console.log(data.rows);

If you prefer exceptions, enable throw mode once during startup:

api.throw = true;

try {
	let { data } = await api.getEvent({ id: 'emri0e0tnxibay5t' });
	console.log(data.event);
}
catch (err) {
	console.error(err);
}

Request Options

Pass a optional options object as the second argument. You can specify properties such as headers, files, and download. The SDK always adds the X-API-Key header (unless you set your own).

let { err, data } = await api.runEvent(
	{ id: 'emri0e0tnxibay5t' },
	{ headers: { 'X-Request-ID': 'deploy-123' } }
);

See the pixl-request documentation for all supported options.

Downloading Files

Set download to a destination path or writable stream, for APIs that return binary responses. The promise resolves after the complete response has been written.

let { err } = await api.getJobLog(
	{ id: 'JOB_ID' },
	{ download: 'dest_file.log' }
);

You can use the same pattern for other wrapped binary or streamed APIs. Endpoints with extra path components or nonstandard GET names may require a direct HTTP request, as noted in the catalog.

Uploading Files

Pass file paths in opts.files like this:

let { err } = await api.uploadBucketFiles(
	{ id: 'BUCKET_ID' },
	{ files: ['file1.txt', 'file2.txt'] }
);

You can pass the files array directly as a shorthand:

let { err } = await api.uploadBucketFiles(
	{ id: 'BUCKET_ID' },
	['file1.txt', 'file2.txt']
);

The same pattern works with APIs such as uploadFiles, runEvent, createTicket, uploadUserTicketFiles, and sendEmail.

Streaming a Live Job

streamJob watches a live job, and calls your iterator function for every update (i.e. progress, state changes, completion, etc.):

let { err } = await api.streamJob({ id: 'JOB_ID' }, function(data) {
	// called repeatedly for each streaming job update
	console.log(data);
});

The call remains pending until the event stream closes.

API Catalog

Every standard API method is available via the SDK. The examples below show the SDK method and an example request. Follow each link for parameters, privileges, and response fields.

All examples assume you've preloaded the API:

const { api } = require('@pixlcore/xyops-sdk');

Alerts

getAlerts

Fetch all alert definitions. This call does not require any parameters. See the get_alerts API reference for response details.

let { err, data } = await api.getAlerts();
if (err) return console.error(err);

console.log(data.rows);

getAlert

Fetch one alert definition by its ID. See the get_alert API reference for parameter and response details.

let { err, data } = await api.getAlert({ id: 'load_avg_high' });
if (err) return console.error(err);

console.log(data.alert);

createAlert

Create a new alert definition. See the create_alert API reference for all supported alert properties.

let { err, data } = await api.createAlert({
	title: 'High CPU Load',
	expression: 'monitors.load_avg >= (cpu.cores + 1)',
	message: 'CPU load average is too high: {{float(monitors.load_avg)}}',
	monitor_id: 'load_avg',
	enabled: true,
	samples: 1
});
if (err) return console.error(err);

console.log(data.alert);

updateAlert

Update selected properties on an existing alert. The request is shallow-merged, so properties you omit are left unchanged. See the update_alert API reference for details.

let { err } = await api.updateAlert({
	id: 'load_avg_high',
	title: 'High CPU Load',
	expression: 'monitors.load_avg >= (cpu.cores + 1)'
});
if (err) return console.error(err);

testAlert

Test an alert expression and message against the current data from a server. See the test_alert API reference for response details.

let { err, data } = await api.testAlert({
	server: 'SERVER_ID',
	expression: 'monitors.load_avg >= (cpu.cores + 1)',
	message: 'CPU load average is too high: {{float(monitors.load_avg)}}'
});
if (err) return console.error(err);

console.log(data.result, data.message);

deleteAlert

Permanently delete an alert definition by its ID. See the delete_alert API reference for privilege requirements.

let { err } = await api.deleteAlert({ id: 'load_avg_high' });
if (err) return console.error(err);

Buckets

getBuckets

Fetch all storage bucket definitions. Bucket data and file lists are not included. See the get_buckets API reference for response details.

let { err, data } = await api.getBuckets();
if (err) return console.error(err);

console.log(data.rows);

getBucket

Fetch one bucket definition, including its user-defined data and file list. See the get_bucket API reference for response details.

let { err, data } = await api.getBucket({ id: 'BUCKET_ID' });
if (err) return console.error(err);

console.log(data.bucket, data.data, data.files);

createBucket

Create a new storage bucket, optionally with initial user-defined data. Files must be uploaded separately. See the create_bucket API reference for all supported bucket properties.

let { err, data } = await api.createBucket({
	title: 'Build Artifacts',
	enabled: true,
	data: {
		build: 42,
		status: 'ready'
	}
});
if (err) return console.error(err);

console.log(data.bucket);

updateBucket

Update selected properties on an existing bucket. The request is shallow-merged, so properties you omit are left unchanged. See the update_bucket API reference for details.

let { err } = await api.updateBucket({
	id: 'BUCKET_ID',
	title: 'Release Artifacts',
	notes: 'Files from production releases'
});
if (err) return console.error(err);

deleteBucket

Permanently delete a bucket and all of its data and files. See the delete_bucket API reference for privilege requirements.

let { err } = await api.deleteBucket({ id: 'BUCKET_ID' });
if (err) return console.error(err);

writeBucketData

Shallow-merge user-defined data into an existing bucket. Set fetch to true to return the complete merged data object. See the write_bucket_data API reference for details.

let { err, data } = await api.writeBucketData({
	id: 'BUCKET_ID',
	fetch: true,
	data: {
		build: 43,
		status: 'complete'
	}
});
if (err) return console.error(err);

console.log(data.data);

uploadBucketFiles

Upload one or more files into a bucket using a multipart request. Existing files with the same normalized filenames are replaced. See the upload_bucket_files API reference for details.

let { err } = await api.uploadBucketFiles(
	{ id: 'BUCKET_ID' },
	['report.csv', 'summary.txt']
);
if (err) return console.error(err);

deleteBucketFile

Permanently delete one file from a bucket using its normalized filename. See the delete_bucket_file API reference for details.

let { err } = await api.deleteBucketFile({
	id: 'BUCKET_ID',
	filename: 'report.csv'
});
if (err) return console.error(err);

emptyBucket

Permanently remove all files, all user-defined data, or both, while keeping the bucket itself. See the empty_bucket API reference for details.

let { err } = await api.emptyBucket({
	id: 'BUCKET_ID',
	files: true,
	data: true
});
if (err) return console.error(err);

Categories

getCategories

Fetch all category definitions. This call does not require any parameters. See the get_categories API reference for response details.

let { err, data } = await api.getCategories();
if (err) return console.error(err);

console.log(data.rows);

getCategory

Fetch one category definition by its ID. See the get_category API reference for parameter and response details.

let { err, data } = await api.getCategory({ id: 'general' });
if (err) return console.error(err);

console.log(data.category);

createCategory

Create a new category for organizing events. See the create_category API reference for all supported category properties.

let { err, data } = await api.createCategory({
	title: 'Maintenance',
	enabled: true,
	color: 'blue',
	notes: 'Scheduled maintenance events',
	limits: [],
	actions: []
});
if (err) return console.error(err);

console.log(data.category);

updateCategory

Update selected properties on an existing category. The request is shallow-merged, so properties you omit are left unchanged. See the update_category API reference for details.

let { err } = await api.updateCategory({
	id: 'general',
	title: 'General Jobs',
	color: 'blue'
});
if (err) return console.error(err);

deleteCategory

Permanently delete a category by its ID. xyOps refuses the deletion if any events are still assigned to the category. See the delete_category API reference for privilege requirements.

let { err } = await api.deleteCategory({ id: 'CATEGORY_ID' });
if (err) return console.error(err);

Channels

getChannels

Fetch all channel definitions. See the get_channels API reference for complete parameters, privileges, and response details.

let { err, data } = await api.getChannels();
if (err) return console.error(err);

console.log(data.rows);

getChannel

Fetch one channel definition by its ID. See the get_channel API reference for complete parameters, privileges, and response details.

let { err, data } = await api.getChannel({ id: 'sev1' });
if (err) return console.error(err);

console.log(data.channel);

createChannel

Create a new channel. See the create_channel API reference for complete parameters, privileges, and response details.

let { err, data } = await api.createChannel({ title: 'On Call', enabled: true, users: ['admin'] });
if (err) return console.error(err);

console.log(data.channel);

updateChannel

Update an existing channel. See the update_channel API reference for complete parameters, privileges, and response details.

let { err } = await api.updateChannel({ id: 'sev1', max_per_day: 5 });
if (err) return console.error(err);

deleteChannel

Permanently delete an existing channel. See the delete_channel API reference for complete parameters, privileges, and response details.

let { err } = await api.deleteChannel({ id: 'CHANNEL_ID' });
if (err) return console.error(err);

Events

getEvents

Fetch event definitions, optionally filtered by properties such as plugin or enabled state. See the get_events API reference for complete parameters, privileges, and response details.

let { err, data } = await api.getEvents({ enabled: true });
if (err) return console.error(err);

console.log(data.rows);

getEvent

Fetch one event definition by its ID. See the get_event API reference for complete parameters, privileges, and response details.

let { err, data } = await api.getEvent({ id: 'EVENT_ID' });
if (err) return console.error(err);

console.log(data.event);

getEventHistory

Fetch the revision history for an event. See the get_event_history API reference for complete parameters, privileges, and response details.

let { err, data } = await api.getEventHistory({ id: 'EVENT_ID', limit: 20 });
if (err) return console.error(err);

console.log(data.rows);

createEvent

Create a new event. See the create_event API reference for complete parameters, privileges, and response details.

let { err, data } = await api.createEvent({
	title: 'Nightly Task',
	enabled: true,
	category: 'general',
	targets: ['main'],
	algo: 'random',
	plugin: 'shellplug',
	params: {
		script: "#!/bin/bash\n\necho 'Hi'\n"
	}
});
if (err) return console.error(err);

console.log(data.event);

updateEvent

Update an existing event. See the update_event API reference for complete parameters, privileges, and response details.

let { err } = await api.updateEvent({ id: 'EVENT_ID', enabled: false });
if (err) return console.error(err);

deleteEvent

Permanently delete an existing event. See the delete_event API reference for complete parameters, privileges, and response details.

let { err } = await api.deleteEvent({ id: 'EVENT_ID' });
if (err) return console.error(err);

runEvent

Run an event on demand with optional parameter overrides. See the run_event API reference for complete parameters, privileges, and response details.

let { err, data } = await api.runEvent({ id: 'EVENT_ID', params: { mode: 'full' } });
if (err) return console.error(err);

console.log(data);

Files

uploadFiles

Upload one or more general-purpose files for the user (API key in this case). See the upload_files API reference for complete parameters, privileges, and response details.

let { err, data } = await api.uploadFiles({}, ['report.csv']);
if (err) return console.error(err);

console.log(data);

deleteJobFile

Delete a file attached to a job. See the delete_job_file API reference for complete parameters, privileges, and response details.

let { err } = await api.deleteJobFile({ id: 'JOB_ID', path: 'files/jobs/JOB_ID/.../report.csv' });
if (err) return console.error(err);

Groups

getGroups

Fetch all server group definitions. See the get_groups API reference for complete parameters, privileges, and response details.

let { err, data } = await api.getGroups();
if (err) return console.error(err);

console.log(data.rows);

getGroup

Fetch one server group definition by its ID. See the get_group API reference for complete parameters, privileges, and response details.

let { err, data } = await api.getGroup({ id: 'main' });
if (err) return console.error(err);

console.log(data.group);

createGroup

Create a new group. See the create_group API reference for complete parameters, privileges, and response details.

let { err, data } = await api.createGroup({ title: 'Linux Servers', hostname_match: '^linux-' });
if (err) return console.error(err);

console.log(data.group);

updateGroup

Update an existing group. See the update_group API reference for complete parameters, privileges, and response details.

let { err } = await api.updateGroup({ id: 'main', title: 'Production' });
if (err) return console.error(err);

deleteGroup

Permanently delete an existing server group. See the delete_group API reference for complete parameters, privileges, and response details.

let { err } = await api.deleteGroup({ id: 'GROUP_ID' });
if (err) return console.error(err);

watchGroup

Start or stop automatic snapshots for a server group. See the watch_group API reference for complete parameters, privileges, and response details.

let { err } = await api.watchGroup({ id: 'main', duration: 3600 });
if (err) return console.error(err);

createGroupSnapshot

Create a snapshot containing the latest data for a server group. See the create_group_snapshot API reference for complete parameters, privileges, and response details.

let { err, data } = await api.createGroupSnapshot({ group: 'main' });
if (err) return console.error(err);

console.log(data);

Jobs

getActiveJobs

Fetch active jobs. See the get_active_jobs API reference for complete parameters, privileges, and response details.

let { err, data } = await api.getActiveJobs({ limit: 50 });
if (err) return console.error(err);

console.log(data.rows);

getActiveJobSummary

Fetch active job summary. See the get_active_job_summary API reference for complete parameters, privileges, and response details.

let { err, data } = await api.getActiveJobSummary();
if (err) return console.error(err);

console.log(data.events);

getWorkflowJobSummary

Fetch workflow job summary. See the get_workflow_job_summary API reference for complete parameters, privileges, and response details.

let { err, data } = await api.getWorkflowJobSummary({ 'workflow.job': 'JOB_ID' });
if (err) return console.error(err);

console.log(data.nodes);

getJob

Fetch job data for a specific job, which may be running or completed. See the get_job API reference for complete parameters, privileges, and response details.

let { err, data } = await api.getJob({ id: 'JOB_ID' });
if (err) return console.error(err);

console.log(data.job);

getJobs

Fetch multiple jobs by their IDs. See the get_jobs API reference for complete parameters, privileges, and response details.

let { err, data } = await api.getJobs({ ids: ['JOB_ID_1', 'JOB_ID_2'] });
if (err) return console.error(err);

console.log(data.jobs);

getJobLog

Download a job log to a local file. See the get_job_log API reference for complete parameters, privileges, and response details.

let { err } = await api.getJobLog({ id: 'JOB_ID' }, { download: 'job.log' });
if (err) return console.error(err);

streamJob

Receive live job updates over Server-Sent Events. See the stream_job API reference for complete parameters, privileges, and response details.

let { err } = await api.streamJob({ id: 'JOB_ID' }, data => console.log(data));
if (err) return console.error(err);

updateActiveJob

Update a live job while it is owned by the conductor. Standard jobs can only be updated before dispatch to xySat, while top-level workflow jobs can be updated as their sub-jobs run. The changes are saved with the completed job, but do not modify the source event. See the update_active_job API reference for complete field restrictions, privileges, and workflow validation details.

let { err } = await api.updateActiveJob({
	id: 'JOB_ID',
	title: 'Updated Before Dispatch',
	targets: ['production']
});
if (err) return console.error(err);

updateJob

Update an existing job (administrator only). See the update_job API reference for complete parameters, privileges, and response details.

let { err } = await api.updateJob({ id: 'JOB_ID', label: 'Corrected Label' });
if (err) return console.error(err);

resumeJob

Resume a suspended active job with optional parameters. See the resume_job API reference for complete parameters, privileges, and response details.

let { err } = await api.resumeJob({ id: 'JOB_ID', params: { approved: true } });
if (err) return console.error(err);

jobSkipDelay

Skip the current delay period for an active job. See the job_skip_delay API reference for complete parameters, privileges, and response details.

let { err } = await api.jobSkipDelay({ id: 'JOB_ID' });
if (err) return console.error(err);

manageJobTags

Replace the tags on a completed job. See the manage_job_tags API reference for complete parameters, privileges, and response details.

let { err } = await api.manageJobTags({ id: 'JOB_ID', tags: ['important'] });
if (err) return console.error(err);

manageJobTickets

Replace the ticket associations on a completed job. The tickets array is a complete replacement, so include every ticket that should remain attached. See the manage_job_tickets API reference for complete parameters, privileges, and response details.

let { err } = await api.manageJobTickets({ id: 'JOB_ID', tickets: ['TICKET_ID'] });
if (err) return console.error(err);

abortJob

Abort a running job. See the abort_job API reference for complete parameters, privileges, and response details.

let { err } = await api.abortJob({ id: 'JOB_ID' });
if (err) return console.error(err);

deleteJob

Permanently delete an existing completed job, including its log and files. See the delete_job API reference for complete parameters, privileges, and response details.

let { err } = await api.deleteJob({ id: 'JOB_ID' });
if (err) return console.error(err);

flushEventQueue

Remove all queued jobs for an event. See the flush_event_queue API reference for complete parameters, privileges, and response details.

let { err } = await api.flushEventQueue({ id: 'EVENT_ID' });
if (err) return console.error(err);

Monitors

getMonitors

Fetch all monitor definitions. See the get_monitors API reference for complete parameters, privileges, and response details.

let { err, data } = await api.getMonitors();
if (err) return console.error(err);

console.log(data.rows);

getMonitor

Fetch one monitor definition by its ID. See the get_monitor API reference for complete parameters, privileges, and response details.

let { err, data } = await api.getMonitor({ id: 'cpu_usage' });
if (err) return console.error(err);

console.log(data.monitor);

createMonitor

Create a new monitor. See the create_monitor API reference for complete parameters, privileges, and response details.

let { err, data } = await api.createMonitor({ 
	title: 'CPU Usage', 
	source: 'cpu.currentLoad', 
	data_type: 'float' 
});
if (err) return console.error(err);

console.log(data.monitor);

updateMonitor

Update an existing monitor. See the update_monitor API reference for complete parameters, privileges, and response details.

let { err } = await api.updateMonitor({ id: 'cpu_usage', display: true });
if (err) return console.error(err);

testMonitor

Test a monitor configuration against current data from a server. See the test_monitor API reference for complete parameters, privileges, and response details.

let { err, data } = await api.testMonitor({ server: 'SERVER_ID', source: 'cpu.currentLoad', data_type: 'float' });
if (err) return console.error(err);

console.log(data);

deleteMonitor

Permanently delete an existing monitor. See the delete_monitor API reference for complete parameters, privileges, and response details.

let { err } = await api.deleteMonitor({ id: 'MONITOR_ID' });
if (err) return console.error(err);

getQuickmonData

Fetch the latest QuickMon samples for one or more servers (last 60 seconds of real-time data). See the get_quickmon_data API reference for complete parameters, privileges, and response details.

let { err, data } = await api.getQuickmonData({ server: 'SERVER_ID' });
if (err) return console.error(err);

console.log(data.servers);

getLatestMonitorData

Fetch the latest monitoring timeline entries for a server. See the get_latest_monitor_data API reference for complete parameters, privileges, and response details.

let { err, data } = await api.getLatestMonitorData({ server: 'SERVER_ID', sys: 'hourly', limit: 24 });
if (err) return console.error(err);

console.log(data.rows);

getHistoricalMonitorData

Fetch historical monitoring timeline entries for a server. See the get_historical_monitor_data API reference for complete parameters, privileges, and response details.

let { err, data } = await api.getHistoricalMonitorData({
	server: 'SERVER_ID',
	sys: 'hourly',
	date: 1783873778,
	limit: 24
});
if (err) return console.error(err);

console.log(data.rows);

Plugins

getPlugins

Fetch all plugins. See the get_plugins API reference for complete parameters, privileges, and response details.

let { err, data } = await api.getPlugins();
if (err) return console.error(err);

console.log(data.rows);

getPlugin

Fetch a single plugin by its ID. See the get_plugin API reference for complete parameters, privileges, and response details.

let { err, data } = await api.getPlugin({ id: 'shellplug' });
if (err) return console.error(err);

console.log(data.plugin);

createPlugin

Create a new plugin. See the create_plugin API reference for complete parameters, privileges, and response details.

let { err, data } = await api.createPlugin({
	title: 'Custom Runner',
	type: 'event',
	command: 'node plugin.js',
	enabled: true
});
if (err) return console.error(err);

console.log(data.plugin);

updatePlugin

Update an existing plugin. See the update_plugin API reference for complete parameters, privileges, and response details.

let { err } = await api.updatePlugin({ id: 'PLUGIN_ID', enabled: false });
if (err) return console.error(err);

deletePlugin

Permanently delete an existing plugin. See the delete_plugin API reference for complete parameters, privileges, and response details.

let { err } = await api.deletePlugin({ id: 'PLUGIN_ID' });
if (err) return console.error(err);

Roles

getRoles

Fetch all user roles. See the get_roles API reference for complete parameters, privileges, and response details.

let { err, data } = await api.getRoles();
if (err) return console.error(err);

console.log(data.rows);

getRole

Fetch single user role by its ID. See the get_role API reference for complete parameters, privileges, and response details.

let { err, data } = await api.getRole({ id: 'all' });
if (err) return console.error(err);

console.log(data.role);

createRole

Create a new role. See the create_role API reference for complete parameters, privileges, and response details.

let { err, data } = await api.createRole({ title: 'Operators', enabled: true, privileges: { run_jobs: true } });
if (err) return console.error(err);

console.log(data.role);

updateRole

Update an existing role. See the update_role API reference for complete parameters, privileges, and response details.

let { err } = await api.updateRole({ id: 'ROLE_ID', enabled: false });
if (err) return console.error(err);

deleteRole

Permanently delete an existing role. See the delete_role API reference for complete parameters, privileges, and response details.

let { err } = await api.deleteRole({ id: 'ROLE_ID' });
if (err) return console.error(err);

Search

searchJobs

Search completed jobs with custom criteria. See the search_jobs API reference for complete parameters, privileges, and response details.

let { err, data } = await api.searchJobs({ query: 'tags:_error', limit: 50 });
if (err) return console.error(err);

console.log(data.rows);

searchServers

Search servers with custom criteria. See the search_servers API reference for complete parameters, privileges, and response details.

let { err, data } = await api.searchServers({ query: 'os_platform:linux', limit: 50 });
if (err) return console.error(err);

console.log(data.rows);

searchAlerts

Search alerts with custom criteria. See the search_alerts API reference for complete parameters, privileges, and response details.

let { err, data } = await api.searchAlerts({ query: 'active:true', limit: 50 });
if (err) return console.error(err);

console.log(data.rows);

searchSnapshots

Search snapshots with custom criteria. See the search_snapshots API reference for complete parameters, privileges, and response details.

let { err, data } = await api.searchSnapshots({ query: 'source:alert', limit: 50 });
if (err) return console.error(err);

console.log(data.rows);

searchTickets

Search tickets with custom criteria. See the search_tickets API reference for complete parameters, privileges, and response details.

let { err, data } = await api.searchTickets({ query: 'status:open', limit: 50 });
if (err) return console.error(err);

console.log(data.rows);

searchActivity

Search activity with custom criteria. See the search_activity API reference for complete parameters, privileges, and response details.

let { err, data } = await api.searchActivity({ query: 'action:job_error', limit: 50 });
if (err) return console.error(err);

console.log(data.rows);

searchRevisionHistory

Search revision history. See the search_revision_history API reference for complete parameters, privileges, and response details.

let { err, data } = await api.searchRevisionHistory({ type: 'events', limit: 20 });
if (err) return console.error(err);

console.log(data.rows);

searchStatHistory

Fetch daily snapshots from the system statistics history. See the search_stat_history API reference for complete parameters, privileges, and response details.

let { err, data } = await api.searchStatHistory({ limit: 30, current_day: true });
if (err) return console.error(err);

console.log(data.items);

bulkSearchExport

Export search results to a local CSV, TSV, or NDJSON file. See the bulk_search_export API reference for complete parameters, privileges, and response details.

let { err } = await api.bulkSearchExport(
	{
		index: 'jobs',
		query: 'tags:_error',
		columns: ['id', 'event', 'category', 'plugin', 'completed', 'code'],
		sort_by: 'completed',
		sort_dir: -1,
		format: 'csv',
		compress: true
	},
	{ download: 'error-jobs.csv.gz' }
);
if (err) return console.error(err);

Marketplace

marketplace

Search the xyOps Marketplace or fetch supporting product information. See the marketplace API reference for complete parameters, privileges, and response details.

Search for products:

let { err, data } = await api.marketplace({ query: 'backup', limit: 20 });
if (err) return console.error(err);

console.log(data.rows);

Fetch the unique values available for Marketplace filters:

let { err, data } = await api.marketplace({ fields: true });
if (err) return console.error(err);

console.log(data.fields);

Fetch a product README in GitHub Flavored Markdown:

let { err, data } = await api.marketplace({
	id: 'pixlcore/xyplug-weather',
	readme: true
});
if (err) return console.error(err);

console.log(data.text);

Fetch a product's xyOps Portable Data file:

let { err, data } = await api.marketplace({
	id: 'pixlcore/xyplug-weather',
	data: true
});
if (err) return console.error(err);

console.log(data.data);

Secrets

getSecrets

Fetch all secret metadata (does not include encrypted variables). See the get_secrets API reference for complete parameters, privileges, and response details.

let { err, data } = await api.getSecrets();
if (err) return console.error(err);

console.log(data.rows);

getSecret

Fetch secret metadata for a single secret by its ID (does not include encrypted variables). See the get_secret API reference for complete parameters, privileges, and response details.

let { err, data } = await api.getSecret({ id: 'SECRET_ID' });
if (err) return console.error(err);

console.log(data.secret);

decryptSecret

Decrypt and return the variables stored in a secret. See the [decrypt_secret](https://docs.xyops.io/