Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.declaw.ai/llms.txt

Use this file to discover all available pages before exploring further.

Use case

Every sandbox exposes a set of path-based URLs under api.declaw.ai for interacting with its filesystem, ports, and MCP endpoint. This example exercises each URL helper and round-trips a 50 MiB payload through the upload/download endpoints to verify streaming works end-to-end.
All URLs are path-based under api.declaw.ai. Subdomain-style URLs (<id>.api.declaw.ai) are not supported.

What you’ll learn

  • Using envd_api_url to get the base namespace URL for a sandbox
  • Building download and upload URLs with download_url(path) / upload_url(path)
  • Using get_host(port) for port-based reverse-proxy URLs
  • Using get_mcp_url() for the MCP convenience endpoint
  • Round-tripping a large payload through upload_url + download_url with SHA-256 verification

Prerequisites

export DECLAW_API_KEY="your-api-key"
export DECLAW_DOMAIN="your-declaw-instance.example.com:8080"

Code walkthrough

Create a sandbox and print all five URL helpers:
from declaw import Sandbox

sbx = Sandbox.create(template="base", timeout=600)
print(f"envd_api_url:   {sbx.envd_api_url}")
print(f"download_url:   {sbx.download_url('/tmp/hello.bin')}")
print(f"upload_url:     {sbx.upload_url('/tmp/hello.bin')}")
print(f"get_host(3000): {sbx.get_host(3000)}")
print(f"get_mcp_url():  {sbx.get_mcp_url()}")
Round-trip a 50 MiB payload through the raw file streaming endpoints:
import hashlib, os, random
import httpx

api_key = os.environ["DECLAW_API_KEY"]
headers = {"X-API-Key": api_key}
client = httpx.Client(http2=True, timeout=120)

random.seed(0xC0FFEE)
payload = bytes(random.randbytes(50 * 1024 * 1024))
want_hash = hashlib.sha256(payload).hexdigest()

# Upload
resp = client.put(
    sbx.upload_url("/tmp/roundtrip.bin"),
    content=payload,
    headers={**headers, "Content-Type": "application/octet-stream"},
)
assert resp.status_code == 200

# Download and verify
resp = client.get(
    sbx.download_url("/tmp/roundtrip.bin"),
    headers=headers,
)
got = resp.content
got_hash = hashlib.sha256(got).hexdigest()
assert got_hash == want_hash, "hash mismatch"
print(f"Round-trip PASS: {len(got)} bytes, sha256 matches.")
Port proxy — start a server inside the sandbox and access it through get_host():
# Port proxy — start a server and access it through get_host()
sbx.commands.run(
    "nohup perl -e '"
    "use IO::Socket::INET;"
    "my $s=IO::Socket::INET->new(Listen=>10,LocalPort=>3000,ReuseAddr=>1) or die;"
    "while(1){"
    "  my $c=$s->accept or next; <$c>;"
    "  1 while defined($_=<$c>) && /\\S/;"
    '  my $b="port-proxy-ok";'
    '  print $c "HTTP/1.1 200 OK\\r\\nContent-Length: ".length($b)."\\r\\nConnection: close\\r\\n\\r\\n$b";'
    "  close $c;"
    "}"
    "' &>/dev/null &"
)
import time; time.sleep(1)

resp = client.get(sbx.get_host(3000), headers=headers)
assert resp.status_code == 200
print(f"get_host(3000): {resp.status_code} body={resp.text!r}")
# get_host(3000): 200 body='port-proxy-ok'

Expected output

envd_api_url:   https://api.declaw.ai/sandboxes/sbx-.../...
download_url:   https://api.declaw.ai/sandboxes/sbx-.../files/raw?path=...
upload_url:     https://api.declaw.ai/sandboxes/sbx-.../files/raw?path=...
get_host(3000): https://api.declaw.ai/sandboxes/sbx-.../ports/3000
get_mcp_url():  https://api.declaw.ai/sandboxes/sbx-.../ports/50005/mcp

Round-trip PASS: 52428800 bytes, sha256 matches.

get_host(3000): 200 body='port-proxy-ok'

Full source

See cookbook/examples/url-helpers/main.py in the repo.