Authentication
Every SDK request must be authenticated using exactly one of two methods: an API token or a node ID.
API tokens
The simplest way to authenticate. Generate a token from the CLI or the CiderStack app, then pass it directly to the client.
Tokens are prefixed with csk_ and come in two permission levels:
| Permission | Can read | Can write (start/stop/create/delete) |
|---|---|---|
readOnly | Yes | No |
fullAccess | Yes | Yes |
Read-only tokens can list VMs, get node stats, view snapshots and templates — but cannot start, stop, create, or delete anything.
How to get a token
- CiderStack CLI:
cider fleet token generate --name "my-script" - CiderStack app: Settings > Fleet > API Tokens
- Programmatically: via the SDK (requires node ID auth — see below)
Using a token
// JavaScript
import { FleetClient } from "@ciderstack/fleet-sdk";
const client = new FleetClient({
host: "192.168.1.100",
apiToken: "csk_abc123...",
});# Python
from ciderstack import FleetClient
client = FleetClient("192.168.1.100", api_token="csk_abc123...")Node ID via pairing
For advanced use cases — or when you need to generate API tokens programmatically — you can pair the SDK with a Fleet node using a 6-digit code displayed in the CiderStack app UI.
The pairing process generates a P-256 (SECP256R1) ECDSA keypair and registers your SDK client as a trusted node in the fleet.
JavaScript
import { FleetClient } from "@ciderstack/fleet-sdk";
// One-time pairing
const creds = await FleetClient.pair(
"192.168.1.100", // Fleet node host
"123456", // 6-digit code from UI
"my-ci-script", // Display name (optional)
9473, // Port (optional, default 9473)
);
// creds contains:
// {
// nodeId: string, — your unique node ID (save this)
// privateKeyHex: string, — P-256 private key (hex)
// publicKeyHex: string, — P-256 public key (hex)
// responderNodeId: string, — Fleet node's ID
// responderName: string, — Fleet node's display name
// }
// Use the node ID for future connections
const client = new FleetClient({
host: "192.168.1.100",
nodeId: creds.nodeId,
});Python
from ciderstack import FleetClient
# One-time pairing (requires cryptography package)
creds = FleetClient.pair(
"192.168.1.100", # Fleet node host
"123456", # 6-digit code from UI
"my-ci-script", # Display name (optional)
9473, # Port (optional, default 9473)
)
# creds is a dict:
# {
# "node_id": str, — your unique node ID (save this)
# "private_key_hex": str, — P-256 private key (hex)
# "public_key_hex": str, — P-256 public key (hex)
# "responder_node_id": str, — Fleet node's ID
# "responder_name": str, — Fleet node's display name
# }
# Use the node ID for future connections
client = FleetClient("192.168.1.100", node_id=creds["node_id"])Note: Python pairing requires the
cryptographypackage. Install it withpip install ciderstack[pairing].
Generating tokens programmatically
Once paired via node ID, you can generate API tokens for simpler future authentication:
// JavaScript
const client = new FleetClient({ host: "192.168.1.100", nodeId: creds.nodeId });
const token = await client.generateAPIToken("ci-pipeline", "fullAccess");
console.log(token.token); // "csk_..." — save securely
console.log(token.id); // UUID for revoking later
// Now use the token directly
const tokenClient = new FleetClient({
host: "192.168.1.100",
apiToken: token.token,
});# Python
client = FleetClient("192.168.1.100", node_id=creds["node_id"])
token = client.generate_api_token("ci-pipeline", "fullAccess")
print(token.token) # "csk_..." — save securely
print(token.id) # UUID for revoking later
# Now use the token directly
token_client = FleetClient("192.168.1.100", api_token=token.token)Important: The full token string is only returned once at creation time. Store it securely. Token generation also requires node ID authentication — you cannot use an API token to create more tokens.
Managing tokens
// JavaScript — list all tokens (strings are redacted)
const tokens = await client.listAPITokens();
for (const t of tokens) {
console.log(`${t.name}: ${t.tokenPrefix}... (${t.permissions})`);
}
// Revoke a token
await client.revokeAPIToken(token.id);# Python — list all tokens (strings are redacted)
tokens = client.list_api_tokens()
for t in tokens:
print(f"{t.name}: {t.token_prefix}... ({t.permissions})")
# Revoke a token
client.revoke_api_token(token.id)See also
- JavaScript / TypeScript SDK — Full client reference
- Python SDK — Full client reference
- CLI Reference — Generate tokens from the terminal