Server SDK

Platform SDK

The server-side SDK for persistent NodeSandbox projects. Create projects, read their Git-backed files, commit changes, merge branches, and manage your team.

$npm i @node-sandbox/sdk

Set up the SDK

Create a secret key in the NodeSandbox dashboard and pass it to NodeSandbox. Secret keys are scoped to one team and authorize platform operations for that team.

.env
NODESANDBOX_API_KEY=ns_secret_...
nodesandbox.ts
import { NodeSandbox } from '@node-sandbox/sdk';

export const nodesandbox = new NodeSandbox({
  apiKey: process.env.NODESANDBOX_API_KEY!,
});
Server only.

Never expose an ns_secret_ key in browser code or a NEXT_PUBLIC_, VITE_, or similar public environment variable.

Create projects

Projects are persistent, team-owned sandboxes. Creation returns immediately with an importing project; use waitUntilReady() before reading or committing files.

create-project.ts
const project = await nodesandbox.projects.create({
  name: 'Customer playground',
  visibility: 'private',
  source: {
    type: 'template',
    template: 'vite-hono',
  },
});

const ready = await nodesandbox.projects.waitUntilReady(project.id);
console.log(ready.id, ready.defaultBranch); // main

Projects can also start from an in-memory file map, an HTTPS Git URL, or a ZIP URL.

project-sources.ts
await nodesandbox.projects.create({
  name: 'Imported app',
  source: {
    type: 'git',
    url: 'https://github.com/acme/example.git',
    ref: 'main',
  },
});

await nodesandbox.projects.create({
  name: 'Small script',
  source: {
    type: 'files',
    files: {
      'package.json': JSON.stringify({ scripts: { start: 'node index.js' } }),
      'index.js': 'console.log("hello")',
    },
  },
});

Fetch project files

Read the complete file tree at HEAD, a branch, a full ref, or a commit OID.HEAD resolves to the project's default branch, normally main.

read-files.ts
const head = await nodesandbox.projects.files.list(projectId, {
  ref: 'HEAD',
});

console.log(head.ref);       // refs/heads/main
console.log(head.commitOid); // resolved commit
console.log(head.files['package.json'].content);

const app = await nodesandbox.projects.files.retrieve(
  projectId,
  'src/App.tsx',
  { ref: 'feat/editor' },
);

Binary content is returned as a Uint8Array. Pass includeContent: falsewhen you only need paths, object IDs, modes, and sizes.

Files are read-only.

The SDK intentionally has no file write, move, or delete methods. Persistent changes always create a Git commit.

Commit changes

Send full-file additions and deletions in one atomic commit. The branch is optional and defaults to main. Use encodeFileContents() for text or binary content.

commit.ts
import { encodeFileContents } from '@node-sandbox/sdk';

const result = await nodesandbox.projects.commits.create(projectId, {
  branch: 'main',
  message: 'Update the application',
  fileChanges: {
    additions: [
      {
        path: 'src/App.tsx',
        contents: encodeFileContents('export default () => <h1>Hello</h1>;'),
      },
    ],
    deletions: [
      { path: 'src/old.ts' },
      { path: 'src/generated', recursive: true },
    ],
  },
});

console.log(result.commitOid);

A move is represented as an addition at the destination and a deletion at the original path.

history.ts
const history = await nodesandbox.projects.commits.list(projectId, {
  branch: 'main',
  limit: 25,
});

const commit = await nodesandbox.projects.commits.retrieve(
  projectId,
  history.data[0].oid,
);

Branches and merges

Create a branch from HEAD, another branch, or a commit OID. Commits can then target that branch by name.

branches.ts
await nodesandbox.projects.branches.create(projectId, {
  name: 'feat/editor',
  from: 'main',
});

await nodesandbox.projects.commits.create(projectId, {
  branch: 'feat/editor',
  message: 'Build editor UI',
  fileChanges: {
    additions: [
      { path: 'src/Editor.tsx', contents: encodeFileContents(editorSource) },
    ],
  },
});

await nodesandbox.projects.merge(projectId, {
  source: 'feat/editor',
  target: 'main',
});

Merges preserve non-conflicting changes from both branches and automatically choose the source branch for every conflict. The source branch remains available after the merge.

Teams and members

The secret key automatically addresses its owning team. It cannot access unrelated teams.

team.ts
const team = await nodesandbox.teams.retrieve();

await nodesandbox.teams.update({ name: 'Acme Engineering' });

const member = await nodesandbox.teams.members.invite({
  email: 'developer@acme.com',
  name: 'Ada Developer',
  role: 'member',
});

await nodesandbox.teams.members.update(member.id, { role: 'admin' });

const members = await nodesandbox.teams.members.list();

API reference

projects.create()

Create from files, Git, ZIP, or a built-in template.

projects.waitUntilReady()

Wait for asynchronous source import to finish.

projects.files.*

Read files at HEAD, a branch, ref, or commit.

projects.commits.*

Create commits and inspect project history.

projects.branches.*

List, create, and delete branches.

projects.merge()

Merge a source branch into a target branch.

projects.fork()

Copy a public or team project into the key's team.

teams.members.*

Invite, list, promote, and remove members.