SpinupSpinup Docs
SDK

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/sdk

Spinup'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 by spinup 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 /runs calls

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.