Console Playground โ–ถ

C# (.NET 10) API Documentation

Quick Start

Execute code in 42+ languages with a single API call. Here's how to get started:

1

Get your API key

Sign up at unsandbox.com/console to get your API credentials.

2

Make your first request

Send code to the execute endpoint and get results back instantly.

3

Build something amazing

Use our sandboxed execution for AI agents, code playgrounds, educational tools, and more.

Installation

Download Binary

# Linux x86_64
wget https://unsandbox.com/downloads/un
chmod +x un

# Move to PATH (optional)
sudo mv un /usr/local/bin/

Build from Source

# Requirements: GCC, libcurl, libwebsockets
sudo apt-get install build-essential libcurl4-openssl-dev libwebsockets-dev

# Compile
wget https://unsandbox.com/downloads/un.c
gcc -Wall -O2 -o un un.c -lcurl -lwebsockets

SDK Libraries (un-inception)

For languages that need programmatic access, use our SDK implementations:

# Python - download un.py
wget https://unsandbox.com/cli/inception/un.py
python un.py script.py

# JavaScript - download un.js
wget https://unsandbox.com/cli/inception/un.js
node un.js script.py

# Go - download un.go
wget https://unsandbox.com/cli/inception/un.go
go run un.go script.py

View all 42 language SDKs โ†’

Authentication

All API requests require HMAC-SHA256 signature authentication for security.

Required Headers

Header Description
Authorization Bearer <public_key> (your unsb-pk-xxxx key)
X-Timestamp Unix timestamp in seconds (ยฑ5 min tolerance)
X-Signature HMAC-SHA256 signature (lowercase hex)
Content-Type application/json

Signature Format

HMAC-SHA256(secret_key, timestamp:METHOD:path:body)

Example signature string:

1699564800:POST:/execute:{"language":"python","code":"print('hi')"}

Your secret key is never transmitted. The server verifies signatures using your encrypted key.

Execute File (CLI)

Run any code file. Language is auto-detected from file extension or shebang.

Basic Usage

# Python
un hello.py

# JavaScript
un app.js

# Rust (compiles and runs)
un main.rs

# C (compiles and runs)
un program.c

# Go
un main.go

With Options

# Extended timeout (5 minutes)
un --ttl 300 long_script.py

# With more CPU/RAM (4 vCPUs, 8GB RAM)
un -v 4 heavy_compute.py

# Maximum resources (8 vCPUs, 16GB RAM)
un --vcpu 8 ml_training.py

Response

Output streams directly to your terminal:

$ un hello.py
Hello from unsandbox!

$ echo $?
0

API Equivalent

POST /execute

{
  "success": true,
  "stdout": "Hello from unsandbox!\n",
  "stderr": "",
  "exit_code": 0,
  "language": "python",
  "total_time_ms": 127
}
Execute Inline Code (CLI)

Run code snippets directly from the command line using the -s flag.

Basic Usage

# Python
un -s python 'print("Hello World")'

# Bash
un -s bash 'echo "Hello" && date'

# JavaScript
un -s javascript 'console.log(Math.PI)'

# Ruby
un -s ruby 'puts 2 ** 100'

# Go (full program)
un -s go 'package main; import "fmt"; func main() { fmt.Println("Hi") }'

Multi-line Code

# Using heredoc
un -s python <<'EOF'
import json
data = {"name": "unsandbox", "version": 2}
print(json.dumps(data, indent=2))
EOF

Supported Languages

Any of the 42 supported languages work with -s:

un -s python 'print(42)'
un -s javascript 'console.log(42)'
un -s typescript 'console.log(42 as number)'
un -s ruby 'puts 42'
un -s php '<?php echo 42;'
un -s perl 'print 42'
un -s lua 'print(42)'
un -s rust 'fn main() { println!("42"); }'
un -s c 'int main() { printf("42"); return 0; }'
un -s cpp 'int main() { std::cout << 42; }'
un -s java 'class M { public static void main(String[] a) { System.out.println(42); }}'
un -s kotlin 'fun main() = println(42)'
un -s go 'package main; import "fmt"; func main() { fmt.Println(42) }'
un -s haskell 'main = print 42'
un -s elixir 'IO.puts 42'
un -s julia 'println(42)'
un -s r 'print(42)'
Environment Variables

Pass environment variables to your code using the -e flag.

Single Variable

un -e DEBUG=1 script.py
un -e API_KEY=secret app.js

Multiple Variables

un -e DEBUG=1 -e NAME=World -e COUNT=42 script.py

With Inline Code

un -e NAME=Claude -s python 'import os; print(f"Hello {os.environ[\"NAME\"]}")'

un -e X=10 -e Y=20 -s bash 'echo "Sum: $((X + Y))"'

Example Script

# config_demo.py
import os

debug = os.environ.get('DEBUG', '0')
name = os.environ.get('NAME', 'World')

if debug == '1':
    print(f"Debug mode enabled")
print(f"Hello {name}!")

Run It

$ un -e DEBUG=1 -e NAME=unsandbox config_demo.py
Debug mode enabled
Hello unsandbox!
Input Files

Teleport files into the sandbox. CLI uses -f flag; API uses input_files array.

CLI Usage

# Single file
un -f data.csv process.py

# Multiple files
un -f data.csv -f config.json -f image.png script.py

# Large files (skip confirmation)
un -f large_dataset.parquet -y ml_training.py

Limits

  • Maximum files: 10 per execution
  • Maximum total size: 10MB (encoded)
  • Maximum single file: 5MB
# Files are placed in working directory
un -f data.csv -s python 'print(open("data.csv").read())'

# Process multiple input files
un -f input.json -f config.yaml script.py
{
  "language": "python",
  "code": "print(open('data.csv').read())",
  "input_files": [
    {
      "filename": "data.csv",
      "content": "bmFtZSxhZ2UKQWxpY2UsMzAKQm9iLDI1"
    }
  ]
}

Content must be Base64-encoded.

Files are placed in the working directory:

  • Python: open('data.csv')
  • Node.js: fs.readFileSync('data.csv')
  • Ruby: File.read('data.csv')
  • Go: os.ReadFile("data.csv")
  • Bash: cat data.csv
Artifacts

Teleport files out of the sandbox. Use -a to collect artifacts from /tmp/artifacts/ or get compiled binaries.

Collect Generated Files

# Files in /tmp/artifacts/ are collected
un -a -o ./outputs script.py

Get Compiled Binary

# Compile C and get the binary
un -a -o ./bin main.c

# Compile Rust and get the binary
un -a -o ./bin main.rs

# Compile Go and get the binary
un -a -o ./bin main.go

WebAssembly Compilation

# Compile to WASM (supported languages)
un --wasm -o ./wasm main.c
un --wasm -o ./wasm main.rs

Example: Generate and Collect

# generate_report.py
import json
import os

os.makedirs('/tmp/artifacts', exist_ok=True)

data = {"users": 100, "revenue": 50000}
with open('/tmp/artifacts/report.json', 'w') as f:
    json.dump(data, f, indent=2)

print("Report generated!")

Run It

$ un -a -o ./reports generate_report.py
Report generated!

$ ls ./reports
report.json
Network Modes

Zero Trust (default)

Complete network isolation. No internet access.

# Default - no network
un script.py

Semi-Trusted

Internet access via egress proxy.

# Enable network access
un -n semitrusted script.py

# Or with sessions
un session -n semitrusted

Use Cases

# Zero Trust - safe for untrusted code
un -s python 'print("Isolated execution")'

# Semi-Trusted - when you need network
un -n semitrusted -s python '
import requests
r = requests.get("https://api.github.com")
print(r.status_code)
'

# Semi-Trusted session for development
un session -n semitrusted --shell bash
Create Session

Start an interactive shell session in a sandbox container.

Basic Session

# Default bash shell
un session

# Choose your shell
un session --shell zsh
un session --shell fish

REPL Sessions

# Python REPL
un session --shell python3
un session --shell ipython
un session --shell bpython

# Node.js REPL
un session --shell node

# Ruby REPL
un session --shell irb

# Other REPLs
un session --shell julia
un session --shell ghci    # Haskell
un session --shell iex     # Elixir

Session Options

# With network access
un session -n semitrusted

# With persistence (can reconnect)
un session --tmux
un session --screen

# With timeout (1 hour)
un session --ttl 3600

# Full audit recording
un session --audit -o ./logs

API Equivalent

POST /sessions

{
  "session_id": "sess_xyz789",
  "websocket_url": "wss://api.unsandbox.com/sessions/sess_xyz789/shell",
  "status": "running"
}
List Sessions

List Active Sessions

un session --list

Output

Active sessions: 2

SESSION ID                     CONTAINER         SHELL      TTL      STATUS
sess_abc123...                 unsb-vm-12345     python3    45m30s   active
sess_def456...                 unsb-vm-67890     bash       1h2m     active

Get Session Details

un session --info sess_abc123

API Equivalent

GET /sessions and GET /sessions/{id}

{
  "sessions": [
    {
      "session_id": "sess_abc123",
      "status": "running",
      "network_mode": "zerotrust",
      "shell": "python3"
    }
  ]
}
Attach & Detach

Reconnect to persistent sessions (requires --tmux or --screen).

Create Persistent Session

# With tmux (recommended)
un session --tmux

# With screen
un session --screen

Detach

# tmux: Press Ctrl+b then d
# screen: Press Ctrl+a then d

Reconnect

# By session ID
un session --attach sess_abc123

# By container name
un session --attach unsb-vm-12345

Terminate Session

# Kill by ID
un session --kill sess_abc123

# Kill by container name
un session --kill unsb-vm-12345

API Equivalent

DELETE /sessions/{id}

{"status": "terminated"}
Shells & REPLs

Available shells and REPLs for interactive sessions:

Shells

bash, dash, sh, zsh, fish, ksh
tcsh, csh, elvish, xonsh, ash

REPLs

# Python
python3, bpython, ipython

# JavaScript
node

# Ruby
ruby, irb

# Other
lua, php, perl, guile, scheme
ghci, erl, iex, sbcl, clisp
r, julia, clojure

API Equivalent

GET /shells returns the full list of available shells.

Freeze & Unfreeze Sessions

Freeze sessions to save resources while preserving state.

Freeze Session

un session --freeze sess_abc123

Unfreeze Session

un session --unfreeze sess_abc123

API Equivalent

POST /sessions/{id}/freeze

{"status": "frozen"}

POST /sessions/{id}/unfreeze

{"status": "running", "unfreeze_time_ms": 1250}
Session Snapshots

Create point-in-time snapshots of session state.

Create Snapshot

# With name
un session --snapshot sess_abc123 --name "before-upgrade"

# Quick snapshot (auto-generated name)
un session --snapshot sess_abc123

Restore from Snapshot

un session --restore snap_xyz789

API Equivalent

POST /sessions/{id}/snapshot

{
  "snapshot_id": "snap_abc123",
  "name": "before-upgrade",
  "size_bytes": 52428800
}

POST /sessions/{id}/restore

{"status": "restored"}
Create Service

Create long-running services with custom subdomains at *.on.unsandbox.com.

Basic Service

# Simple web server
un service --name myapp --ports 80 --bootstrap "python -m http.server 80"

# With multiple ports
un service --name api --ports 80,443 --bootstrap "./start.sh"

With Files

# Deploy app tarball
un service --name blog --ports 8000 \
  -f app.tar.gz \
  --bootstrap "tar xzf app.tar.gz && cd app && ./start.sh"

Custom Domains

un service --name api --ports 80 \
  --domains api.example.com,www.api.example.com \
  --bootstrap "./start.sh"

Service Types

# Web service (default)
un service --name web --ports 80

# Minecraft server
un service --name mc --type minecraft --bootstrap ./setup.sh

# Game server types
un service --name game --type mumble
un service --name game --type teamspeak
un service --name game --type source

API Equivalent

POST /services

{
  "service_id": "svc_abc123",
  "name": "myapp",
  "url": "https://myapp.on.unsandbox.com",
  "status": "starting",
  "ports": [80]
}
Manage Services

List Services

un service --list

Get Service Info

un service --info svc_abc123

Freeze/Unfreeze Service

# Freeze (auto-unfreezes on HTTP request)
un service --freeze svc_abc123

# Manual unfreeze
un service --unfreeze svc_abc123

Lock/Unlock

# Prevent accidental deletion
un service --lock svc_abc123

# Allow deletion
un service --unlock svc_abc123

Destroy Service

un service --destroy svc_abc123

API Endpoints

  • GET /services - List all services
  • GET /services/{id} - Get service details
  • POST /services/{id}/freeze - Freeze service
  • POST /services/{id}/unfreeze - Unfreeze service
  • POST /services/{id}/lock - Lock service
  • POST /services/{id}/unlock - Unlock service
  • DELETE /services/{id} - Destroy service
Logs & Execute

View Bootstrap Logs

# All logs
un service --logs svc_abc123

# Last 9000 lines
un service --tail svc_abc123

Execute Command in Service

# Run any command
un service --execute svc_abc123 'ls -la'

# Check service status
un service --execute svc_abc123 'systemctl status myapp'

# View application logs
un service --execute svc_abc123 'journalctl -u myapp -n 50'

Dump Bootstrap Script

# Print to stdout
un service --dump-bootstrap svc_abc123

# Save to file
un service --dump-bootstrap svc_abc123 backup.sh

API Equivalent

GET /services/{id}/logs

{"log": "Bootstrap started...\nInstalling...\nServer listening on port 80"}

POST /services/{id}/execute

{
  "stdout": "...",
  "stderr": "",
  "exit_code": 0
}
Environment Vault

Encrypted storage for service secrets. Variables are injected when the container starts or unfreezes.

Set Environment Variables

# Using the API (PUT /services/{id}/env)
# Content-Type: text/plain
# Body: .env format

DATABASE_URL=postgres://user:pass@host/db
API_SECRET=abc123
DEBUG=false

Get Vault Status

GET /services/{id}/env

{
  "exists": true,
  "variable_count": 3,
  "updated_at": "2026-01-14T12:00:00Z"
}

Export Decrypted Vault

POST /services/{id}/env/export

{"env": "DATABASE_URL=postgres://...\nAPI_SECRET=abc123\nDEBUG=false"}

Delete Vault

DELETE /services/{id}/env

{"status": "deleted"}
Redeploy Service

Re-run Bootstrap

# Re-run existing bootstrap
un service --redeploy svc_abc123

# Redeploy with new bootstrap
un service --redeploy svc_abc123 --bootstrap ./new-setup.sh

Create Service Snapshot

# Standard snapshot (pauses briefly)
un service --snapshot svc_abc123 --name "stable-v1.0"

# Hot snapshot (no pause)
un service --snapshot svc_abc123 --hot

API Equivalent

POST /services/{id}/redeploy

{"state": "redeploying"}

POST /services/{id}/snapshot

{
  "snapshot_id": "snap_def456",
  "name": "stable-v1.0",
  "size_bytes": 104857600
}
List Snapshots

List All Snapshots

un snapshot --list

Output

Snapshots: 3

SNAPSHOT ID                  NAME              SOURCE     SIZE     CREATED
snap_a1b2-c3d4-e5f6-g7h8     before-upgrade    session    512 MB   2h ago
snap_i9j0-k1l2-m3n4-o5p6     stable-v1.0       service    1.2 GB   1d ago
snap_q7r8-s9t0-u1v2-w3x4     dev-checkpoint    session    256 MB   3d ago

Get Snapshot Info

un snapshot --info snap_a1b2-c3d4-e5f6-g7h8

Delete Snapshot

un snapshot --delete snap_a1b2-c3d4-e5f6-g7h8

API Equivalent

GET /snapshots

{
  "snapshots": [
    {
      "snapshot_id": "snap_abc123",
      "name": "before-upgrade",
      "source_type": "session",
      "size_bytes": 52428800
    }
  ]
}
Restore & Clone

Restore to Original

# Restore session from snapshot
un session --restore snap_abc123

# Restore service from snapshot
un service --restore snap_def456

Clone to New Container

POST /snapshots/{id}/clone

# Clone to new session
{
  "type": "session",
  "shell": "bash"
}

# Clone to new service
{
  "type": "service",
  "name": "cloned-app"
}

API Response

Clone to session:

{"session_id": "sess_new123"}

Clone to service:

{
  "service_id": "svc_new456",
  "url": "https://cloned-app.on.unsandbox.com"
}

Lock/Unlock Snapshots

POST /snapshots/{id}/lock - Prevent deletion

POST /snapshots/{id}/unlock - Allow deletion

Base URL

All API requests should be made to:

https://api.unsandbox.com

The API supports two network modes:

  • zerotrust (default) โ€” No network access, fully isolated execution
  • semitrusted โ€” Network access via egress proxy, can reach the internet
Required Dependencies

The C# (.NET 10) examples below require the following 3rd party libraries:

  • None (uses built-in HttpClient and System.Text.Json)

Make sure these packages are installed in your environment before running the examples.

POST https://api.unsandbox.com/execute

Execute code immediately and wait for results. Best for quick scripts and interactive use.

Request Parameters

Parameter Type Required Description
language string โœ“ Programming language
code string โœ“ Source code to execute
env object Environment variables (key-value pairs)
network_mode string "zerotrust" or "semitrusted"
ttl integer Timeout 1-900s (default: 60)
return_artifact boolean Return compiled binary
return_wasm_artifact boolean Return WebAssembly binary
vcpu integer vCPUs 1-8 (each includes 2GB RAM)
input_files array Files to upload (see Input Files)
// C# with .NET 10 (modern async/await)
// Build: dotnet build
// Run: dotnet run

using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

class Program
{
    static string PublicKey = Environment.GetEnvironmentVariable("UNSANDBOX_PUBLIC_KEY") ?? "unsb-pk-test-0000-0000-0001";
    static string SecretKey = Environment.GetEnvironmentVariable("UNSANDBOX_SECRET_KEY") ?? "unsb-sk-test0-vault-unlck-12345";

    static string HmacSha256Hex(string key, string data)
    {
        using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));
        var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(data));
        return Convert.ToHexString(hash).ToLower();
    }

    static async Task Main()
    {
        using var client = new HttpClient();

        var path = "/execute";
        var payload = new
        {
            language = "python",
            code = "print('Hello from unsandbox!')"
        };
        var body = JsonSerializer.Serialize(payload);

        var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();
        var message = $"{timestamp}:POST:{path}:{body}";
        var signature = HmacSha256Hex(SecretKey, message);

        var url = "https://api.unsandbox.com" + path;
        using var request = new HttpRequestMessage(HttpMethod.Post, url);
        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", PublicKey);
        request.Headers.Add("X-Timestamp", timestamp);
        request.Headers.Add("X-Signature", signature);
        request.Content = new StringContent(body, Encoding.UTF8, "application/json");

        using var response = await client.SendAsync(request);
        var responseBody = await response.Content.ReadAsStringAsync();

        using var doc = JsonDocument.Parse(responseBody);
        var root = doc.RootElement;

        if (root.GetProperty("success").GetBoolean())
        {
            var stdout = root.GetProperty("stdout").GetString();
            Console.WriteLine($"Output: {stdout}");
        }
        else
        {
            var error = root.GetProperty("error").GetString();
            Console.WriteLine($"Error: {error}");
        }
    }
}
{
  "success": true,
  "stdout": "Hello from unsandbox!\n",
  "stderr": "",
  "exit_code": 0,
  "language": "python",
  "job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "network_mode": "zerotrust",
  "total_time_ms": 236
}
{
  "success": false,
  "stdout": "",
  "stderr": "SyntaxError: invalid syntax\n",
  "exit_code": 1,
  "language": "python",
  "job_id": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
  "network_mode": "zerotrust",
  "total_time_ms": 312
}
POST https://api.unsandbox.com/execute/async

Submit code for execution and receive a job ID to poll for results. Best for long-running scripts or when you need to decouple submission from execution.

Request Parameters

Parameter Type Required Description
language string โœ“ Programming language
code string โœ“ Source code to execute
env object Environment variables (key-value pairs)
network_mode string "zerotrust" or "semitrusted"
ttl integer Timeout 1-900s (default: 60)
return_artifact boolean Return compiled binary
return_wasm_artifact boolean Return WebAssembly binary
vcpu integer vCPUs 1-8 (each includes 2GB RAM)
input_files array Files to upload (see Input Files)
// C# with .NET 10 (modern async/await)
// Execute code asynchronously and poll for results
// Build: dotnet build
// Run: dotnet run

using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

class Program
{
    static string PublicKey = Environment.GetEnvironmentVariable("UNSANDBOX_PUBLIC_KEY") ?? "unsb-pk-test-0000-0000-0001";
    static string SecretKey = Environment.GetEnvironmentVariable("UNSANDBOX_SECRET_KEY") ?? "unsb-sk-test0-vault-unlck-12345";
    static readonly HttpClient client = new();

    static string HmacSha256Hex(string key, string data)
    {
        using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));
        var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(data));
        return Convert.ToHexString(hash).ToLower();
    }

    static async Task<string> MakeRequestAsync(string method, string path, string body)
    {
        var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();
        var message = $"{timestamp}:{method}:{path}:{body}";
        var signature = HmacSha256Hex(SecretKey, message);

        var url = "https://api.unsandbox.com" + path;
        using var request = new HttpRequestMessage(new HttpMethod(method), url);
        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", PublicKey);
        request.Headers.Add("X-Timestamp", timestamp);
        request.Headers.Add("X-Signature", signature);

        if (!string.IsNullOrEmpty(body))
        {
            request.Content = new StringContent(body, Encoding.UTF8, "application/json");
        }

        using var response = await client.SendAsync(request);
        return await response.Content.ReadAsStringAsync();
    }

    static async Task Main()
    {
        // Submit async job
        var payload = new { language = "python", code = "import time; time.sleep(2); print('Hello after 2 seconds!')" };
        var body = JsonSerializer.Serialize(payload);
        var submitResponse = await MakeRequestAsync("POST", "/execute/async", body);
        Console.WriteLine($"Submit response: {submitResponse}");

        // Extract job_id
        using var submitDoc = JsonDocument.Parse(submitResponse);
        var jobId = submitDoc.RootElement.GetProperty("job_id").GetString();
        Console.WriteLine($"Job ID: {jobId}");

        // Poll for results
        Console.WriteLine("Polling for results...");
        for (int i = 0; i < 10; i++)
        {
            await Task.Delay(1000);
            var statusResponse = await MakeRequestAsync("GET", $"/jobs/{jobId}", "");

            using var doc = JsonDocument.Parse(statusResponse);
            var root = doc.RootElement;
            var status = root.GetProperty("status").GetString();

            if (status == "completed")
            {
                Console.WriteLine("Job completed!");
                var stdout = root.GetProperty("stdout").GetString();
                Console.WriteLine($"Output: {stdout}");
                break;
            }
            else if (status == "failed")
            {
                Console.WriteLine("Job failed!");
                var error = root.GetProperty("error").GetString();
                Console.WriteLine($"Error: {error}");
                break;
            }
            else
            {
                Console.WriteLine("Status: pending...");
            }
        }
    }
}
{
  "job_id": "ba943906-4ea6-a61c-9980-445f459368d",
  "status": "pending",
  "message": "Job accepted for execution"
}
POST https://api.unsandbox.com/run

Execute code with automatic language detection via shebang. Send raw code as the request body with Content-Type: text/plain.

Request

  • Content-Type: text/plain
  • Body: Raw code with shebang (e.g., #!/usr/bin/env python3)

Query Parameters

Parameter Type Required Description
env string URL-encoded JSON object with environment variables
network_mode string "zerotrust" or "semitrusted"
ttl integer Timeout 1-900s (default: 60)
return_artifact boolean Return compiled binary
return_wasm_artifact boolean Return WebAssembly binary
// C# with .NET 10 (modern async/await) - Run code with shebang detection
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

class Program
{
    static string PublicKey = Environment.GetEnvironmentVariable("UNSANDBOX_PUBLIC_KEY") ?? "unsb-pk-test-0000-0000-0001";
    static string SecretKey = Environment.GetEnvironmentVariable("UNSANDBOX_SECRET_KEY") ?? "unsb-sk-test0-vault-unlck-12345";

    static string HmacSha256Hex(string key, string data) =>
        Convert.ToHexString(new HMACSHA256(Encoding.UTF8.GetBytes(key)).ComputeHash(Encoding.UTF8.GetBytes(data))).ToLower();

    static async Task Main()
    {
        using var client = new HttpClient();
        var path = "/run";
        var payload = new { code = "#!/usr/bin/env python3\nprint('Hello from shebang!')" };
        var body = JsonSerializer.Serialize(payload);
        var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();
        var message = $"{timestamp}:POST:{path}:{body}";
        var signature = HmacSha256Hex(SecretKey, message);

        using var request = new HttpRequestMessage(HttpMethod.Post, "https://api.unsandbox.com" + path);
        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", PublicKey);
        request.Headers.Add("X-Timestamp", timestamp);
        request.Headers.Add("X-Signature", signature);
        request.Content = new StringContent(body, Encoding.UTF8, "application/json");

        using var response = await client.SendAsync(request);
        Console.WriteLine(await response.Content.ReadAsStringAsync());
    }
}
{
  "success": true,
  "stdout": "Language auto-detected!\n",
  "stderr": "",
  "exit_code": 0,
  "language": "python",
  "detected_language": "python",
  "job_id": "f6a7b8c9-d0e1-2345-fghi-678901234567",
  "network_mode": "zerotrust"
}
POST https://api.unsandbox.com/run/async

Submit code with automatic language detection and receive a job ID. Combines the convenience of /run with the flexibility of async execution.

Request

  • Content-Type: text/plain
  • Body: Raw code with shebang (e.g., #!/usr/bin/env ruby)

Query Parameters

Parameter Type Required Description
env string URL-encoded JSON object with environment variables
network_mode string "zerotrust" or "semitrusted"
ttl integer Timeout 1-900s (default: 60)
return_artifact boolean Return compiled binary
return_wasm_artifact boolean Return WebAssembly binary
// C# with .NET 10 (modern async/await) - Run code async with shebang
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

class Program
{
    static string PublicKey = Environment.GetEnvironmentVariable("UNSANDBOX_PUBLIC_KEY") ?? "unsb-pk-test-0000-0000-0001";
    static string SecretKey = Environment.GetEnvironmentVariable("UNSANDBOX_SECRET_KEY") ?? "unsb-sk-test0-vault-unlck-12345";

    static string HmacSha256Hex(string key, string data) =>
        Convert.ToHexString(new HMACSHA256(Encoding.UTF8.GetBytes(key)).ComputeHash(Encoding.UTF8.GetBytes(data))).ToLower();

    static async Task Main()
    {
        using var client = new HttpClient();
        var path = "/run/async";
        var payload = new { code = "#!/usr/bin/env python3\nimport time; time.sleep(2); print('Async shebang!')" };
        var body = JsonSerializer.Serialize(payload);
        var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();
        var message = $"{timestamp}:POST:{path}:{body}";
        var signature = HmacSha256Hex(SecretKey, message);

        using var request = new HttpRequestMessage(HttpMethod.Post, "https://api.unsandbox.com" + path);
        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", PublicKey);
        request.Headers.Add("X-Timestamp", timestamp);
        request.Headers.Add("X-Signature", signature);
        request.Content = new StringContent(body, Encoding.UTF8, "application/json");

        using var response = await client.SendAsync(request);
        Console.WriteLine(await response.Content.ReadAsStringAsync());
    }
}
{
  "job_id": "ba943906-4ea6-a61c-9980-445f459368d",
  "status": "pending",
  "detected_language": "python",
  "message": "Job accepted for execution"
}

Via GET /jobs/{id}

{
  "job_id": "a7b8c9d0-e1f2-3456-ghij-789012345678",
  "status": "completed",
  "created_at": "2025-01-11T12:00:00Z",
  "started_at": "2025-01-11T12:00:01Z",
  "completed_at": "2025-01-11T12:00:02Z",
  "success": true,
  "stdout": "Running async with auto-detect!\n",
  "stderr": "",
  "exit_code": 0,
  "language": "ruby",
  "network_mode": "zerotrust",
  "total_time_ms": 1234
}
GET https://api.unsandbox.com/jobs/{id}

Check the status and results of an asynchronous job. Poll this endpoint after submitting a job via /execute/async or /run/async.

URL Parameters

Parameter Type Description
id string Job ID returned from async endpoint

Possible Status Values

  • pending - Job queued, waiting to execute
  • running - Job currently executing
  • completed - Job finished successfully
  • failed - Job execution failed
  • timeout - Job exceeded TTL limit
  • cancelled - Job was cancelled via DELETE
// C# with .NET 10 (modern async/await)
// Get job status by ID
// Build: dotnet build
// Run: dotnet run <job_id>

using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

class Program
{
    static string PublicKey = Environment.GetEnvironmentVariable("UNSANDBOX_PUBLIC_KEY") ?? "unsb-pk-test-0000-0000-0001";
    static string SecretKey = Environment.GetEnvironmentVariable("UNSANDBOX_SECRET_KEY") ?? "unsb-sk-test0-vault-unlck-12345";

    static string HmacSha256Hex(string key, string data)
    {
        using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));
        var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(data));
        return Convert.ToHexString(hash).ToLower();
    }

    static async Task Main(string[] args)
    {
        if (args.Length == 0)
        {
            Console.WriteLine("Usage: dotnet run <job_id>");
            return;
        }

        using var client = new HttpClient();

        var jobId = args[0];
        var path = $"/jobs/{jobId}";
        var body = "";

        var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();
        var message = $"{timestamp}:GET:{path}:{body}";
        var signature = HmacSha256Hex(SecretKey, message);

        var url = "https://api.unsandbox.com" + path;
        using var request = new HttpRequestMessage(HttpMethod.Get, url);
        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", PublicKey);
        request.Headers.Add("X-Timestamp", timestamp);
        request.Headers.Add("X-Signature", signature);

        using var response = await client.SendAsync(request);
        var responseBody = await response.Content.ReadAsStringAsync();
        Console.WriteLine(responseBody);
    }
}
{
  "job_id": "c3d4e5f6-a7b8-9012-cdef-345678901234",
  "status": "completed",
  "created_at": "2025-01-11T12:00:00Z",
  "started_at": "2025-01-11T12:00:01Z",
  "completed_at": "2025-01-11T12:00:05Z",
  "success": true,
  "stdout": "Hello from unsandbox!\n",
  "stderr": "",
  "exit_code": 0,
  "language": "python",
  "network_mode": "zerotrust",
  "total_time_ms": 4021
}
GET https://api.unsandbox.com/jobs

List all active (pending or running) jobs for your API key. Useful for monitoring multiple async executions.

// C# with .NET 10 (modern async/await) - List all jobs
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

class Program
{
    static string PublicKey = Environment.GetEnvironmentVariable("UNSANDBOX_PUBLIC_KEY") ?? "unsb-pk-test-0000-0000-0001";
    static string SecretKey = Environment.GetEnvironmentVariable("UNSANDBOX_SECRET_KEY") ?? "unsb-sk-test0-vault-unlck-12345";

    static string HmacSha256Hex(string key, string data)
    {
        using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));
        return Convert.ToHexString(hmac.ComputeHash(Encoding.UTF8.GetBytes(data))).ToLower();
    }

    static async Task Main()
    {
        using var client = new HttpClient();
        var path = "/jobs";
        var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();
        var message = $"{timestamp}:GET:{path}:";
        var signature = HmacSha256Hex(SecretKey, message);

        using var request = new HttpRequestMessage(HttpMethod.Get, "https://api.unsandbox.com" + path);
        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", PublicKey);
        request.Headers.Add("X-Timestamp", timestamp);
        request.Headers.Add("X-Signature", signature);

        using var response = await client.SendAsync(request);
        Console.WriteLine(await response.Content.ReadAsStringAsync());
    }
}
[
  {
    "job_id": "ba943906-4ea6-a61c-9980-445f459368d",
    "status": "completed",
    "language": "python",
    "network_mode": "zerotrust",
    "created_at": "2025-01-11T12:00:00Z"
  },
  {
    "job_id": "c1d2e3f4-5678-90ab-cdef-1234567890ab",
    "status": "running",
    "language": "rust",
    "network_mode": "zerotrust",
    "created_at": "2025-01-11T12:01:00Z"
  }
]
DELETE https://api.unsandbox.com/jobs/{id}

Cancel a pending or running job. If the job is already executing, it will be terminated and partial output returned.

URL Parameters

Parameter Type Description
id string Job ID to cancel
// C# with .NET 10 (modern async/await) - Delete/cancel a job
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

class Program
{
    static string PublicKey = Environment.GetEnvironmentVariable("UNSANDBOX_PUBLIC_KEY") ?? "unsb-pk-test-0000-0000-0001";
    static string SecretKey = Environment.GetEnvironmentVariable("UNSANDBOX_SECRET_KEY") ?? "unsb-sk-test0-vault-unlck-12345";

    static string HmacSha256Hex(string key, string data) =>
        Convert.ToHexString(new HMACSHA256(Encoding.UTF8.GetBytes(key)).ComputeHash(Encoding.UTF8.GetBytes(data))).ToLower();

    static async Task Main(string[] args)
    {
        if (args.Length == 0) { Console.WriteLine("Usage: dotnet run <job_id>"); return; }

        using var client = new HttpClient();
        var jobId = args[0];
        var path = $"/jobs/{jobId}";
        var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();
        var message = $"{timestamp}:DELETE:{path}:";
        var signature = HmacSha256Hex(SecretKey, message);

        using var request = new HttpRequestMessage(HttpMethod.Delete, "https://api.unsandbox.com" + path);
        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", PublicKey);
        request.Headers.Add("X-Timestamp", timestamp);
        request.Headers.Add("X-Signature", signature);

        using var response = await client.SendAsync(request);
        Console.WriteLine(await response.Content.ReadAsStringAsync());
    }
}
{
  "job_id": "ba943906-4ea6-a61c-9980-445f459368d",
  "status": "cancelled",
  "message": "Job cancelled",
  "completed_at": "2025-01-11T12:00:30Z",
  "success": true,
  "stdout": "   Compiling hello v0.1.0 (/tmp)\n",
  "artifacts": []
}
Images Overview

Images are independent, transferable container snapshots that survive container deletion. Unlike snapshots (tied to container lifecycle), images can be:

  • Transferred between API keys
  • Shared with specific users via trust
  • Made public for the marketplace
  • Used to spawn new services

Visibility Levels

  • private โ€” Only owner can see/use (default)
  • unlisted โ€” Hidden from listing, but can be shared via trust
  • public โ€” Visible to all users (marketplace)
POST https://api.unsandbox.com/images

Publish an image from a service or snapshot.

Request Body

Parameter Type Required Description
source_type string "service" or "snapshot"
source_id string ID of service or snapshot
name string User-friendly name
description string Optional description

Request

{
  "source_type": "service",
  "source_id": "unsb-service-abc123",
  "name": "my-app-v1.0",
  "description": "Production-ready app image"
}

Response

{
  "id": "unsb-image-xyz789",
  "name": "my-app-v1.0",
  "description": "Production-ready app image",
  "source_type": "service",
  "source_id": "unsb-service-abc123",
  "fingerprint": "abc123def456...",
  "size_bytes": 524288000,
  "visibility": "private",
  "locked": false,
  "owner_api_key": "unsb-pk-xxxx-xxxx-xxxx-xxxx",
  "created_at": "2025-01-11T12:00:00Z"
}
GET https://api.unsandbox.com/images

List all images owned by or shared with your API key.

Related Endpoints

  • GET /images/public โ€” List marketplace images
  • GET /images/owned โ€” List only your images
  • GET /images/shared โ€” List images shared with you

Response

{
  "images": [
    {
      "id": "unsb-image-xyz789",
      "name": "my-app-v1.0",
      "fingerprint": "abc123...",
      "size_bytes": 524288000,
      "visibility": "private",
      "locked": false,
      "created_at": "2025-01-11T12:00:00Z"
    }
  ]
}
GET https://api.unsandbox.com/images/{id}

Get detailed information about an image.

URL Parameters

Parameter Type Description
id string Image ID (unsb-image-xxxx)

Response

{
  "id": "unsb-image-xyz789",
  "name": "my-app-v1.0",
  "description": "Production-ready app image",
  "source_type": "service",
  "source_id": "unsb-service-abc123",
  "fingerprint": "abc123def456...",
  "node": "cammy",
  "size_bytes": 524288000,
  "visibility": "private",
  "locked": false,
  "owner_api_key": "unsb-pk-xxxx-xxxx-xxxx-xxxx",
  "trusted_keys": [],
  "created_at": "2025-01-11T12:00:00Z"
}
POST https://api.unsandbox.com/images/{id}/spawn

Create a new service using this image as the base.

Request Body

Parameter Type Required Description
name string Service name
ports array Ports to expose
network_mode string "zerotrust" or "semitrusted"
bootstrap string Optional bootstrap script

Request

{
  "name": "my-app-instance",
  "ports": [8080],
  "network_mode": "semitrusted"
}

Response

{
  "service_id": "unsb-service-xyz789",
  "name": "my-app-instance",
  "source_image": "unsb-image-abc123",
  "state": "starting"
}
Image Management

Visibility

POST /images/{id}/visibility

{"visibility": "unlisted"}

Clone Image

POST /images/{id}/clone

{
  "name": "my-copy-of-app",
  "description": "My personal copy"
}

Lock/Unlock

  • POST /images/{id}/lock โ€” Prevent deletion
  • POST /images/{id}/unlock โ€” Allow deletion

Delete Image

DELETE /images/{id}

Grant Access

POST /images/{id}/grant

{
  "api_key": "unsb-pk-xxxx-xxxx-xxxx-xxxx"
}

Revoke Access

POST /images/{id}/revoke

{
  "api_key": "unsb-pk-xxxx-xxxx-xxxx-xxxx"
}

List Trusted Keys

GET /images/{id}/trusted

{
  "trusted_keys": [
    "unsb-pk-aaaa-bbbb-cccc-dddd",
    "unsb-pk-1111-2222-3333-4444"
  ]
}

Transfer Ownership

POST /images/{id}/transfer

{
  "to_api_key": "unsb-pk-xxxx-xxxx-xxxx-xxxx"
}
Error Codes

The API returns standard HTTP status codes along with detailed error information.

Code Status Description
200 OK Request succeeded (check 'success' field for execution result)
400 Bad Request Invalid request body or missing required parameters
401 Unauthorized Missing or invalid API key / signature
403 Forbidden Account suspended or feature not available
404 Not Found Job ID not found or expired
429 Too Many Requests Rate limit exceeded
500 Internal Error Server error, please retry

Error Response Format

{
  "error": "Invalid API key",
  "code": "INVALID_KEY",
  "details": "The provided public key does not exist"
}
Rate Limits

Rate limits are enforced per API key and vary by plan. See pricing for plan details โ†’

Rate Limit Headers

Response headers include rate limit information:

  • X-RateLimit-Limit โ€” Max requests per minute
  • X-RateLimit-Remaining โ€” Requests remaining
  • X-RateLimit-Reset โ€” Unix timestamp when limit resets

When rate limited, wait for the reset time or upgrade your plan for higher limits.

POST https://api.unsandbox.com/keys/validate

Validate your API key pair and retrieve its configuration including rate limits, concurrency limits, and expiration status.

This is useful for:

  • Checking if your key pair is valid
  • Viewing your current limits
  • Building key management interfaces
  • Monitoring key expiration

Authentication

Uses standard HMAC authentication (same as all other endpoints).

# Sign the request
TIMESTAMP=$(date +%s)
PUBLIC_KEY="unsb-pk-xxxx-xxxx-xxxx-xxxx"
SECRET_KEY="unsb-sk-xxxxx-xxxxx-xxxxx-xxxxx"
BODY="{}"
MESSAGE="${TIMESTAMP}:POST:/keys/validate:${BODY}"
SIGNATURE=$(echo -n "$MESSAGE" | openssl dgst -sha256 -hmac "$SECRET_KEY" | cut -d' ' -f2)

# Make the request
curl -X POST https://api.unsandbox.com/keys/validate \
  -H "Authorization: Bearer $PUBLIC_KEY" \
  -H "X-Timestamp: $TIMESTAMP" \
  -H "X-Signature: $SIGNATURE" \
  -H "Content-Type: application/json" \
  -d "$BODY"
{
  "valid": true,
  "public_key": "unsb-pk-xxxx-xxxx-xxxx-xxxx",
  "rate_per_minute": 60,
  "burst": 10,
  "concurrency_limit": 5,
  "expires_at": "2026-12-31T23:59:59Z",
  "tier": "Tier 3"
}
GET https://api.unsandbox.com/languages

Returns all supported programming languages and their aliases.

Common Aliases

  • node, js โ†’ javascript
  • ts โ†’ typescript
  • lisp โ†’ commonlisp

Response

{
  "languages": [
    "python",
    "javascript",
    "typescript",
    "ruby",
    "go",
    "rust",
    "c",
    "cpp"
  ],
  "aliases": {
    "js": "javascript",
    "node": "javascript",
    "ts": "typescript",
    "lisp": "commonlisp"
  },
  "count": 42
}
GET https://api.unsandbox.com/shells

Returns all supported shells and REPLs for interactive sessions, grouped by category.

Categories

  • unix โ€” bash, dash, sh, zsh, fish, ksh
  • python โ€” python, python3, ipython, bpython
  • javascript โ€” node
  • ruby โ€” ruby, irb
  • lisp โ€” scheme, guile, sbcl, clisp, clojure
  • erlang โ€” erl, iex
  • data โ€” r, julia, sqlite3

Response

{
  "shells": [
    "bash", "bpython", "clisp",
    "clojure", "dash", "fish",
    "ghci", "guile", "iex",
    "ipython", "irb", "julia"
  ],
  "categories": {
    "unix": ["bash", "dash", "sh", "zsh", "fish"],
    "python": ["python", "python3", "ipython", "bpython"],
    "javascript": ["node"],
    "ruby": ["ruby", "irb"],
    "lisp": ["scheme", "guile", "sbcl", "clisp", "clojure"]
  },
  "count": 35
}
GET https://api.unsandbox.com/health

Simple health check endpoint. Returns service status.

Response

{"status": "ok"}
GET https://api.unsandbox.com/cluster

Get information about the container pool and system status.

Network Modes

  • zerotrust_only โ€” Only isolated containers
  • semitrusted_only โ€” Only network-enabled containers
  • hybrid โ€” Both types available

Response

{
  "mode": "pooled",
  "pool_size": 288,
  "allocated": 5,
  "available": 280,
  "spawning": 0,
  "total_containers": 285,
  "network_mode": "hybrid",
  "network_breakdown": {
    "zerotrust": {
      "allocated": 2,
      "available": 140,
      "total": 142
    },
    "semitrusted": {
      "allocated": 3,
      "available": 140,
      "services": 1,
      "total": 143
    }
  }
}
GET https://api.unsandbox.com/pools

Get status of all registered container pools (horizontal scaling).

Response

{
  "pool_count": 2,
  "total_capacity": 288,
  "total_allocated": 8,
  "total_available": 280,
  "pools": [
    {
      "id": "pool_manager@cammy",
      "allocated": 4,
      "available": 140,
      "total": 144
    },
    {
      "id": "pool_manager@ai",
      "allocated": 4,
      "available": 140,
      "total": 144
    }
  ]
}
GET https://api.unsandbox.com/stats

Get detailed system statistics including load and container metrics.

Response

{
  "containers": 285,
  "load_1min": "2.15",
  "load_5min": "1.89",
  "load_15min": "1.45"
}
SDK Libraries (un-inception)

Full SDK implementations with HMAC authentication in 42 languages. Use these when you need programmatic access from your own code.

Browse all 42 language implementations โ†’

Usage Pattern

# Download the SDK for your language
wget https://unsandbox.com/cli/inception/un.py

# Use it in your code
# un.py provides: execute_code(), create_session(), create_service()

# Or run it as a CLI
python un.py script.py
python un.py -s python 'print("Hello")'

Ready to get started?

Get a free API key and start executing code in minutes.

Export Vault

Enter a password to encrypt your exported vault. You'll need this password to import the vault on another device.

Import Vault

Select an exported vault file and enter the export password to decrypt it.