DaytonaDocs

Quickstart

Create your first sandbox and run a command in under five minutes.

This guide walks you through the complete loop: get an API key, install an SDK, create a sandbox from a public image, run a command inside it, and clean up. By the end you will have executed code in a hardware-isolated microVM that took about 100 milliseconds to start.

1. Get an API key

Every request to Daytona is authenticated with a project-scoped API key. Sign in to the dashboard at https://app.rl.trydaytona.com, open your project, go to API Keys, and create a new key.

Keys look like rlp_... and are shown once at creation — copy the value immediately and store it somewhere safe. If you lose it, create a new key and delete the old one. See Authentication for the full picture.

Export the key so the examples below can pick it up:

cURL
export RLP_API_KEY="rlp_..."

2. Install the SDK

Daytona ships official SDKs for Python and TypeScript. Both wrap the same REST API, handle polling for sandbox readiness, and give you a high-level Sandbox object with process, filesystem, and git helpers.

Python
pip install rlp-sdk
TypeScript
npm install @rlp/sdk

3. Create a sandbox and run a command

The snippet below creates a sandbox from the public python:3.12-slim image, waits until it is ready, runs a shell command inside it, prints the output, and deletes the sandbox. Creation is asynchronous under the hood, but the SDK's create() polls until the sandbox is running (default timeout 60 seconds), so you get back a ready-to-use sandbox.

The client needs the API URL, your API key, and the toolbox URL (where in-sandbox calls like exec are sent). All three can be passed in code or read from the environment variables RLP_API_URL, RLP_API_KEY, and RLP_TOOLBOX_URL.

Python
from rlp import Daytona, DaytonaConfig, CreateSandboxFromImageParams
 
daytona = Daytona(DaytonaConfig(
    api_url="https://api.rl.trydaytona.com",
    api_key="rlp_...",          # or set RLP_API_KEY
))
 
sandbox = daytona.create(CreateSandboxFromImageParams(image="python:3.12-slim"))
 
result = sandbox.process.exec("echo hello from Daytona")
print(result.exit_code)  # 0
print(result.result)     # "hello from Daytona"
 
daytona.delete(sandbox)
TypeScript
import { Daytona } from '@rlp/sdk'
 
const daytona = new Daytona({
  apiUrl: 'https://api.rl.trydaytona.com',
  apiKey: 'rlp_...',            // or set RLP_API_KEY
})
 
const sandbox = await daytona.create({ image: 'python:3.12-slim' })
 
const result = await sandbox.process.executeCommand('echo hello from Daytona')
console.log(result.exitCode)  // 0
console.log(result.result)    // "hello from Daytona"
 
await daytona.delete(sandbox)

The first create with a new image is slower while Daytona pulls and converts it; every create after that starts from the fleet-wide cache in about 100 milliseconds. See Images for how caching works.

4. Same thing with cURL

If you prefer raw HTTP, the flow has three steps: create the sandbox, wait for it to reach running, then call the toolbox. POST /vms returns immediately with a vm_id and status: "pending"; the ?wait=running long-poll on GET /vms/:id blocks until the sandbox is ready (or the timeout elapses).

cURL
# 1. Create — returns vm_id, job_id, status "pending", and a one-time access_token
curl -s -X POST https://api.rl.trydaytona.com/vms \
  -H "Authorization: Bearer $RLP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"image": "python:3.12-slim"}'
 
# 2. Wait until running (long-poll)
export VM_ID="<vm_id from step 1>"
curl -s "https://api.rl.trydaytona.com/vms/$VM_ID?wait=running&timeout_ms=60000" \
  -H "Authorization: Bearer $RLP_API_KEY"
 
# 3. Run a command via the toolbox
curl -s -X POST "$RLP_TOOLBOX_URL/$VM_ID/process/execute" \
  -H "Authorization: Bearer $RLP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"command": "echo hello from Daytona"}'
 
# 4. Clean up
curl -s -X DELETE "https://api.rl.trydaytona.com/vms/$VM_ID" \
  -H "Authorization: Bearer $RLP_API_KEY"

Note: The create response also includes a one-time per-sandbox access_token (rlpv_...) for direct toolbox access. It is returned only once — store it if you plan to call the toolbox without a project API key. The SDKs capture and use it automatically.

Next steps

On this page