Vertal Run documentation

Everything you need to run code safely with Vertal Run: from your first API call to running your own infrastructure.

Overview

Vertal Run is KUBO Protocol's secure code-execution platform. You send code; Vertal Run runs it in a fresh, isolated sandbox and returns the output. It was built for:

You can use it three ways: the HTTP API, the Python SDK, or the MCP server for AI agents. Supported languages today: Python 3.12, JavaScript (Node 22) and Bash 5.2.

Quickstart

1. Get an API key

Create a free account at vertalrun.com/entrar and generate a key in your dashboard, which also gives you ready-to-paste MCP, Claude Code, HTTP and SDK snippets. Keys look like kubo_sk_…. They are shown once and stored only as a SHA-256 hash, so keep yours in a secrets manager or an environment variable. An account can have up to 5 active keys and revoke any of them from the dashboard.

export KUBO_API_KEY="kubo_sk_..."

2. Run your first program

curl -X POST https://vertalrun.com/api/v1/executions \
  -H "Authorization: Bearer $KUBO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"language": "python", "code": "print(6 * 7)"}'
{
  "id": "exe_9392448a9b514e3f90193963b7d948d0",
  "status": "succeeded",
  "stdout": "42\n",
  "stderr": "",
  "exit_code": 0,
  "duration_ms": 265,
  "truncated": false,
  "usage": {"sandbox_seconds": 0.265},
  "request_id": "req_be05ea1492f949f8a0617a4f3cd738cc"
}

3. Try it in the browser

Open the playground, paste your key and press Run (or Ctrl/⌘ + Enter).

Core concepts

ConceptWhat it means
ExecutionOne program run. It has an id (exe_…), a status, output, an exit code and a duration. You can fetch it later.
SandboxA fresh, isolated environment created for each execution and destroyed afterwards. Nothing persists between executions.
TenantThe account an API key belongs to. Executions, usage and quotas are scoped to the tenant; tenants never see each other's data.
PlanFree, Pro or Enterprise. Sets daily quota, rate limit, maximum run time and sandbox memory.
Request IDEvery response carries request_id and an X-Request-Id header. Include it when you contact support.

Execution status values:

StatusMeaning
succeededThe program exited with code 0.
failedThe program exited with a non-zero code. Read stderr and exit_code.
timeoutThe program ran longer than timeout_s; the sandbox was killed. exit_code is null.
errorThe sandbox could not start. Retry later; this is not caused by your code.

Authentication

Send your key as a bearer token on every request except GET /health:

Authorization: Bearer kubo_sk_...

Operators create and revoke keys with the CLI. You can rotate your own key at any time with POST /v1/keys/rotate: you get a new key and the old one stops working immediately.

API reference

Base URL: https://vertalrun.com/api. Requests and responses are JSON (UTF-8).

POST/v1/executions

Runs code in a new sandbox and waits for it to finish.

FieldTypeRequiredDescription
languagestringyespython, javascript or bash.
codestringyesProgram source, up to 128 KB. It is passed on standard input.
timeout_snumbernoMaximum run time in seconds. Default 10, capped by your plan.

Response fields: id, status, stdout, stderr, exit_code, duration_ms, truncated (true if the output went over 64 KB per stream), usage.sandbox_seconds, request_id.

Safe retries. Add an Idempotency-Key header (1–255 characters: letters, digits, . _ : -). If the same key arrives again with the same body, you get the first result back with "idempotent_replay": true, and the code does not run or count against your quota again. The same key with a different body returns 409 idempotency_conflict.

curl https://vertalrun.com/api/v1/executions \
  -H "Authorization: Bearer $KUBO_API_KEY" \
  -H "Idempotency-Key: order-1234" \
  -H "Content-Type: application/json" \
  -d '{"language": "python", "code": "print(6 * 7)"}'

GET/v1/executions/{id}

Returns a stored execution, including language and created_at (Unix time). Only the tenant that created it can read it; anyone else gets 404.

GET/v1/usage

Returns today's usage (UTC) and your plan limits.

{
  "tenant": "kubo-vibe",
  "plan": "pro",
  "today": {"executions": 3, "sandbox_seconds": 2.635},
  "limits": {"executions_per_day": 10000, "requests_per_minute": 120, "max_timeout_s": 60}
}

POST/v1/keys/rotate

Issues a new key for your account (same plan) and revokes the key used for the call. The new key is shown once:

{"api_key": "kubo_sk_...", "key_id": "key_...", "revoked_key_id": "key_...", "plan": "pro"}

GET/v1/openapi.json

Public OpenAPI 3.1 description of the API. Import it into agent frameworks, API clients or code generators to get typed tools such as runCode.

GET/health

Public liveness check: {"status": "ok", "version": "0.2.0"}.

Errors

Errors use one shape, and never include stack traces or internal details:

{"error": {"code": "quota_exceeded", "message": "daily quota of 100 executions reached"}, "request_id": "req_..."}
HTTPCodeWhat to do
400invalid_language, invalid_code, invalid_timeout, invalid_json, invalid_content_length, invalid_idempotency_keyFix the request.
401unauthorizedCheck the key; it may be missing, wrong or revoked.
403forbiddenThe API origin was called directly. Use https://vertalrun.com/api.
404not_foundUnknown endpoint, or an execution of another tenant.
409idempotency_conflictYou reused an Idempotency-Key with a different body. Use a new key.
413code_too_large, body_too_largeKeep code under 128 KB and the body under 256 KB.
429rate_limitedToo many requests per minute. Wait for the Retry-After seconds and retry.
429quota_exceededDaily quota reached. Wait for the next UTC day or upgrade.
500internalRetry; contact support with the request_id if it persists.
503capacity_exhaustedAll sandboxes are busy. Retry after Retry-After seconds, with the same Idempotency-Key.
502 / 503api_unreachable, api_not_configuredThe platform behind the edge is down or not connected yet.

Plans & limits

PlanExecutions / dayRequests / minMax run timeSandbox memory
Free1001010 s256 MB
Pro10,00012060 s1 GB
Enterprise1,000,0001,200300 s4 GB

Every plan also has these limits:

Python SDK

The SDK has no dependencies (Python 3.10+). It is in the repository as vertal2kubo.client.

from vertal2kubo.client import KuboClient, KuboError

client = KuboClient("https://vertalrun.com/api", "kubo_sk_...")   # or KUBO_API_URL / KUBO_API_KEY env vars

result = client.run("print(sum(range(10)))", language="python", timeout_s=10)
print(result["status"], result["stdout"])                   # succeeded 45

print(client.get(result["id"])["created_at"])
print(client.usage()["today"])

client.run("print(1)", idempotency_key="job-42")             # retry-safe: same key, same result
client.rotate_key()                                         # new key; the client switches to it

try:
    client.run("x", timeout_s=999)
except KuboError as e:
    print(e.status, e.code, e.request_id)                   # 400 invalid_timeout req_...

CLI

# Operators (on the API host)
python -m vertal2kubo serve --host 0.0.0.0 --port 8080 --max-concurrent 4 --queue-timeout 30
python -m vertal2kubo serve --runtime runsc             # every sandbox under gVisor
python -m vertal2kubo create-key acme --plan pro        # prints kubo_sk_... once
python -m vertal2kubo revoke-key key_1a2b3c4d5e6f
python -m vertal2kubo purge --days 30                   # delete stored outputs older than 30 days

# Clients
export KUBO_API_URL=https://vertalrun.com/api KUBO_API_KEY=kubo_sk_...
python -m vertal2kubo run "print('hello')"
python -m vertal2kubo run "console.log(6*7)" --language javascript --timeout 5

MCP for AI agents

Vertal Run ships its own MCP server (stdio, JSON-RPC 2.0). Any MCP client, including KUBO IA, Claude and IDE assistants, gets two tools. Both go through the API, so the same key, quota and metering apply.

ToolInputOutput
run_codecode, language (default python), timeout_sstatus, stdout, stderr, exit code, duration. Marked as an error when the program fails or the API refuses.
get_usage—Today's executions, sandbox seconds, plan and limits.

Client configuration (Claude Desktop, Claude Code and others):

{
  "mcpServers": {
    "vertal-run": {
      "command": "python",
      "args": ["-m", "vertal2kubo.mcp"],
      "env": {"KUBO_API_URL": "https://vertalrun.com/api", "KUBO_API_KEY": "kubo_sk_..."}
    }
  }
}
Each run_code call starts from a clean sandbox. To carry data between steps, have the agent include it in the next program.

Security

Every execution runs in its own container, which is removed when the execution ends. The container has:

Operators can add a second wall with gVisor (serve --runtime runsc): a user-space kernel that intercepts every system call, so an exploit of the Linux kernel inside the sandbox does not reach the host.

Plain containers share the host kernel. For hostile, multi-tenant production workloads, run with gVisor (--runtime runsc); the roadmap adds a microVM (Firecracker) driver with hardware isolation. Report vulnerabilities privately through GitHub Security Advisories.

Self-hosting

You can run the whole platform on your own infrastructure.

  1. One-paste server (Hetzner): paste deploy/hetzner/cloud-init.yaml as the server's cloud config. On first boot it installs Docker and gVisor, closes every inbound port except SSH, and starts the API and a Cloudflare Tunnel. It then pulls each new API image from ghcr.io on its own. Operate it with vertal status, vertal key <name> pro and vertal logs.
  2. Any Linux VM with Docker: docker compose -f deploy/compose.yaml --env-file deploy/.env up -d --build (2 vCPU / 4 GB to start). This starts the API and a Cloudflare Tunnel; no inbound ports are needed.
  3. Edge + site: the cloudflare/ Worker deploys from GitHub Actions to vertalrun.com.

The step-by-step guide, with secrets and DNS, is in docs/DEPLOY.md.

Architecture

client / SDK / MCP agent
        │  https://vertalrun.com/api
        ▼
Cloudflare edge Worker ── serves vertalrun.com (site + docs)
        │  https://api.vertalrun.com  (+ edge secret, via Cloudflare Tunnel)
        ▼
Vertal Run API ── auth · plans · quotas · rate limits · metering (SQLite)
        │
        ▼
Sandbox engine ── one hardened container per execution
                  (pluggable driver: microVM next)

The engine's Driver interface lets a Firecracker microVM driver replace Docker without changing the API, SDK or MCP server. The full design is in ARCHITECTURE.md.

FAQ

Can my code access the internet?

No. Sandboxes have no network, by design.

Can I install packages?

Not at run time, because the filesystem is read-only and there is no network. The Python and Node standard libraries are available. Custom images with preinstalled packages are on the roadmap.

Does state persist between executions?

No. Each execution gets a clean sandbox.

How is usage counted?

Each execution counts once toward the daily quota (UTC). Sandbox time is reported as sandbox_seconds.

Is Vertal Run open source?

The Vertal Run code is MIT-licensed in kuboprotocol/Vertal2Kubo. Third-party components keep their own licenses.