TypeScript SDK
Install `@getspinup/sdk`, create a client, and call Spinup's workspace-scoped public API from TypeScript or JavaScript.
Install the SDK from npm:
npm install @getspinup/sdkSpinup's SDK wraps Spinup's public API for workspace-scoped control-plane operations and agent-scoped runtime operations.
Create a client
The SDK does not read environment variables for you. Pass values from your own config layer:
import { createSpinupClient } from "@getspinup/sdk";
const spinup = createSpinupClient({
apiKey: process.env.SPINUP_API_KEY,
defaultWorkspaceSlug: process.env.SPINUP_WORKSPACE,
});
const me = await spinup.me.get();
const workspaces = await spinup.workspaces.list();
const agents = await spinup.agents.list();
const supportAgent = await spinup.agents.get({
agentSlug: "support-agent",
});
console.log(supportAgent.agent.modelPolicy);
const capabilities = await spinup.agents.capabilities.list({
agentSlug: "support-agent",
});
console.log(capabilities.capabilities);What works today
Current workspace-oriented control-plane methods:
me.get()workspaces.list()agents.list()agents.get({ agentSlug })agents.create({ name })agents.update({ agentSlug, name })agents.updateHarnesses({ agentSlug, defaultHarness })agents.capabilities.list({ agentSlug })agents.capabilities.add({ agentSlug, capability })agents.capabilities.update({ agentSlug, capabilityId, capability })agents.capabilities.remove({ agentSlug, capabilityId })agents.delete({ agentSlug, confirmationSlug })
Current agent-runtime methods:
agents.status({ agentId })agents.exec({ agentId, input })agents.runs.list({ agentId })agents.runs.get({ agentId, runId })
Per-call overrides still work when you need a different workspace or key:
await spinup.agents.get({
agentSlug: "research-agent",
apiKey: process.env.OTHER_SPINUP_API_KEY,
workspaceSlug: "labs",
});If you do not set defaultWorkspaceSlug, pass workspaceSlug explicitly on workspace-scoped reads.
Inspect an agent
agents.get({ agentSlug }) returns the public inspection shape for one agent:
- agent ID, slug, created time, and updated time
- model, supported harnesses and default, capabilities, and runtime sizing
- environment status, attention, readiness time, and runtime reconciliation state
Environment variable values and secret references are intentionally omitted from the SDK response. Use the dashboard for secret management.
Manage capabilities
See Capabilities for the concept. Use the SDK to keep capability settings with the agent for future runs.
The SDK can mark a capability as declared or disabled. Spinup records runtime fulfillment separately when the environment projects, validates, or fails a capability.
List capabilities:
const capabilities = await spinup.agents.capabilities.list({
agentSlug: "support-agent",
});Add a declared CLI requirement:
await spinup.agents.capabilities.add({
agentSlug: "support-agent",
capability: {
kind: "cli",
name: "ffmpeg",
source: "system",
status: "declared",
validationPlan: {
strategy: "executable",
executable: "ffmpeg",
versionArgs: ["-version"],
},
},
});Disable or remove a capability:
await spinup.agents.capabilities.update({
agentSlug: "support-agent",
capabilityId: "capability_01hxyz...",
capability: { status: "disabled" },
});
await spinup.agents.capabilities.remove({
agentSlug: "support-agent",
capabilityId: "capability_01hxyz...",
});Manage agents
Create an agent:
const created = await spinup.agents.create({
name: "Support Agent",
});Rename an agent:
const renamed = await spinup.agents.update({
agentSlug: created.agent.slug,
name: "Support Agent v2",
});Update the default harness:
await spinup.agents.updateHarnesses({
agentSlug: renamed.agent.slug,
defaultHarness: "hermes",
});Supported harness values today are openclaw and hermes.
Add a skill capability:
await spinup.agents.capabilities.add({
agentSlug: renamed.agent.slug,
capability: {
kind: "skill",
name: "vercel-react-best-practices",
source: "vercel-labs/agent-skills",
installPlan: {
strategy: "skill",
manager: "skills_cli",
skillName: "vercel-react-best-practices",
source: "vercel-labs/agent-skills",
},
},
});Delete an agent:
await spinup.agents.delete({
agentSlug: renamed.agent.slug,
confirmationSlug: renamed.agent.slug,
});Agent creation, deletion, default harness changes, and capability changes follow the same control-plane behavior as the dashboard. Creation queues provisioning. Harness changes choose the default used when a run does not specify harness; supported harnesses stay available for per-run overrides. Capability changes update what Spinup keeps with the agent. Both use runtime reconciliation when needed. Deleting a ready agent first tears down its runtime environment state, and deletion is rejected while an environment lifecycle operation is in progress.
Runtime status, exec, and runs
Runtime helpers require an agent runtime key (sk_agent_...) scoped to the target agent ID:
const runtime = createSpinupClient({
apiKey: process.env.SPINUP_AGENT_API_KEY,
});
const status = await runtime.agents.status({
agentId: "agent_01hxyz...",
});
const execResult = await runtime.agents.exec({
agentId: "agent_01hxyz...",
input: "Summarize this repository.",
harness: "openclaw",
timeoutSeconds: 45,
workspace: "workspace",
cwd: "repo",
});
console.log(status.status, execResult.output);
const runs = await runtime.agents.runs.list({
agentId: "agent_01hxyz...",
limit: 20,
});
const run = await runtime.agents.runs.get({
agentId: "agent_01hxyz...",
runId: runs.runs[0].id,
});
console.log(run.run.status, run.run.output);Run history returns support-safe fields: lifecycle timestamps, harness selection, request options, final user-facing output, generic error state, warnings, token/tool counts, and bounded evidence counts. It does not return the original prompt input, raw stdout/stderr, raw provider payloads, billing cost details, audit events, actor IDs, internal session IDs, Worker Host IDs, microVM IDs, or secret/env maps.
Override base URLs carefully
For local or staging environments, you can override the SDK hosts:
const spinup = createSpinupClient({
apiBaseUrl: "https://api.staging.example.com/v1",
apiKey: process.env.SPINUP_API_KEY,
});Point apiBaseUrl at a plain origin or the final base path you want the SDK to resolve against. Do not include query strings or hash fragments.
Use the right credential
Prefer a dashboard-created workspace API key (sk_workspace_...) for SDK clients.
- Workspace API key (
sk_workspace_...): preferred for@getspinup/sdk, direct public API calls, and server-side automation in one workspace - Personal/device key (
sk_user_...): created byspinup login; user-scoped so the CLI can list and switch workspaces - Agent runtime key (
sk_agent_...): one-agent credential for SDK runtime helpers and direct/status,/exec, and/runscalls
Device authorization is optional
If you already have a valid sk_workspace_... workspace API key, you can use the SDK directly without the device authorization flow.
Device authorization and personal/device key exchange are reserved for the Spinup CLI. Application code should use a dashboard-created workspace API key.