Execute código em mais de 42 linguagens com uma única chamada API. Veja como começar:
Obtenha sua chave API
Cadastre-se em unsandbox.com/console para obter suas credenciais API.
Faça sua primeira requisição
Envie código para o endpoint de execução e receba resultados instantaneamente.
Construa algo incrível
Use nossa execução em sandbox para agentes de machine learning, playgrounds de código, ferramentas educacionais e mais.
Baixar
# Linux x86_64
wget https://unsandbox.com/downloads/un
chmod +x un
# Move to PATH (optional)
sudo mv un /usr/local/bin/
Compilar do código fonte
# 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
Bibliotecas SDK (un-inception)
Para linguagens que precisam de acesso programático, use nossas implementações de SDK:
# 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
Todas as requisições API requerem autenticação por assinatura HMAC-SHA256 para segurança.
Obrigatório
| 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 |
Formato da Assinatura
HMAC-SHA256(secret_key, timestamp:METHOD:path:body)
Exemplo de string de assinatura:
1699564800:POST:/execute:{"language":"python","code":"print('hi')"}
Sua chave secreta nunca é transmitida. O servidor verifica assinaturas usando sua chave criptografada.
Execute qualquer arquivo de código. A linguagem é detectada automaticamente pela extensão do arquivo ou shebang.
Uso Básico
# 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
Com Opções
# 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
Resposta
A saída é transmitida diretamente para seu terminal:
$ un hello.py
Hello from unsandbox!
$ echo $?
0
Equivalente API
POST /execute
{
"success": true,
"stdout": "Hello from unsandbox!\n",
"stderr": "",
"exit_code": 0,
"language": "python",
"total_time_ms": 127
}
Execute trechos de código diretamente da linha de comando usando a flag -s.
Uso Básico
# 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") }'
Código Multilinha
# Using heredoc
un -s python <<'EOF'
import json
data = {"name": "unsandbox", "version": 2}
print(json.dumps(data, indent=2))
EOF
Linguagens Suportadas
Qualquer uma das 42 linguagens suportadas funciona com -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)'
Passe variáveis de ambiente para seu código usando a flag -e.
Variável Única
un -e DEBUG=1 script.py
un -e API_KEY=secret app.js
Múltiplas Variáveis
un -e DEBUG=1 -e NAME=World -e COUNT=42 script.py
Com Código Inline
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))"'
Exemplo
# 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}!")
Executar
$ un -e DEBUG=1 -e NAME=unsandbox config_demo.py
Debug mode enabled
Hello unsandbox!
Teleporte arquivos para o sandbox. O CLI usa a flag -f; a API usa o array input_files.
Uso do CLI
# 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
Limites
- Número máximo de arquivos
- Tamanho total máximo
- Tamanho máximo de arquivo único
# 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"
}
]
}
O conteúdo deve estar codificado em Base64.
Os arquivos são colocados no diretório de trabalho:
- Python:
open('data.csv') - Node.js:
fs.readFileSync('data.csv') - Ruby:
File.read('data.csv') - Go:
os.ReadFile("data.csv") - Bash:
cat data.csv
Teleporte arquivos para fora do sandbox. Use -a para coletar artefatos de /tmp/artifacts/ ou obter binários compilados.
Coletar Arquivos Gerados
# Files in /tmp/artifacts/ are collected
un -a -o ./outputs script.py
Binário pré-compilado
# 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
Compilação WebAssembly
# Compile to WASM (supported languages)
un --wasm -o ./wasm main.c
un --wasm -o ./wasm main.rs
Exemplo: Gerar e Coletar
# 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!")
Executar
$ un -a -o ./reports generate_report.py
Report generated!
$ ls ./reports
report.json
Zero Trust (padrão)
Isolamento completo de rede. Sem acesso à internet.
# Default - no network
un script.py
Semi-Confiável
Acesso à internet via proxy de saída.
# Enable network access
un -n semitrusted script.py
# Or with sessions
un session -n semitrusted
Casos de Uso
# 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
Inicie uma sessão de shell interativo em um contêiner sandbox.
Sessão Básica
# Default bash shell
un session
# Choose your shell
un session --shell zsh
un session --shell fish
Sessões REPL
# 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
Gravação de sessão
# 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
Equivalente API
POST /sessions
{
"session_id": "sess_xyz789",
"websocket_url": "wss://api.unsandbox.com/sessions/sess_xyz789/shell",
"status": "running"
}
Listar Trabalhos Ativos
un session --list
Saída
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
Obter Detalhes da Sessão
un session --info sess_abc123
Equivalente API
GET /sessions and GET /sessions/{id}
{
"sessions": [
{
"session_id": "sess_abc123",
"status": "running",
"network_mode": "zerotrust",
"shell": "python3"
}
]
}
Reconecte-se a sessões persistentes (requer --tmux ou --screen).
Criar Sessão Persistente
# With tmux (recommended)
un session --tmux
# With screen
un session --screen
Desconectar
# tmux: Press Ctrl+b then d
# screen: Press Ctrl+a then d
Desconto
# By session ID
un session --attach sess_abc123
# By container name
un session --attach unsb-vm-12345
Encerrar Sessão
# Kill by ID
un session --kill sess_abc123
# Kill by container name
un session --kill unsb-vm-12345
Equivalente API
DELETE /sessions/{id}
{"status": "terminated"}
Shells e REPLs disponíveis para sessões interativas:
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
Equivalente API
GET /shells retorna a lista completa de shells disponíveis.
Congele sessões para economizar recursos enquanto preserva o estado.
Congelar Sessão
un session --freeze sess_abc123
Descongelar Sessão
un session --unfreeze sess_abc123
Equivalente API
POST /sessions/{id}/freeze
{"status": "frozen"}
POST /sessions/{id}/unfreeze
{"status": "running", "unfreeze_time_ms": 1250}
Crie snapshots pontuais do estado da sessão.
Criar Snapshot
# With name
un session --snapshot sess_abc123 --name "before-upgrade"
# Quick snapshot (auto-generated name)
un session --snapshot sess_abc123
Restaurar a partir do Snapshot
un session --restore snap_xyz789
Equivalente API
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 automatic HTTPS at *.on.unsandbox.com. TLS certificates are provisioned automatically via Let's Encrypt. Custom domains supported via CNAME.
Serviço Básico
# 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"
Com Arquivos
# Deploy app tarball
un service --name blog --ports 8000 \
-f app.tar.gz \
--bootstrap "tar xzf app.tar.gz && cd app && ./start.sh"
Domínios Personalizados
un service --name api --ports 80 \
--domains api.example.com,www.api.example.com \
--bootstrap "./start.sh"
Nível de Serviço:
# 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
Equivalente API
POST /services
{
"service_id": "svc_abc123",
"name": "myapp",
"url": "https://myapp.on.unsandbox.com",
"status": "starting",
"ports": [80]
}
Listar Serviços
un service --list
Obter Info do Serviço
un service --info svc_abc123
Congelar/Descongelar Serviço
# Freeze (auto-unfreezes on HTTP request)
un service --freeze svc_abc123
# Manual unfreeze
un service --unfreeze svc_abc123
Bloquear/Desbloquear
# Prevent accidental deletion
un service --lock svc_abc123
# Allow deletion
un service --unlock svc_abc123
Destruir Serviço
un service --destroy svc_abc123
Endpoint de API acessado
GET /services- Listar todos os serviçosGET /services/{id}- Obter detalhes do serviçoPOST /services/{id}/freeze- Congelar serviçoPOST /services/{id}/unfreeze- Descongelar serviçoPOST /services/{id}/lock- Bloquear serviçoPOST /services/{id}/unlock- Desbloquear CofreDELETE /services/{id}- Destruir serviço
Descongelamento Automático
Quando habilitado, serviços congelados acordam automaticamente quando recebem uma requisição HTTP.
# Enable auto-unfreeze (default for new services)
un service --auto-unfreeze svc_abc123
# Disable auto-unfreeze
un service --no-auto-unfreeze svc_abc123
Exibição da Página de Congelamento
Controle o que os visitantes veem ao acessar um serviço congelado.
# Show HTML payment page (default)
un service --show-freeze-page svc_abc123
# Return JSON error instead
un service --no-show-freeze-page svc_abc123
Equivalente API
PATCH /services/{id}
# Enable auto-unfreeze
{"unfreeze_on_demand": true}
# Disable freeze page (return JSON error)
{"show_freeze_page": false}
Comportamento da Página de Congelamento
show_freeze_page: true- Exibe página HTML com opções de pagamentoshow_freeze_page: false- Retorna JSON: {"error": "service_frozen"}
Use o modo JSON para serviços API onde respostas HTML quebrariam os clientes.
Ver Logs de Bootstrap
# All logs
un service --logs svc_abc123
# Last 9000 lines
un service --tail svc_abc123
Executar Código
# 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'
Exportar Script de Bootstrap
# Print to stdout
un service --dump-bootstrap svc_abc123
# Save to file
un service --dump-bootstrap svc_abc123 backup.sh
Equivalente API
GET /services/{id}/logs
{"log": "Bootstrap started...\nInstalling...\nServer listening on port 80"}
POST /services/{id}/execute
{
"stdout": "...",
"stderr": "",
"exit_code": 0
}
Armazenamento criptografado para segredos do serviço. Variáveis são injetadas quando o contêiner inicia ou descongela.
Definir Variáveis de Ambiente
# 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
Obter Status do Cofre
GET /services/{id}/env
{
"exists": true,
"variable_count": 3,
"updated_at": "2026-01-14T12:00:00Z"
}
Exportar Cofre Descriptografado
POST /services/{id}/env/export
{"env": "DATABASE_URL=postgres://...\nAPI_SECRET=abc123\nDEBUG=false"}
Excluir
DELETE /services/{id}/env
{"status": "deleted"}
Reexecutar Bootstrap
# Re-run existing bootstrap
un service --redeploy svc_abc123
# Redeploy with new bootstrap
un service --redeploy svc_abc123 --bootstrap ./new-setup.sh
Criar Snapshot do Serviço
# Standard snapshot (pauses briefly)
un service --snapshot svc_abc123 --name "stable-v1.0"
# Hot snapshot (no pause)
un service --snapshot svc_abc123 --hot
Equivalente API
POST /services/{id}/redeploy
{"state": "redeploying"}
POST /services/{id}/snapshot
{
"snapshot_id": "snap_def456",
"name": "stable-v1.0",
"size_bytes": 104857600
}
Listar Todos os Snapshots
un snapshot --list
Saída
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
Obter Info do Snapshot
un snapshot --info snap_a1b2-c3d4-e5f6-g7h8
Excluir Snapshot
un snapshot --delete snap_a1b2-c3d4-e5f6-g7h8
Equivalente API
GET /snapshots
{
"snapshots": [
{
"snapshot_id": "snap_abc123",
"name": "before-upgrade",
"source_type": "session",
"size_bytes": 52428800
}
]
}
Restaurar para o Original
# Restore session from snapshot
un session --restore snap_abc123
# Restore service from snapshot
un service --restore snap_def456
Clonar para Novo Contêiner
POST /snapshots/{id}/clone
# Clone to new session
{
"type": "session",
"shell": "bash"
}
# Clone to new service
{
"type": "service",
"name": "cloned-app"
}
Resposta
Clonar para sessão:
{"session_id": "sess_new123"}
Clonar para serviço:
{
"service_id": "svc_new456",
"url": "https://cloned-app.on.unsandbox.com"
}
Bloquear/Desbloquear Snapshots
POST /snapshots/{id}/lock - Impedir exclusão
POST /snapshots/{id}/unlock - Permitir exclusão
Todas as requisições API devem ser feitas para:
https://api.unsandbox.com
A API suporta dois modos de rede:
- zerotrust (default) — Sem acesso à rede, execução totalmente isolada
- semitrusted — Acesso à rede via proxy de saída, pode acessar a internet
Os exemplos em V abaixo requerem as seguintes bibliotecas de terceiros:
net.http (built-in)json (built-in)
Certifique-se de que estes pacotes estão instalados em seu ambiente antes de executar os exemplos.
Execute código imediatamente e aguarde os resultados. Ideal para scripts rápidos e uso interativo.
Parâmetros da Requisição
| 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 | Arquivos para upload (veja Arquivos de Entrada) |
import net.http
import json
import crypto.hmac
import crypto.sha256
import os
import time
fn get_public_key() string {
return os.getenv_opt('UNSANDBOX_PUBLIC_KEY') or { 'unsb-pk-test-0000-0000-0001' }
}
fn get_secret_key() string {
return os.getenv_opt('UNSANDBOX_SECRET_KEY') or { 'unsb-sk-test0-vault-unlck-12345' }
}
fn sign_request(method string, path string, body string) (string, string) {
timestamp := '${time.now().unix()}'
message := '${timestamp}:${method}:${path}:${body}'
signature := hmac.new(get_secret_key().bytes(), message.bytes(), sha256.new).hex()
return timestamp, signature
}
struct ExecuteRequest {
language string
code string
}
fn main() {
path := '/execute'
request := ExecuteRequest{
language: 'python'
code: 'print("Hello from unsandbox!")'
}
payload := json.encode(request)
timestamp, signature := sign_request('POST', path, payload)
mut req := http.new_request(.post, 'https://api.unsandbox.com${path}', payload)!
req.add_header(.content_type, 'application/json')
req.add_header(.authorization, 'Bearer ${get_public_key()}')
req.add_custom_header('X-Timestamp', timestamp)!
req.add_custom_header('X-Signature', signature)!
resp := req.do()!
result := json.decode(map[string]json.Any, resp.body)!
exit_code := result['exit_code']!.int()
if exit_code == 0 {
println('Output: ${result['stdout']!.str()}')
} else {
println('Error: ${result['stderr']!.str()}')
}
}
{
"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.
Parâmetros da Requisição
| 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 | Arquivos para upload (veja Arquivos de Entrada) |
import net.http
import json
import crypto.hmac
import crypto.sha256
import os
import time
fn get_public_key() string {
return os.getenv_opt('UNSANDBOX_PUBLIC_KEY') or { 'unsb-pk-test-0000-0000-0001' }
}
fn get_secret_key() string {
return os.getenv_opt('UNSANDBOX_SECRET_KEY') or { 'unsb-sk-test0-vault-unlck-12345' }
}
fn sign_request(method string, path string, body string) (string, string) {
timestamp := '${time.now().unix()}'
message := '${timestamp}:${method}:${path}:${body}'
signature := hmac.new(get_secret_key().bytes(), message.bytes(), sha256.new).hex()
return timestamp, signature
}
struct ExecuteAsyncRequest {
language string
code string
ttl int
}
fn main() {
// Submit job
path := '/execute/async'
request := ExecuteAsyncRequest{
language: 'python'
code: 'print("Computing...")'
ttl: 300
}
payload := json.encode(request)
timestamp, signature := sign_request('POST', path, payload)
mut req := http.new_request(.post, 'https://api.unsandbox.com${path}', payload)!
req.add_header(.content_type, 'application/json')
req.add_header(.authorization, 'Bearer ${get_public_key()}')
req.add_custom_header('X-Timestamp', timestamp)!
req.add_custom_header('X-Signature', signature)!
resp := req.do()!
job := json.decode(map[string]json.Any, resp.body)!
job_id := job['job_id']!.str()
println('Job submitted: ${job_id}')
// Poll for results
status_path := '/jobs/${job_id}'
for {
time.sleep(1 * time.second)
ts, sig := sign_request('GET', status_path, '')
mut status_req := http.new_request(.get, 'https://api.unsandbox.com${status_path}', '')!
status_req.add_header(.authorization, 'Bearer ${get_public_key()}')
status_req.add_custom_header('X-Timestamp', ts)!
status_req.add_custom_header('X-Signature', sig)!
status_resp := status_req.do()!
status := json.decode(map[string]json.Any, status_resp.body)!
state := status['status']!.str()
if state == 'completed' {
exit_code := status['exit_code']!.int()
if exit_code == 0 {
println('Output: ${status['stdout']!.str()}')
} else {
println('Error: ${status['stderr']!.str()}')
}
break
} else if state == 'timeout' || state == 'cancelled' {
println('Job ${state}')
break
}
}
}
{
"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 |
import net.http
import json
import crypto.hmac
import crypto.sha256
import os
import time
fn get_public_key() string {
return os.getenv_opt('UNSANDBOX_PUBLIC_KEY') or { 'unsb-pk-test-0000-0000-0001' }
}
fn get_secret_key() string {
return os.getenv_opt('UNSANDBOX_SECRET_KEY') or { 'unsb-sk-test0-vault-unlck-12345' }
}
fn sign_request(method string, path string, body string) (string, string) {
timestamp := '${time.now().unix()}'
message := '${timestamp}:${method}:${path}:${body}'
signature := hmac.new(get_secret_key().bytes(), message.bytes(), sha256.new).hex()
return timestamp, signature
}
fn main() {
path := '/run'
code := '#!/usr/bin/env python3
print("Language auto-detected!")'
timestamp, signature := sign_request('POST', path, code)
mut req := http.new_request(.post, 'https://api.unsandbox.com${path}', code)!
req.add_header(.content_type, 'text/plain')
req.add_header(.authorization, 'Bearer ${get_public_key()}')
req.add_custom_header('X-Timestamp', timestamp)!
req.add_custom_header('X-Signature', signature)!
resp := req.do()!
result := json.decode(map[string]json.Any, resp.body)!
println('Detected: ${result['detected_language']!.str()}')
println('Output: ${result['stdout']!.str()}')
}
{
"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 |
import net.http
import json
import crypto.hmac
import crypto.sha256
import os
import time
fn get_public_key() string {
return os.getenv_opt('UNSANDBOX_PUBLIC_KEY') or { 'unsb-pk-test-0000-0000-0001' }
}
fn get_secret_key() string {
return os.getenv_opt('UNSANDBOX_SECRET_KEY') or { 'unsb-sk-test0-vault-unlck-12345' }
}
fn sign_request(method string, path string, body string) (string, string) {
timestamp := '${time.now().unix()}'
message := '${timestamp}:${method}:${path}:${body}'
signature := hmac.new(get_secret_key().bytes(), message.bytes(), sha256.new).hex()
return timestamp, signature
}
fn main() {
path := '/run/async'
code := '#!/usr/bin/env ruby
puts "Running async with auto-detect!"'
// Submit job
timestamp, signature := sign_request('POST', path, code)
mut req := http.new_request(.post, 'https://api.unsandbox.com${path}', code)!
req.add_header(.content_type, 'text/plain')
req.add_header(.authorization, 'Bearer ${get_public_key()}')
req.add_custom_header('X-Timestamp', timestamp)!
req.add_custom_header('X-Signature', signature)!
resp := req.do()!
job := json.decode(map[string]json.Any, resp.body)!
job_id := job['job_id']!.str()
println('Job submitted: ${job_id}')
// Poll for results
status_path := '/jobs/${job_id}'
for {
time.sleep(1 * time.second)
ts, sig := sign_request('GET', status_path, '')
mut status_req := http.new_request(.get, 'https://api.unsandbox.com${status_path}', '')!
status_req.add_header(.authorization, 'Bearer ${get_public_key()}')
status_req.add_custom_header('X-Timestamp', ts)!
status_req.add_custom_header('X-Signature', sig)!
status_resp := status_req.do()!
status := json.decode(map[string]json.Any, status_resp.body)!
state := status['status']!.str()
if state == 'completed' {
println('Detected: ${status['detected_language']!.str()}')
exit_code := status['exit_code']!.int()
if exit_code == 0 {
println('Output: ${status['stdout']!.str()}')
} else {
println('Error: ${status['stderr']!.str()}')
}
break
} else if state == 'timeout' || state == 'cancelled' {
println('Job ${state}')
break
}
}
}
{
"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
import net.http
import json
import crypto.hmac
import crypto.sha256
import os
import time
fn get_public_key() string {
return os.getenv_opt('UNSANDBOX_PUBLIC_KEY') or { 'unsb-pk-test-0000-0000-0001' }
}
fn get_secret_key() string {
return os.getenv_opt('UNSANDBOX_SECRET_KEY') or { 'unsb-sk-test0-vault-unlck-12345' }
}
fn sign_request(method string, path string, body string) (string, string) {
timestamp := '${time.now().unix()}'
message := '${timestamp}:${method}:${path}:${body}'
signature := hmac.new(get_secret_key().bytes(), message.bytes(), sha256.new).hex()
return timestamp, signature
}
fn main() {
job_id := 'job_1234567890_abc'
path := '/jobs/${job_id}'
timestamp, signature := sign_request('GET', path, '')
mut req := http.new_request(.get, 'https://api.unsandbox.com${path}', '')!
req.add_header(.authorization, 'Bearer ${get_public_key()}')
req.add_custom_header('X-Timestamp', timestamp)!
req.add_custom_header('X-Signature', signature)!
resp := req.do()!
job := json.decode(map[string]json.Any, resp.body)!
println('Status: ${job['status']!.str()}')
if job['status']!.str() == 'completed' {
println('Exit code: ${job['exit_code']!.int()}')
println('Output: ${job['stdout']!.str()}')
}
}
{
"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.
import net.http
import json
import crypto.hmac
import crypto.sha256
import os
import time
fn get_public_key() string {
return os.getenv_opt('UNSANDBOX_PUBLIC_KEY') or { 'unsb-pk-test-0000-0000-0001' }
}
fn get_secret_key() string {
return os.getenv_opt('UNSANDBOX_SECRET_KEY') or { 'unsb-sk-test0-vault-unlck-12345' }
}
fn sign_request(method string, path string, body string) (string, string) {
timestamp := '${time.now().unix()}'
message := '${timestamp}:${method}:${path}:${body}'
signature := hmac.new(get_secret_key().bytes(), message.bytes(), sha256.new).hex()
return timestamp, signature
}
fn main() {
path := '/jobs'
timestamp, signature := sign_request('GET', path, '')
mut req := http.new_request(.get, 'https://api.unsandbox.com${path}', '')!
req.add_header(.authorization, 'Bearer ${get_public_key()}')
req.add_custom_header('X-Timestamp', timestamp)!
req.add_custom_header('X-Signature', signature)!
resp := req.do()!
jobs := json.decode([]map[string]json.Any, resp.body)!
for job in jobs {
println('${job['job_id']!.str()}: ${job['status']!.str()} (${job['language']!.str()})')
}
}
[
{
"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 |
import net.http
import json
import crypto.hmac
import crypto.sha256
import os
import time
fn get_public_key() string {
return os.getenv_opt('UNSANDBOX_PUBLIC_KEY') or { 'unsb-pk-test-0000-0000-0001' }
}
fn get_secret_key() string {
return os.getenv_opt('UNSANDBOX_SECRET_KEY') or { 'unsb-sk-test0-vault-unlck-12345' }
}
fn sign_request(method string, path string, body string) (string, string) {
timestamp := '${time.now().unix()}'
message := '${timestamp}:${method}:${path}:${body}'
signature := hmac.new(get_secret_key().bytes(), message.bytes(), sha256.new).hex()
return timestamp, signature
}
fn main() {
job_id := 'job_1234567890_abc'
path := '/jobs/${job_id}'
timestamp, signature := sign_request('DELETE', path, '')
mut req := http.new_request(.delete, 'https://api.unsandbox.com${path}', '')!
req.add_header(.authorization, 'Bearer ${get_public_key()}')
req.add_custom_header('X-Timestamp', timestamp)!
req.add_custom_header('X-Signature', signature)!
resp := req.do()!
result := json.decode(map[string]json.Any, resp.body)!
println('Cancelled: ${result['message']!.str()}')
if 'stdout' in result {
println('Partial output: ${result['stdout']!.str()}')
}
}
{
"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": []
}
Imagens são snapshots de contêiner independentes e transferíveis que sobrevivem à exclusão do contêiner. Diferente dos snapshots (vinculados ao ciclo de vida do contêiner), imagens podem ser:
- Transferido entre chaves API
- Compartilhado com usuários específicos via confiança
- Tornado público para o marketplace
- Usado para criar novos serviços
Níveis de Visibilidade
- private — Somente o proprietário pode ver/usar (padrão)
- unlisted — Oculto da listagem, mas pode ser compartilhado via confiança
- public — Visível para todos os usuários (marketplace)
Publique uma imagem a partir de um serviço ou snapshot.
Corpo da Requisição
| 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 |
Metadados de Requisição:
{
"source_type": "service",
"source_id": "unsb-service-abc123",
"name": "my-app-v1.0",
"description": "Production-ready app image"
}
Resposta
{
"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"
}
Liste todas as imagens que pertencem à ou foram compartilhadas com sua chave API.
Endpoints Relacionados
GET /images/public— Listar imagens do marketplaceGET /images/owned— Listar apenas suas imagensGET /images/shared— Listar imagens compartilhadas com você
Resposta
{
"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"
}
]
}
Obtenha informações detalhadas sobre uma imagem.
Parâmetros de URL
| Parameter | Type | Description |
|---|---|---|
id |
string | Image ID (unsb-image-xxxx) |
Resposta
{
"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"
}
Crie um novo serviço usando esta imagem como base.
Corpo da Requisição
| Parameter | Type | Required | Description |
|---|---|---|---|
name |
string | Service name | |
ports |
array | Ports to expose | |
network_mode |
string | "zerotrust" or "semitrusted" | |
bootstrap |
string | Optional bootstrap script |
Metadados de Requisição:
{
"name": "my-app-instance",
"ports": [8080],
"network_mode": "semitrusted"
}
Resposta
{
"service_id": "unsb-service-xyz789",
"name": "my-app-instance",
"source_image": "unsb-image-abc123",
"state": "starting"
}
Visibilidade e Compartilhamento
POST /images/{id}/visibility
{"visibility": "unlisted"}
Clonar Imagem
POST /images/{id}/clone
{
"name": "my-copy-of-app",
"description": "My personal copy"
}
Bloquear/Desbloquear
POST /images/{id}/lock— Impedir exclusãoPOST /images/{id}/unlock— Permitir exclusão
Excluir
DELETE /images/{id}
Conceder Acesso
POST /images/{id}/grant
{
"api_key": "unsb-pk-xxxx-xxxx-xxxx-xxxx"
}
Revogar Acesso
POST /images/{id}/revoke
{
"api_key": "unsb-pk-xxxx-xxxx-xxxx-xxxx"
}
Listar Chaves de Confiança
GET /images/{id}/trusted
{
"trusted_keys": [
"unsb-pk-aaaa-bbbb-cccc-dddd",
"unsb-pk-1111-2222-3333-4444"
]
}
Transferir Propriedade
POST /images/{id}/transfer
{
"to_api_key": "unsb-pk-xxxx-xxxx-xxxx-xxxx"
}
A API retorna códigos de status HTTP padrão junto com informações detalhadas de erro.
| Code | Status | Description |
|---|---|---|
200 |
OK | Requisição bem-sucedida (verifique o campo 'success' para o resultado da execução) |
400 |
Bad Request | Corpo da requisição inválido ou parâmetros obrigatórios ausentes |
401 |
Unauthorized | Chave API / assinatura ausente ou inválida |
403 |
Forbidden | Conta suspensa ou recurso não disponível |
404 |
Not Found | ID do job não encontrado ou expirado |
429 |
Too Many Requests | Limite de taxa excedido |
500 |
Internal Error | Erro no servidor, por favor tente novamente |
Formato de Resposta de Erro
{
"error": "Invalid API key",
"code": "INVALID_KEY",
"details": "The provided public key does not exist"
}
Os limites de taxa são aplicados por chave API e variam por plano. Veja os preços para detalhes do plano →
Limite de Requisições:
Os cabeçalhos de resposta incluem informações de limite de taxa:
X-RateLimit-Limit— requisições/minutoX-RateLimit-Remaining— Requisições restantesX-RateLimit-Reset— Timestamp Unix quando o limite é redefinido
Quando limitado pela taxa, aguarde o tempo de redefinição ou faça upgrade do seu plano para limites maiores.
Valide seu par de chaves API e recupere sua configuração incluindo limites de taxa, limites de concorrência e status de expiração.
Isso é útil para:
- Verificando se seu par de chaves é válido
- Visualizando seus limites atuais
- Construindo interfaces de gerenciamento de chaves
- Monitorando expiração da chave
Autenticação
Usa autenticação HMAC padrão (igual a todos os outros 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"
}
Retorna todas as linguagens de programação suportadas e seus aliases.
Aliases Comuns
node,js→javascriptts→typescriptlisp→commonlisp
Resposta
{
"languages": [
"python",
"javascript",
"typescript",
"ruby",
"go",
"rust",
"c",
"cpp"
],
"aliases": {
"js": "javascript",
"node": "javascript",
"ts": "typescript",
"lisp": "commonlisp"
},
"count": 42
}
Retorna todos os shells e REPLs suportados para sessões interativas, agrupados por categoria.
Categorias
- 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
Resposta
{
"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
}
Endpoint simples de verificação de integridade. Retorna o status do serviço.
Resposta
{"status": "ok"}
Obtenha informações sobre o pool de contêineres e status do sistema.
Modos de Rede
- zerotrust_only — Only isolated containers
- semitrusted_only — Only network-enabled containers
- hybrid — Both types available
Resposta
{
"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
}
}
}
Obtenha o status de todos os pools de contêineres registrados (escalabilidade horizontal).
Resposta
{
"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
}
]
}
Obtenha estatísticas detalhadas do sistema incluindo carga e métricas de contêineres.
Resposta
{
"containers": 285,
"load_1min": "2.15",
"load_5min": "1.89",
"load_15min": "1.45"
}
Implementações completas de SDK com autenticação HMAC em 42 linguagens. Use quando precisar de acesso programático a partir do seu próprio código.
Navegue por todas as 42 implementações de linguagens →
Padrão de Uso
# 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")'
Pronto para começar?
Obtenha uma chave API gratuita e comece a executar código em minutos.