DevelopersTypeScript SDK

Hostwolf SDK for JavaScript & TypeScript

@hostwolf/sdk is the official typed client for the Hostwolf API. With it you can control your game servers from code: power, console, files, backups, mods, players, schedules and more.

npm install https://game.hostwolf.net/dl/hostwolf-sdk-0.1.6.tgz

The SDK is served from hostwolf.net rather than the npm registry. The command above adds it to your package.json as "@hostwolf/sdk": "https://game.hostwolf.net/dl/hostwolf-sdk-0.1.6.tgz", and you import it as @hostwolf/sdk. pnpm, yarn and bun accept the same URL. Every release has its own URL; see Releases.

It works in Node 18+, Bun and Deno, and has no runtime dependencies. For the live console in Node below 22, also run npm install ws.

Quick start#

Create an API key at panel.hostwolf.net/account/api, then:

import { Hostwolf } from '@hostwolf/sdk';

const hw = new Hostwolf({ apiKey: process.env.HOSTWOLF_API_KEY! });

const { data: servers } = await hw.servers.list();
for (const s of servers) {
    const res = await hw.servers.resources(s.identifier);
    console.log(s.name, s.egg_name, res.current_state);
}

const id = servers[0].identifier;
await hw.servers.command(id, 'say Backup in 1 minute');
await hw.backups.create(id, { name: 'before-update' });
console.log(await hw.tail(id, { lines: 20 }));

Every server method takes the server's short identifier (the 8 characters in its panel URL) or its uuid as the first argument. Response objects use the API's own field names (snake_case). Their TypeScript types are exported, e.g. Server, Backup and FileObject.

Options#

new Hostwolf({
    apiKey: 'ptlc_...',                     // required
    baseUrl: 'https://panel.hostwolf.net',  // default
    timeoutMs: 30_000,                      // per request
    maxRetries: 2,                          // 429s, and 502/503/504 on GET
    maxRetryWaitMs: 10_000,                 // longer Retry-After waits fail fast instead
    fetch: customFetch,                     // optional
    WebSocket: customWebSocket,             // optional, for the console
});

Servers#

MethodWhat it does
servers.list({ page, per_page })A page of your servers: { data, pagination }
servers.listAll()Async iterator over every server
servers.get(id, ['egg', 'subusers'])Server details, with allocations and startup variables
servers.resources(id)Live state, CPU, memory, disk, network, uptime
servers.power(id, signal) / start / stop / restart / killPower actions
servers.command(id, command)Run a console command
servers.activity(id)Activity log (paginated)
servers.rename(id, name, description?)Rename
servers.reinstall(id)Re-run the install script
servers.setDockerImage(id, image)Switch the runtime image (e.g. Java version)

Console#

const c = await hw.console(id).connect();
c.on('output', (line) => console.log(line));
c.on('stats', (s) => console.log(s.state, s.memory_bytes));
c.requestLogs();          // replay recent output
c.sendCommand('list');
// later
c.close();

// Or just fetch the recent lines (ANSI colours stripped):
const lines = await hw.tail(id, { lines: 50 });

The console connects straight to the node running your server and refreshes its token automatically.

Events:

  • ready and close
  • output
  • status
  • stats
  • install output
  • daemon message and daemon error
  • error

Files#

await hw.files.list(id, '/plugins');
const props = await hw.files.read(id, 'server.properties');
await hw.files.write(id, 'server.properties', props.replace('pvp=true', 'pvp=false'));
await hw.files.rename(id, '/', [{ from: 'world', to: 'world-old' }]);
await hw.files.delete(id, '/logs', ['old.log']);
await hw.files.createFolder(id, '/', 'maps');
await hw.files.compress(id, '/', ['world']);       // returns the archive
await hw.files.decompress(id, '/', 'world.tar.gz');
await hw.files.pull(id, 'https://example.com/map.zip', { directory: '/maps' });
const url = await hw.files.downloadUrl(id, 'world.tar.gz');
const uploadUrl = await hw.files.uploadUrl(id);    // POST multipart "files" to `${uploadUrl}&directory=/maps`

Backups#

const { data } = await hw.backups.list(id);
const b = await hw.backups.create(id, { name: 'nightly', is_locked: false });
await hw.backups.restore(id, b.uuid, { truncate: false });
await hw.backups.toggleLock(id, b.uuid);
await hw.backups.downloadUrl(id, b.uuid);
await hw.backups.delete(id, b.uuid);
await hw.backups.setSmart(id, true);   // automatic backups before risky changes

Game, players and settings#

await hw.game.versions(id);                          // current + available versions
await hw.game.setVersion(id, '1.21.4');              // switches and reinstalls
await hw.game.settings(id);                          // friendly settings, grouped by file
await hw.game.updateSettings(id, { difficulty: 'hard' }, true);
await hw.game.diagnostics(id);                       // "Fix my server" checks

await hw.players.info(id);                           // online count (+ names on Minecraft)
await hw.players.list(id);                           // live list via RCON/query
await hw.players.kick(id, 'Steve');
await hw.players.ban(id, { steamid: '7656...' });
await hw.players.broadcast(id, 'Restarting in 5 minutes');

Mods, plugins and modpacks#

const profile = await hw.addons.profile(id);         // sources, install dir, frameworks
const { items } = await hw.addons.search(id, 'modrinth', 'worldedit');
await hw.addons.install(id, 'modrinth', items[0].id); // newest compatible version
const installed = await hw.addons.installed(id, { checkUpdates: true });
await hw.addons.uninstall(id, installed.addons[0].id);

const packs = await hw.modpacks.search(id, 'cobblemon');
await hw.modpacks.install(id, packs.items[0].id, { freshWorld: false });

Other addon calls:

  • addons.upload(id, blob, name)
  • addons.setFramework
  • addons.workshop / setWorkshop (Steam Workshop games)
  • addons.cs2Framework
  • modpacks.current / versions / remove

More#

NamespaceMethods
startupget(id), setVariable(id, key, value)
scheduleslist, get, create, update, execute, delete, createTask, updateTask, deleteTask
databaseslist(id, { includePassword }), create, rotatePassword, delete
networkallocations, createAllocation, setNotes, setPrimary, deleteAllocation
userslist, get, create(id, email, permissions), update, delete, permissions()
notificationsPer-server Discord alerts: get, update, test
domainCustom domain: get, check, set, remove
mcNetworkVelocity/BungeeCord networks: get, link, unlink, installFabricProxy
accountget, updateEmail, updatePassword, updateProfile, updateLanguage, activity, getNotifications, updateNotifications, apiKeys.*, sshKeys.*, setCurseforgeKey
storeRead-only: catalog(), orders(), billing()

Ordering, cancelling and paying for servers can only be done in the panel, so an API key can never spend money.

Pagination#

servers.list, backups.list and the activity methods return { data, pagination }. To walk through every server:

import { collect } from '@hostwolf/sdk';
const all = await collect(hw.servers.listAll());

Errors#

Failed calls throw a HostwolfError.

import { HostwolfError } from '@hostwolf/sdk';
try {
    await hw.game.setVersion(id, '1.16.5');
} catch (e) {
    if (e instanceof HostwolfError && e.code === 'downgrade_requires_reset') {
        // older versions can't load a newer world: retry with { resetWorld: true } or { force: true }
    }
}

It has these properties:

  • status: the HTTP status, or 0 for network errors and timeouts.
  • code: the error code.
  • retryAfter: on a 429, seconds until the action is allowed again. Short waits are retried for you; longer ones (like the 2-backups-per-10-minutes limit) fail at once with this set.
  • message: a readable description.
  • errors: the raw error list.
  • body: the response body.
  • Shortcut flags: isNotFound, isRateLimited and isValidation.

Raw requests#

If an endpoint has no wrapper yet, call it directly:

await hw.http.get(`/servers/${id}/players`);
await hw.http.post(`/servers/${id}/command`, { command: 'list' });

Paths are relative to /api/client, and responses are unwrapped the same way as the wrapped methods. See the API reference for every endpoint.

Releases#

FileUse
https://game.hostwolf.net/dl/hostwolf-sdk-<version>.tgzA fixed release. Use this in package.json.
https://game.hostwolf.net/dl/hostwolf-sdk.tgzAlways the newest release. Package managers cache by URL, so prefer versioned URLs.
https://game.hostwolf.net/dl/index.jsonCurrent versions, with SHA-256 and npm integrity hashes.

To upgrade, install the newer versioned URL.

License#

MIT

Stuck, or missing an endpoint? Tell us at game.hostwolf.net/contact or hostwolfsupport@gmail.com.