Skip to main content

sstudio TypeScript SDK

Async TypeScript client and command-line interface for model lifecycle APIs.

Requirements​

  • Node.js 18+
  • An API key
  • An API base URL

Installation​

npm install sstudio

Install the CLI globally when needed:

npm install --global sstudio

Quick Start​

import { SmartStudioClient } from "sstudio";

const client = new SmartStudioClient({
apiKey: process.env.SSTUDIO_PLATFORM__API_KEY!,
baseUrl: process.env.SSTUDIO_PLATFORM__API_ENDPOINT!,
});

try {
const me = await client.me();
const models = await client.models.list({ page: 1, pageSize: 20 });
console.log(me);
console.log(models);
} finally {
client.close();
}

Authentication​

Only the API key and API base URL are required. The SDK manages the two-step authentication flow internally:

StepBehavior
LoginExchanges the API key for a short-lived bearer token.
RequestsAdds the bearer token to authenticated API requests.
RefreshRefreshes authentication and retries a safe request once after a 401.

The API key is never sent to pre-signed object storage URLs.

Client Configuration​

const client = new SmartStudioClient({
apiKey: process.env.SSTUDIO_PLATFORM__API_KEY!,
baseUrl: process.env.SSTUDIO_PLATFORM__API_ENDPOINT!,
timeout: 30,
maxRetries: 2,
defaultHeaders: { "X-Request-Source": "integration" },
});

The optional onTokenRefresh callback is intended for a host application that already has an approved secret store. It is omitted here so the example is runnable and does not encourage saving bearer tokens to ordinary files.

OptionRequiredDescription
apiKeyYesAPI key exchanged for a bearer token.
baseUrlYes*API origin or console URL. May be supplied by environment variable.
tokenNoExisting bearer token managed by the host application.
timeoutNoRequest timeout in seconds. Default: 30.
maxRetriesNoSafe-request retry count. Default: 2.
defaultHeadersNoAdditional string headers for API requests.
onTokenRefreshNoCallback invoked when a new bearer token is issued. Store it only in an approved secret store; never log it.
fetchImplNoCustom Fetch implementation for the host runtime.

baseUrl can also be configured with:

export SSTUDIO_PLATFORM__API_ENDPOINT="https://your-host.example"
export SSTUDIO_PLATFORM__API_KEY="your-api-key"

The CLI additionally accepts SSTUDIO_PLATFORM__API_KEY. Constructor options take precedence, and the SDK has no implicit network endpoint. An environment origin, a /msp-console URL, and an explicit /msp-api URL are all normalized to the same API base path.

Return Values and Errors​

Resource methods return the response envelope's data value:

{
"code": 200,
"message": "success",
"data": {"id": 42, "status": "RUNNING"}
}

For this response, await client.deployments.get(42) returns the object inside data. Methods without a result return null; text endpoints such as client.deployments.yaml(42) return string. Use client.request(...) only when the complete envelope is required.

import {
APIError,
AuthenticationError,
ValidationError,
} from "sstudio";

try {
const deployment = await client.deployments.get(42);
} catch (error) {
if (error instanceof AuthenticationError) {
console.error("The API key or session is invalid");
} else if (error instanceof ValidationError) {
console.error(error.errorCode, error.details);
} else if (error instanceof APIError) {
console.error(error.message);
}
}

API exceptions preserve code, message, errorCode, and details when provided by the server.

Module Overview​

ModuleAccessorTypical operations
Identityclient.me()Current authenticated user
Clustersclient.clustersCluster list, capacity, history, resource holds
Modelsclient.modelsModel catalog and deployment capabilities
My Modelsclient.myModelsEnd-to-end model upload and asset lifecycle
Datasetsclient.datasetsEnd-to-end upload, list, preview, download, lifecycle
AI Datasetclient.datasets.preparationsPreparation, labeling, resource preview, download
Deploymentsclient.deploymentsPreflight, create, lifecycle, events, YAML
Trainingclient.trainingPreflight, create, wait, cancel, artifacts
Evaluationsclient.evaluationsPreflight, create, wait, reports, artifacts
Jobsclient.jobsGeneric job status, logs, wait, cancel
API Keysclient.keysPlatform API key lifecycle
Provider Keysclient.providerKeysBYOK provider credentials and connectivity tests
Usageclient.usageUsage records, summaries, trends
Observabilityclient.observabilityCluster, service, and workload metrics

Use the API Map to move between the Python, TypeScript, and CLI references.

Module Examples​

The following examples assume an initialized client.

Identity​

const me = await client.me();

Clusters​

const clusters = await client.clusters.list();
const capacity = await client.clusters.capacity(1);
const history = await client.clusters.timeseries(1, { limit: 60 });
const holds = await client.clusters.holds({ clusterId: 1 });

Models​

const models = await client.models.list({ keyword: "Qwen", page: 1, pageSize: 20 });
const model = await client.models.get("qwen3-4b");
const capabilities = await client.models.deploymentCapabilities(
"qwen3-4b",
{ clusterId: "1" },
);

My Models​

upload(...) validates model files, hashes the directory, transfers objects, completes the upload, and returns the registered model asset.

const model = await client.myModels.upload<{ id: number }>("./model", {
name: "example-model",
modelType: "LLM",
});

const page = await client.myModels.list({ page: 1, pageSize: 20 });
const detail = await client.myModels.get(model.id);
await client.myModels.update(model.id, { description: "production candidate" });

Datasets​

const dataset = await client.datasets.upload<{ id: number }>("./train.jsonl", {
name: "example-training-dataset",
datasetType: "training",
trainingCategory: "sft-llm",
});

const preview = await client.datasets.preview(dataset.id, { limit: 20 });
const page = await client.datasets.list({ pageNum: 1, pageSize: 20 });
const download = await client.datasets.downloadUrl({
datasetId: dataset.id,
fileIndex: 0,
});

AI Dataset Preparations​

const clusters = await client.datasets.preparations.clusterOptions();
const providerKeys = await client.datasets.preparations.availableProviderKeys();
const tasks = await client.datasets.preparations.list({ pageNum: 1, pageSize: 20 });
const task = await client.datasets.preparations.get({ id: 123 });

Create and action payloads are passed as objects matching the API contract:

const preview = await client.datasets.preparations.preview(resourcePreviewRequest);
const task = await client.datasets.preparations.create<{ id: number }>(preparationRequest);
await client.datasets.preparations.generateRules({ id: task.id });
const rulesReady = await client.waitForDatasetPreparation(task.id, {
until: "rules_ready",
});
await client.datasets.preparations.startLabeling(labelingRequest);
const completed = await client.waitForDatasetPreparation(task.id);

Deployments​

The workflow automatically selects the Model Profile or model-asset creation route from the request's model reference.

const request = {
name: "example-deployment",
modelSource: "gallery",
modelName: "Qwen3-4B-Instruct-2507-FAST",
backend: "sglang",
servingMode: "standard",
gpuType: "L20",
replicas: 1,
clusterId: 1,
};

const preview = await client.deployments.preview<{ creatable?: boolean }>(request);
if (preview.creatable) {
const deployment = await client.deployments.create<{ id: number }>(request);
const running = await client.waitForDeployment(deployment.id);
}

Lifecycle and diagnostics:

const page = await client.deployments.list({ page: 1, pageSize: 20 });
const events = await client.deployments.events(42);
const renderedYaml = await client.deployments.yaml(42);
await client.deployments.stop(42);
await client.deployments.previewRestart(42);
await client.deployments.restart(42);

Training​

outputModelName is a suffix, not the complete asset name. Its maximum length depends on the selected base model because the final deployable name is <base>-FT-<suffix>; use the limit returned by the active capability.

const request = {
clientToken: "training-request-001",
displayName: "example-training",
outputModelName: "example-output",
recipeId: "recipe-id",
recipeVersion: "recipe-version",
baseModelRef: { type: "recipe_model", id: "model-id" },
datasetRefs: [{ datasetId: "dataset-id", role: "train" }],
placement: { clusterId: "1", resourceSpecId: "resource-spec-id" },
params: {},
};

await client.training.preview({ clusterId: 1, resourceSpecId: "resource-spec-id" });
const job = await client.training.create<{ jobId: string }>(request);
const completed = await client.waitForTrainingJob(job.jobId) as {
artifacts: Array<{ artifactId: string }>;
};
const artifact = await client.training.artifactDownloadUrl(
completed.artifacts[0]!.artifactId,
);

Evaluations​

const request = {
kind: "benchmark",
modelType: "LLM",
models: [{
type: "service",
msp_api_key_id: "7",
service_id: "42",
}],
dataset: "evaluation-dataset",
maxSamples: 100,
clusterId: 1,
};

await client.evaluations.preview({ clusterId: 1 });
const job = await client.evaluations.create<{ jobId: string }>(request);
await client.waitForEvaluationJob(job.jobId);
const report = await client.evaluations.report(job.jobId);

Jobs​

const jobs = await client.jobs.list({
type: "train",
status: "RUNNING",
page: 1,
pageSize: 20,
});
const job = await client.jobs.get("job-id");
const logs = await client.jobs.logs("job-id", { tail: 200 });
await client.waitForJob("job-id");

API Keys​

const keys = await client.keys.list();
const created = await client.keys.create<{ id: number }>({
keyValue: "sk-created-by-caller",
description: "automation key",
isActive: true,
});
const keyId = String(created.id);
const plaintext = await client.keys.reveal(keyId);
await client.keys.update(keyId, {
description: "renamed key",
isActive: true,
});

Treat the value returned by reveal(...) as a secret and never log it.

Provider Keys​

const providers = await client.providerKeys.providers();
const keys = await client.providerKeys.list();
const created = await client.providerKeys.create<{ id: number }>({
provider: "example-provider",
apiKey: "provider-api-key",
description: "integration credential",
});
const result = await client.providerKeys.test(created.id);
await client.providerKeys.changeStatus(created.id, { status: 1 });

Usage​

const startSeconds = 1782864000;
const endSeconds = 1785542400;

const summary = await client.usage.summary({ startDate: startSeconds, endDate: endSeconds });
const records = await client.usage.list({
startDate: startSeconds,
endDate: endSeconds,
page: 1,
pageSize: 20,
});
const trend = await client.usage.trend({
startDate: startSeconds,
endDate: endSeconds,
granularity: "day",
});

Observability​

const overview = await client.observability.clusterOverview(1);
const services = await client.observability.services({ clusterId: 1 });
const snapshot = await client.observability.serviceSnapshot(42);
const series = await client.observability.serviceTimeseries(42, {
rangeHours: 1,
maxPoints: 120,
});

Detailed API Reference​

Use the expandable TypeScript SDK section in the left navigation. Every public method has a dedicated module page with its purpose, request parameters or body, response shape, examples, and operational constraints.