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/sdkSet 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.
NODESANDBOX_API_KEY=ns_secret_...import { NodeSandbox } from '@node-sandbox/sdk';
export const nodesandbox = new NodeSandbox({
apiKey: process.env.NODESANDBOX_API_KEY!,
});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.
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); // mainProjects can also start from an in-memory file map, an HTTPS Git URL, or a ZIP URL.
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.
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.
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.
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.
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.
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.
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.