> ## 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.

# URL helper methods

> Exercise the five URL-helper methods on Sandbox — envd_api_url, download_url, upload_url, get_host, and get_mcp_url.

## 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.

<Note>
  All URLs are path-based under `api.declaw.ai`. Subdomain-style
  URLs (`<id>.api.declaw.ai`) are not supported.
</Note>

## 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

<Snippet file="snippets/env-setup.mdx" />

## Code walkthrough

Create a sandbox and print all five URL helpers:

```python theme={null}
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:

```python theme={null}
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()`:

```python theme={null}
# 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.
