Execute code in 42+ languages with a single API call. Here's how to get started:
Get your API key
Sign up at unsandbox.com/console to get your API credentials.
Make your first request
Send code to the execute endpoint and get results back instantly.
Build something amazing
Use our sandboxed execution for AI agents, code playgrounds, educational tools, and more.
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
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.
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
}
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)'
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!
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
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
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
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 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"
}
]
}
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"}
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 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}
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 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]
}
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 servicesGET /services/{id}- Get service detailsPOST /services/{id}/freeze- Freeze servicePOST /services/{id}/unfreeze- Unfreeze servicePOST /services/{id}/lock- Lock servicePOST /services/{id}/unlock- Unlock serviceDELETE /services/{id}- Destroy service
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
}
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"}
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 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 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
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
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.
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
}
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"
}
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"
}
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
}
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 executerunning- Job currently executingcompleted- Job finished successfullyfailed- Job execution failedtimeout- Job exceeded TTL limitcancelled- 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
}
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"
}
]
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 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)
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"
}
List all images owned by or shared with your API key.
Related Endpoints
GET /images/publicโ List marketplace imagesGET /images/ownedโ List only your imagesGET /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 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"
}
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"
}
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 deletionPOST /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"
}
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 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 minuteX-RateLimit-Remainingโ Requests remainingX-RateLimit-Resetโ Unix timestamp when limit resets
When rate limited, wait for the reset time or upgrade your plan for higher limits.
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"
}
Returns all supported programming languages and their aliases.
Common Aliases
node,jsโjavascripttsโtypescriptlispโcommonlisp
Response
{
"languages": [
"python",
"javascript",
"typescript",
"ruby",
"go",
"rust",
"c",
"cpp"
],
"aliases": {
"js": "javascript",
"node": "javascript",
"ts": "typescript",
"lisp": "commonlisp"
},
"count": 42
}
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
}
Simple health check endpoint. Returns service status.
Response
{"status": "ok"}
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 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 detailed system statistics including load and container metrics.
Response
{
"containers": 285,
"load_1min": "2.15",
"load_5min": "1.89",
"load_15min": "1.45"
}
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.