APIZDocs

APIZ guide

TypeScript SDK

Use @apiz/sdk in your trusted Node application. Provider sandboxes remain native objects; agents inside them use CLI setup and their ordinary official SDKs.

Install

Use Node 22 or 24 (Node 24 recommended). Create your project and install from npm:

mkdir apiz-demo
cd apiz-demo
npm init -y
npm install @apiz/sdk [email protected]

The SDK ships ESM and TypeScript declarations. E2B is optional; to install only the core SDK, run npm install @apiz/sdk. The .mjs tutorial runs directly with Node; TypeScript projects use the same imports and get the package's types. There is no CommonJS build or browser-management entrypoint.

Tutorial: E2B Host With An Official-Tool Guest

Configure an S3 API connection, read Policy and Client Binding in the Web Console. Choose an existing allowed object. Create .env in your new project:

APIZ_USER_API_KEY=replace-with-your-user-api-key
APIZ_SERVER_URL=https://current-host
APIZ_TEAM_ID=replace-with-your-team-id
APIZ_CLIENT_ID=replace-with-your-client-id
E2B_API_KEY=replace-with-your-e2b-api-key
APIZ_EXAMPLE_BINDING=replace-with-your-s3-binding-alias
APIZ_EXAMPLE_OBJECT_KEY=demo/hello.txt

Replace the placeholders:

VariableMeaning
APIZ_USER_API_KEYHost-only User API Key with Team/Client issuance and revoke access
APIZ_SERVER_URLReachable HTTPS Control Plane URL
APIZ_TEAM_ID, APIZ_CLIENT_IDTeam and existing Client IDs
E2B_API_KEYHost-only E2B key
APIZ_EXAMPLE_BINDINGS3 Binding alias
APIZ_EXAMPLE_OBJECT_KEYAllowed object key

Save the following as main.mjs, then create the guest file described below. Run node --env-file=.env main.mjs once both files exist. This creates a real E2B sandbox. Exported variables override values in .env.

// Trusted host: the native E2B object stays under the caller's control.
import { readFile } from "node:fs/promises";

import { issueAccess } from "@apiz/sdk/access";
import { installCommand } from "@apiz/sdk/cli";
import { Management } from "@apiz/sdk/management";
import { Sandbox } from "e2b";

function required(name) {
  const value = process.env[name];
  if (!value) throw new Error(`Set ${name}`);
  return value;
}

const api = new Management({
  apiKey: required("APIZ_USER_API_KEY"),
  serverUrl: required("APIZ_SERVER_URL"),
  teamId: required("APIZ_TEAM_ID"),
});
const sandbox = await Sandbox.create({
  apiKey: required("E2B_API_KEY"),
  timeoutMs: 600_000,
});
try {
  await sandbox.files.write(
    "/home/user/guest_s3.py",
    await readFile(new URL("./guest_s3.py", import.meta.url), "utf8"),
  );
  await sandbox.commands.run("python -m pip install boto3", {
    timeoutMs: 120_000,
  });
  await sandbox.commands.run(installCommand({ serverUrl: api.serverUrl }), {
    timeoutMs: 120_000,
  });
  const access = await issueAccess(api, {
    clientId: required("APIZ_CLIENT_ID"),
    ttlSeconds: 600,
    env: {
      APIZ_CLI_PATH: "/tmp/apiz/bin/apiz",
      ...Object.fromEntries(
        ["APIZ_EXAMPLE_BINDING", "APIZ_EXAMPLE_OBJECT_KEY"].map((name) => [
          name,
          required(name),
        ]),
      ),
    },
  });
  await access.withAccess(async () => {
    const result = await sandbox.commands.run("python /home/user/guest_s3.py", {
      envs: access.exportEnv(),
      timeoutMs: 30_000,
    });
    if (result.exitCode !== 0)
      throw new Error("Guest request failed; inspect APIZ access logs");
  });
  await sandbox.commands.run("true");
  console.log("PASS: access revoked; native sandbox remains usable");
} finally {
  await sandbox.kill();
  await api.close();
}

Create guest_s3.py beside main.mjs using the full code in the guest tutorial. The guest is Python by design: CLI setup and boto3 run independently of your host language. No Python installation is needed on your host for this Node tutorial.

node --env-file=.env main.mjs

Success ends with PASS: access revoked; native sandbox remains usable. The host then deletes the sandbox. Find the S3 request in Access Logs; CLI readiness alone is not upstream acceptance. Credentials/setup output are not printed.

Case: Optional CLI Installation

import { installCommand } from "@apiz/sdk/cli";

const command = installCommand({
  serverUrl: api.serverUrl,
  installDir: "/tmp/apiz/bin",
  runtime: "node",
});
await sandbox.commands.run(command, { timeoutMs: 120_000 });

installCommand is synchronous, performs no I/O and creates no credentials. Choose "sh" (curl/wget, default), "python" (python3) or "node" (Node.js 22+). All execute the same install.sh, requiring POSIX sh, tar and Unix utilities. See CLI installation. Use /tmp/apiz/bin/apiz afterward or configure PATH yourself; subsequent processes do not inherit an installation command's PATH. Skip this step if your image already contains the CLI.

Case: Bring Your Own Sandbox Or Agent

Create the sandbox with native options for region, image, files and persistence. Optionally execute installCommand({serverUrl: api.serverUrl}) with its native command API, then call issueAccess(api, options). APIZ receives no sandbox object.

Replace the example guest command with your installed agent entrypoint, retaining env: access.exportEnv() (E2B calls the option envs). Use an absolute CLI path or set PATH explicitly in your own command; exportEnv supplies Client credentials. Do not spread process.env into the guest. Customize the agent and its official tools using CLI-generated setup for its Binding.

Case: Explicit Revocation

Inside an existing host scope with api, sandbox and clientId:

const access = await issueAccess(api, {
  clientId,
  ttlSeconds: 600,
});
try {
  await sandbox.commands.run(
    "/tmp/apiz/bin/apiz --output json client handoff inspect",
    { envs: access.exportEnv(), timeoutMs: 30_000 },
  );
} finally {
  const report = await access.revoke();
  if (report.revocation === "unknown") {
    console.error("Reconcile credential group", access.reference);
  }
}

withAccess handles normal/exceptional callback completion and cleanup. Manual revoke() returns a report which you must inspect. Repeated revocation calls share the cached report; they are not retries. Neither mode deletes the sandbox. Keep Management open until revocation finishes; api.close() only closes the HTTP client state.

Case: Cancellation And Separate Time Budgets

const access = await issueAccess(api, {
  clientId,
  ttlSeconds: 600,
  timeoutSeconds: 60,
  cleanupTimeoutSeconds: 15,
  signal: AbortSignal.timeout(90_000),
});

This fragment configures preparation; it does not run or automatically bound a later agent command. Pass the provider's native timeout/signal options to that command separately. Credential TTL, sandbox lifetime, preparation timeout and cleanup budget are independent. Aborting an HTTP mutation does not undo a server commit. Do not interpret cancellation as successful revocation.

Case: Management Without A Sandbox

Save this as management.mjs and run node --env-file=.env management.mjs. Only the four APIZ management variables are needed; it makes no upstream call:

import {
  CreationOutcomeUnknown,
  CreationOutputUnavailable,
  Management,
} from "@apiz/sdk/management";
const management = new Management({
  apiKey: process.env.APIZ_USER_API_KEY,
  serverUrl: process.env.APIZ_SERVER_URL,
  teamId: process.env.APIZ_TEAM_ID,
});
try {
  const prepared = management.credentials.prepare({
    clientId: process.env.APIZ_CLIENT_ID,
    ttlSeconds: 900,
    allBindings: true,
    label: "SDK example",
  });
  // Persist this safe ID before submission in a real orchestrator.
  console.log("Creation operation:", prepared.operationId);
  let issued;
  try {
    issued = await management.credentials.create(prepared);
  } catch (error) {
    if (error instanceof CreationOutcomeUnknown) {
      const status = await management.creationOperations.get(
        prepared.clientId,
        prepared.operationId,
      );
      console.log("Creation state:", status.state);
      if (status.state === "committed")
        await management.credentials.revoke(status.credential_group_id);
      // not_observed remains unknown; keep the operation ID for later lookup.
    } else if (
      error instanceof CreationOutputUnavailable &&
      error.metadata.credential_group_id
    ) {
      await management.credentials.revoke(error.metadata.credential_group_id);
    }
    throw error;
  }
  try {
    console.log("Created group:", issued.credentialGroupId);
    console.log("Expires at:", issued.expiresAt);
  } finally {
    await management.credentials.revoke(issued.credentialGroupId);
  }
} finally {
  await management.close();
}

Persist prepared.operationId before credentials.create(prepared). On CreationOutcomeUnknown, query creationOperations.get(clientId, operationId); not_observed remains unknown. A known committed group can be revoked explicitly.

For a custom executor, issueAccess(api, {clientId, ttlSeconds}) from @apiz/sdk/access issues access without provider CLI installation. Your executor owns preparation, just as it does when using any native provider SDK.

Management API Reference

Network methods return promises and accept options with timeoutMs and signal. The default HTTP deadline is 30 seconds and covers response-body consumption.

MethodPurpose
clients.list() / clients.get(id)Discover/read accessible Clients
clients.bindings(id) / clients.setupOptions(id)Inspect Client configuration
credentials.prepare({clientId, ttlSeconds, allBindings: true})Allocate a local issuance operation
credentials.create(prepared)Issue sensitive credentials
credentials.get(groupId) / credentials.revoke(groupId)Read/revoke a group
creationOperations.get(clientId, operationId)Reconcile uncertain creation
accessLogs.list({clientId, decision: "deny", limit: 20})Find denied requests
accessLogs.request(requestId)Retrieve correlated evidence

This surface is not yet a complete wrapper for every APIZ management endpoint. User API Key scopes and current membership/role still apply.

Failure Handling

Import error types from @apiz/sdk/errors. ConfigurationError is a local input failure; APIZError provides sanitized status/code/reason for server failures. CreationOutcomeUnknown requires operation reconciliation. CleanupError means normal callback work completed but automatic cleanup was not confirmed.

Use cleanupReport(error) and accessReference(error) from @apiz/sdk/access to retrieve safe cleanup status and IDs. If the callback throws, its original error is preserved with cleanup metadata. Access references are safe to persist; credential values, setup manifests and exportEnv() are not safe log payloads.

Provider Guides

E2B, Daytona, Modal, and Vercel each document native creation, command APIs, cleanup and validation limits. @apiz/policy-sdk is a separate authoring package described in the Policy SDK guide; it is not required to grant access.