A low-level, zero dependency Node.js client library for the HTTPS API of the Satisfactory Dedicated Server.
npm i @djwoodz/satisfactory-dedicated-server-https-api-client
// import module
const { APIClient } = require('@djwoodz/satisfactory-dedicated-server-https-api-client');
// create apiClient
const apiClient = new APIClient({
address: '127.0.0.1',
port: 7777,
https: {
request: {
rejectUnauthorized: false, // accepts any CA, not secure
},
},
});
// health check using await
const { data } = await apiClient.healthCheck();
console.log(data);
// health check using .then()
apiClient.healthCheck()
.then((data) => {
console.log(data);
});
Name | Type | Default | Description |
---|---|---|---|
address | string | '127.0.0.1' | The address of the Dedicated Server |
port | number | 7777 | The port number of the Dedicated Server |
https | object | { request: { timeout:30000 } } | Options for HTTPS functions |
authenticationToken | string | The authentication token to be set for requests |
These map to the 'API Functions' in the DedicatedServerAPIDocs.md
file (available under the 'CommunityResources' directory of the installed Satisfactory game):
The client also has several other functions:
Method Signature | Description |
---|---|
setAPIClientAuthenticationToken(authenticationToken: string) | Sets the API Client's authentication token |
(static) getAuthenticationTokenPrivilegeLevel(authenticationToken: string) → {PrivilegeLevel} | Parses a given authentication token and returns its privilege level |
(static) getCertificates(options?) → {Promise.<object>} | Retrieves the server and CA certificates from a remote server via HTTPS |
Privilege Level Enumeration representing different privilege levels granted by an authentication token.
Enumerator | Description |
---|---|
PrivilegeLevel.NotAuthenticated | Not authenticated |
PrivilegeLevel.Client | Authenticated with Client privileges |
PrivilegeLevel.Administrator | Authenticated with Admin privileges |
PrivilegeLevel.InitialAdmin | Authenticated as Initial Admin with privileges to claim the server |
PrivilegeLevel.APIToken | Authenticated as Third Party Application |
Status Code Enumeration representing different HTTP response codes.
Enumerator | Description |
---|---|
StatusCode.OK | Status Code for Ok 200 |
StatusCode.CREATED | Status Code for Created 201 |
StatusCode.ACCEPTED | Status Code for Accepted 202 |
StatusCode.NO_CONTENT | Status Code for No Content 204 |
StatusCode.BAD_REQUEST | Status Code for Bad Request 400 |
StatusCode.DENIED | Status Code for Denied 401 |
StatusCode.FORBIDDEN | Status Code for Forbidden 403 |
StatusCode.NOT_FOUND | Status Code for Not Found 404 |
StatusCode.UNSUPPORTED_MEDIA | Status Code for Unsupported Media 415 |
StatusCode.SERVER_ERROR | Status Code for Server Error 500 |
const { APIClient } = require('@djwoodz/satisfactory-dedicated-server-https-api-client');
const address = '127.0.0.1';
const port = 7777;
const main = async () => {
const apiClient = new APIClient({
address,
port,
https: {
request: {
rejectUnauthorized: false, // accepts any CA, not secure
},
},
});
console.log(await apiClient.healthCheck());
};
main();
const { APIClient } = require('@djwoodz/satisfactory-dedicated-server-https-api-client');
const address = '127.0.0.1';
const port = 7777;
const authenticationToken = 'some API token';
const main = async () => {
const apiClient = new APIClient({
address,
port,
authenticationToken,
https: {
request: {
rejectUnauthorized: false, // accepts any CA, not secure
},
},
});
console.log(await apiClient.queryServerState());
};
main();
const { APIClient, StatusCode } = require('@djwoodz/satisfactory-dedicated-server-https-api-client');
const address = '127.0.0.1';
const port = 7777;
const authenticationToken = 'some API token';
const main = async () => {
const apiClient = new APIClient({
address,
port,
authenticationToken,
https: {
request: {
rejectUnauthorized: false, // accepts any CA, not secure
},
},
});
const { status } = await apiClient.verifyAuthenticationToken();
if (status === StatusCode.NO_CONTENT) {
console.log('The authentication token is valid.');
} else {
console.error('The authentication token is invalid.');
}
};
main();
const { APIClient, StatusCode } = require('@djwoodz/satisfactory-dedicated-server-https-api-client');
const address = '127.0.0.1';
const port = 7777;
const main = async () => {
const apiClient = new APIClient({
address,
port,
https: {
request: {
rejectUnauthorized: false, // accepts any CA, not secure
},
},
});
// Client passwordless login (when Client password is not set)
const { status, data } = await apiClient.passwordlessLogin(PrivilegeLevel.Client);
if (status === StatusCode.OK && data?.authenticationToken) {
// update the API Client to use the authentication token
apiClient.setAPIClientAuthenticationToken(data.authenticationToken);
// check the authentication token is valid
if (apiClient.verifyAuthenticationToken(data.authenticationToken)) {
// perform operation permissable at Client privilege level
console.log(await apiClient.queryServerState());
}
}
};
main();
const { APIClient, StatusCode } = require('@djwoodz/satisfactory-dedicated-server-https-api-client');
const address = '127.0.0.1';
const port = 7777;
const main = async () => {
const apiClient = new APIClient({
address,
port,
https: {
request: {
rejectUnauthorized: false, // accepts any CA, not secure
},
},
});
// Client password login (when Client password is set)
const { status, data } = await apiClient.passwordLogin(PrivilegeLevel.Client, 'My Client Password');
if (status === StatusCode.OK && data?.authenticationToken) {
// update the API Client to use the authentication token
apiClient.setAPIClientAuthenticationToken(data.authenticationToken);
// check the authentication token is valid
if (apiClient.verifyAuthenticationToken(data.authenticationToken)) {
// perform operation permissable at Client privilege level
console.log(await apiClient.queryServerState());
}
}
};
main();
const { APIClient } = require('@djwoodz/satisfactory-dedicated-server-https-api-client');
const address = '127.0.0.1';
const port = 7777;
const authenticationToken = 'some API token';
const main = async () => {
const apiClient = new APIClient({
address,
port,
authenticationToken,
https: {
request: {
rejectUnauthorized: false, // accepts any CA, not secure
},
},
});
console.log(await apiClient.getServerOptions());
};
main();
const { APIClient } = require('@djwoodz/satisfactory-dedicated-server-https-api-client');
const address = '127.0.0.1';
const port = 7777;
const authenticationToken = 'some API token';
const main = async () => {
const apiClient = new APIClient({
address,
port,
authenticationToken,
https: {
request: {
rejectUnauthorized: false, // accepts any CA, not secure
},
},
});
console.log(await apiClient.getAdvancedGameSettings());
};
main();
const { APIClient } = require('@djwoodz/satisfactory-dedicated-server-https-api-client');
const address = '127.0.0.1';
const port = 7777;
const authenticationToken = 'some API token';
const main = async () => {
const apiClient = new APIClient({
address,
port,
authenticationToken,
https: {
request: {
rejectUnauthorized: false, // accepts any CA, not secure
},
},
});
console.log(await apiClient.applyAdvancedGameSettings({
'FG.PlayerRules.GodMode': true,
'FG.PlayerRules.FlightMode': true,
}));
};
main();
const { APIClient } = require('@djwoodz/satisfactory-dedicated-server-https-api-client');
const address = '127.0.0.1';
const port = 7777;
const authenticationToken = 'some API token';
const main = async () => {
const apiClient = new APIClient({
address,
port,
authenticationToken,
https: {
request: {
rejectUnauthorized: false, // accepts any CA, not secure
},
},
});
console.log(await apiClient.renameServer('My Server'));
};
main();
const { APIClient } = require('@djwoodz/satisfactory-dedicated-server-https-api-client');
const address = '127.0.0.1';
const port = 7777;
const authenticationToken = 'some API token';
const main = async () => {
const apiClient = new APIClient({
address,
port,
authenticationToken,
https: {
request: {
rejectUnauthorized: false, // accepts any CA, not secure
},
},
});
console.log(await apiClient.setClientPassword('My Client Password'));
};
main();
const { APIClient } = require('@djwoodz/satisfactory-dedicated-server-https-api-client');
const address = '127.0.0.1';
const port = 7777;
const authenticationToken = 'some API token';
const main = async () => {
const apiClient = new APIClient({
address,
port,
authenticationToken,
https: {
request: {
rejectUnauthorized: false, // accepts any CA, not secure
},
},
});
console.log(await apiClient.setAdminPassword('My Admin Password'));
};
main();
const { APIClient } = require('@djwoodz/satisfactory-dedicated-server-https-api-client');
const address = '127.0.0.1';
const port = 7777;
const authenticationToken = 'some API token';
const main = async () => {
const apiClient = new APIClient({
address,
port,
authenticationToken,
https: {
request: {
rejectUnauthorized: false, // accepts any CA, not secure
},
},
});
console.log(await apiClient.setAutoLoadSessionName('My Session'));
console.log((await apiClient.queryServerState()).data.serverGameState.autoLoadSessionName);
};
main();
const { APIClient } = require('@djwoodz/satisfactory-dedicated-server-https-api-client');
const address = '127.0.0.1';
const port = 7777;
const authenticationToken = 'some API token';
const main = async () => {
const apiClient = new APIClient({
address,
port,
authenticationToken,
https: {
request: {
rejectUnauthorized: false, // accepts any CA, not secure
},
},
});
console.log(await apiClient.runCommand('FG.NetworkQuality'));
};
main();
const { APIClient } = require('@djwoodz/satisfactory-dedicated-server-https-api-client');
const address = '127.0.0.1';
const port = 7777;
const authenticationToken = 'some API token';
const main = async () => {
const apiClient = new APIClient({
address,
port,
authenticationToken,
https: {
request: {
rejectUnauthorized: false, // accepts any CA, not secure
},
},
});
console.log(await apiClient.shutdown());
};
main();
const { APIClient } = require('@djwoodz/satisfactory-dedicated-server-https-api-client');
const address = '127.0.0.1';
const port = 7777;
const authenticationToken = 'some API token';
const main = async () => {
const apiClient = new APIClient({
address,
port,
authenticationToken,
https: {
request: {
rejectUnauthorized: false, // accepts any CA, not secure
},
},
});
console.log(await apiClient.applyServerOptions({ 'FG.AutosaveInterval': '600' }));
};
main();
const { APIClient } = require('@djwoodz/satisfactory-dedicated-server-https-api-client');
const address = '127.0.0.1';
const port = 7777;
const authenticationToken = 'some API token';
const main = async () => {
const apiClient = new APIClient({
address,
port,
authenticationToken,
https: {
request: {
rejectUnauthorized: false, // accepts any CA, not secure
},
},
});
console.log(await apiClient.createNewGame({
SessionName: 'My Session',
}));
};
main();
const { APIClient } = require('@djwoodz/satisfactory-dedicated-server-https-api-client');
const address = '127.0.0.1';
const port = 7777;
const authenticationToken = 'some API token';
const main = async () => {
const apiClient = new APIClient({
address,
port,
authenticationToken,
https: {
request: {
rejectUnauthorized: false, // accepts any CA, not secure
},
},
});
console.log(await apiClient.saveGame('My Save'));
};
main();
const { APIClient } = require('@djwoodz/satisfactory-dedicated-server-https-api-client');
const address = '127.0.0.1';
const port = 7777;
const authenticationToken = 'some API token';
const main = async () => {
const apiClient = new APIClient({
address,
port,
authenticationToken,
https: {
request: {
rejectUnauthorized: false, // accepts any CA, not secure
},
},
});
console.log(await apiClient.deleteSaveFile('My Save'));
};
main();
const { APIClient } = require('@djwoodz/satisfactory-dedicated-server-https-api-client');
const address = '127.0.0.1';
const port = 7777;
const authenticationToken = 'some API token';
const main = async () => {
const apiClient = new APIClient({
address,
port,
authenticationToken,
https: {
request: {
rejectUnauthorized: false, // accepts any CA, not secure
},
},
});
console.log(await apiClient.deleteSaveSession('My Session'));
};
main();
Here is an example of how you can iterate all save names against all sessions:
const { APIClient } = require('@djwoodz/satisfactory-dedicated-server-https-api-client');
const address = '127.0.0.1';
const port = 7777;
const authenticationToken = 'some API token';
const main = async () => {
const apiClient = new APIClient({
address,
port,
authenticationToken,
https: {
request: {
rejectUnauthorized: false, // accepts any CA, not secure
},
},
});
const { data } = await apiClient.enumerateSessions();
const { currentSessionIndex } = data;
data.sessions.forEach((session, index) => {
console.log(`Session: ${session.sessionName}${(index === currentSessionIndex ? ' (Current)' : '')}`);
session.saveHeaders.forEach(({ saveName }) => {
console.log(` Save Name: ${saveName}`);
});
});
};
main();
Example output:
Session: My Session (Current)
Save Name: My Save
const { APIClient } = require('@djwoodz/satisfactory-dedicated-server-https-api-client');
const address = '127.0.0.1';
const port = 7777;
const authenticationToken = 'some API token';
const main = async () => {
const apiClient = new APIClient({
address,
port,
authenticationToken,
https: {
request: {
rejectUnauthorized: false, // accepts any CA, not secure
},
},
});
console.log(await apiClient.loadGame('My Save'));
};
main();
const fs = require('fs');
const { APIClient } = require('@djwoodz/satisfactory-dedicated-server-https-api-client');
const address = '127.0.0.1';
const port = 7777;
const authenticationToken = 'some API token';
const main = async () => {
const apiClient = new APIClient({
address,
port,
authenticationToken,
https: {
request: {
rejectUnauthorized: false, // accepts any CA, not secure
},
},
});
try {
const buffer = fs.readFileSync('My Save 1.sav');
console.log(await apiClient.uploadSaveGame(buffer, 'My Save 1', true));
} catch (error) {
console.error('Error reading the file:', error);
}
};
main();
const fs = require('fs');
const { APIClient } = require('@djwoodz/satisfactory-dedicated-server-https-api-client');
const address = '127.0.0.1';
const port = 7777;
const authenticationToken = 'some API token';
const main = async () => {
const apiClient = new APIClient({
address,
port,
authenticationToken,
https: {
request: {
rejectUnauthorized: false, // accepts any CA, not secure
},
},
});
try {
const buffer = await apiClient.downloadSaveGame('My Save 2');
fs.writeFileSync('My Save 2.sav', buffer);
console.log('Buffer written to file successfully!');
} catch (error) {
console.error('Error writing to file', error);
}
};
main();
const { APIClient } = require('@djwoodz/satisfactory-dedicated-server-https-api-client');
const address = '127.0.0.1';
const port = 7777;
const authenticationToken = 'some API token';
const main = async () => {
const apiClient = new APIClient({
address,
port,
authenticationToken,
https: {
request: {
rejectUnauthorized: false, // accepts any CA, not secure
},
},
});
apiClient.setAPIClientAuthenticationToken('some other token');
};
main();
const { APIClient } = require('@djwoodz/satisfactory-dedicated-server-https-api-client');
console.log(APIClient.getAuthenticationTokenPrivilegeLevel('some API token'));
Here is an example of how to claim a new server (set server name and admin password), set the client password and generate an API Token:
const { APIClient, StatusCode, PrivilegeLevel } = require('@djwoodz/satisfactory-dedicated-server-https-api-client');
const address = '127.0.0.1';
const port = 7777;
const serverName = 'My Server';
const adminPassword = 'My Admin Password';
const clientPassword = 'My Client Password';
const main = async () => {
const apiClient = new APIClient({
address,
port,
https: {
request: {
rejectUnauthorized: false, // accepts any CA, not secure
},
},
});
try {
// passwordless login
{
const {
status,
data,
} = await apiClient.passwordlessLogin(PrivilegeLevel.InitialAdmin);
// check passwordlessLogin returned the 'Ok' status code
if (status === StatusCode.OK) {
// get the initial authentication token
const authenticationToken = data?.authenticationToken;
if (authenticationToken) {
// check the token is an InitialAdmin token
const privilegeLevel = APIClient.getAuthenticationTokenPrivilegeLevel(authenticationToken);
if (privilegeLevel === PrivilegeLevel.InitialAdmin) {
console.log(`${PrivilegeLevel.InitialAdmin} token obtained.`);
// update the API Client to use the InitialAdmin authentication token
apiClient.setAPIClientAuthenticationToken(authenticationToken);
} else {
throw new Error(`authentication token was not ${PrivilegeLevel.InitialAdmin}: ${privilegeLevel}.`);
}
} else {
throw new Error('passwordlessLogin did not return an authentication token.');
}
} else {
throw new Error(`passwordlessLogin status code was: ${status?.code}.`);
}
}
// claim the server
{
const {
status,
data,
} = await apiClient.claimServer(serverName, adminPassword);
// check claimServer returned the 'Ok' status code
if (status === StatusCode.OK) {
// get the authentication token
const authenticationToken = data?.authenticationToken;
if (authenticationToken) {
// check the token is an Administrator token
const privilegeLevel = APIClient.getAuthenticationTokenPrivilegeLevel(authenticationToken);
if (privilegeLevel === PrivilegeLevel.Administrator) {
console.log(`Server claimed (named and admin password set). ${PrivilegeLevel.Administrator} token obtained.`);
// update the API Client to use the Administrator authentication token
apiClient.setAPIClientAuthenticationToken(authenticationToken);
} else {
throw new Error(`authentication token was not ${PrivilegeLevel.Administrator}: ${privilegeLevel}.`);
}
} else {
throw new Error('claimServer did not return an authentication token.');
}
} else {
throw new Error(`claimServer status code was: ${status?.code}.`);
}
}
// set the client password
{
const {
status,
} = await apiClient.setClientPassword(clientPassword);
// check setClientPassword returned the 'No Content' status code
if (status === StatusCode.NO_CONTENT) {
console.log('Client password set.');
} else {
throw new Error('Client password was not set.');
}
}
// generate API token
{
const {
status,
data,
} = await apiClient.runCommand('server.GenerateAPIToken');
// check runCommand returned the 'Ok' status code and had a result
if (status === StatusCode.OK && data?.commandResult) {
console.log(`server.GenerateAPIToken command result: ${data?.commandResult}`);
} else {
throw new Error('server.GenerateAPIToken command failed');
}
}
} catch (error) {
console.error(`An error occurred: ${error.message}`);
}
};
main();
APIClient.getCertificates()
is a static utility function that can obtain the certificate(s) from the server.
Here is an example of how you might use it:
const fs = require('fs');
const { APIClient } = require('@djwoodz/satisfactory-dedicated-server-https-api-client');
const address = '127.0.0.1';
const port = 7777;
const main = async () => {
const { server, ca } = await APIClient.getCertificates({
address,
port,
https: {
request: {
rejectUnauthorized: false, // accepts any CA, not secure
},
},
});
if (server?.pem) {
try {
console.log(`Server cert fingerprint512: ${server.cert?.fingerprint512}`);
fs.writeFileSync('serverCert.pem', server.pem);
console.log('Written server certificate to file successfully!');
} catch (error) {
console.error('Error writing to file', error);
}
}
if (ca?.pem) {
try {
console.log(`CA cert fingerprint512: ${ca.cert?.fingerprint512}`);
fs.writeFileSync('caCert.pem', ca.pem);
console.log('Written CA certificate to file successfully!');
} catch (error) {
console.error('Error writing to file', error);
}
}
};
main();
Then, instead of setting rejectUnauthorized: false
, you can use the results from getCertificates()
with the ca
and checkServerIdentity
options when creating a new APIClient
. The latter is handy for Dedicated Servers that use self-signed certificates.
For example, you can check the host and certificate fingerprint like this:
const fs = require('fs');
const { APIClient } = require('@djwoodz/satisfactory-dedicated-server-https-api-client');
const address = '127.0.0.1';
const port = 7777;
const fingerprint512 = 'some fingerprint';
const ca = fs.readFileSync('serverCert.pem');
const checkServerIdentity = (host, cert) => {
if (host !== address || cert?.fingerprint512 !== fingerprint512) {
throw new Error('Server identity check failed');
}
};
const main = async () => {
const apiClient = new APIClient({
address,
port,
https: {
request: {
ca,
checkServerIdentity,
},
},
});
console.log(await apiClient.healthCheck());
};
main();