Expose ports from a box with public URLs. Each public URL maps to a specific port and can optionally require authentication.
Quickstart
Create a public URL
Start a web server inside your box and create a public URL to access it.
import { Agent, Box } from "@upstash/box"
const box = await Box.create({ runtime: "node" })
// Start a web server on port 3000
await box.exec.command("cd /work && npm install express")
await box.files.write({
path: "/work/server.js",
content: `
const express = require('express')
const app = express()
app.get('/', (req, res) => res.send('Hello from Box!'))
app.listen(3000)
`,
})
await box.exec.command("node /work/server.js &")
// Create a public URL
const publicUrl = await box.getPublicURL(3000)
console.log(publicUrl.url)
// → https://{BOX_ID}-3000.preview.box.upstash.com
from upstash_box import Box
box = Box.create(runtime="node")
# Start a web server on port 3000
box.exec.command("cd /work && npm install express")
box.files.write(
path="/work/server.js",
content="""
const express = require('express')
const app = express()
app.get('/', (req, res) => res.send('Hello from Box!'))
app.listen(3000)
""",
)
box.exec.command("node /work/server.js &")
# Create a public URL
public_url = box.get_public_url(3000)
print(public_url.url)
# -> https://{BOX_ID}-3000.preview.box.upstash.com
Add authentication
Protect your public URL with bearer token or basic authentication.
// With bearer token
const publicUrl = await box.getPublicURL(3000, { bearerToken: true })
console.log(publicUrl.token) // Use this in Authorization header
// → "63d8b153..."
// With basic auth
const publicUrl = await box.getPublicURL(8080, { basicAuth: true })
console.log(publicUrl.username) // → "user"
console.log(publicUrl.password) // → "f0f145f0..."
# With bearer token
public_url = box.get_public_url(3000, bearer_token=True)
print(public_url.token) # Use this in Authorization header
# -> "63d8b153..."
# With basic auth
public_url = box.get_public_url(8080, basic_auth=True)
print(public_url.username) # -> "user"
print(public_url.password) # -> "f0f145f0..."
API
Create Public URL
Creates a public URL that exposes a port on your box. Returns the URL and authentication credentials if requested.
const publicUrl = await box.getPublicURL(3000)
console.log(publicUrl.url)
// → https://{BOX_ID}-3000.preview.box.upstash.com
public_url = box.get_public_url(3000)
print(public_url.url)
# -> https://{BOX_ID}-3000.preview.box.upstash.com
With Bearer Token
Add bearerToken: true to require an authorization header when accessing the public URL.
const publicUrl = await box.getPublicURL(3000, { bearerToken: true })
console.log(publicUrl.token)
// → "63d8b153..."
// Access the public URL:
// curl -H "Authorization: Bearer 63d8b153..." https://{BOX_ID}-3000.preview.box.upstash.com
public_url = box.get_public_url(3000, bearer_token=True)
print(public_url.token)
# -> "63d8b153..."
# Access the public URL:
# curl -H "Authorization: Bearer 63d8b153..." https://{BOX_ID}-3000.preview.box.upstash.com
With Basic Authentication
Add basicAuth: true to require username and password when accessing the public URL.
const publicUrl = await box.getPublicURL(8080, { basicAuth: true })
console.log(publicUrl.username) // → "user"
console.log(publicUrl.password) // → "f0f145f0..."
// Access the public URL:
// curl -u user:f0f145f0... https://{BOX_ID}-8080.preview.box.upstash.com
public_url = box.get_public_url(8080, basic_auth=True)
print(public_url.username) # -> "user"
print(public_url.password) # -> "f0f145f0..."
# Access the public URL:
# curl -u user:f0f145f0... https://{BOX_ID}-8080.preview.box.upstash.com
With Both Auth Methods
Enable both authentication methods. Either one will work when accessing the public URL.
const publicUrl = await box.getPublicURL(8080, { bearerToken: true, basicAuth: true })
console.log(publicUrl.token) // → "63d8b153..."
console.log(publicUrl.username) // → "user"
console.log(publicUrl.password) // → "f0f145f0..."
public_url = box.get_public_url(8080, bearer_token=True, basic_auth=True)
print(public_url.token) # -> "63d8b153..."
print(public_url.username) # -> "user"
print(public_url.password) # -> "f0f145f0..."
List Public URLs
Get all active public URLs for this box.
const { publicURLs } = await box.listPublicURLs()
console.log(publicURLs)
// [
// { url: "https://{BOX_ID}-3000.preview.box.upstash.com", port: 3000 },
// { url: "https://{BOX_ID}-8080.preview.box.upstash.com", port: 8080 },
// ]
result = box.list_public_urls()
print(result["public_urls"])
# [
# PublicURL(url="https://{BOX_ID}-3000.preview.box.upstash.com", port=3000),
# PublicURL(url="https://{BOX_ID}-8080.preview.box.upstash.com", port=8080),
# ]
Delete Public URL
Remove a public URL by port number.
await box.deletePublicURL(3000)
box.delete_public_url(3000)
Behavior
One Public URL Per Port
Creating a public URL for a port that already has one will overwrite the previous one, including any auth credentials.
// First public URL
const publicUrl1 = await box.getPublicURL(3000)
// Second public URL overwrites the first one
const publicUrl2 = await box.getPublicURL(3000, { bearerToken: true })
// publicUrl1.url is no longer accessible
# First public URL
public_url1 = box.get_public_url(3000)
# Second public URL overwrites the first one
public_url2 = box.get_public_url(3000, bearer_token=True)
# public_url1.url is no longer accessible
Public URL Lifecycle
Public URLs expire automatically when:
- The box is paused
- The box is deleted
Auto-Resume
Creating a public URL on a paused box automatically resumes it.
await box.pause()
// This will resume the box
const publicUrl = await box.getPublicURL(3000)
box.pause()
# This will resume the box
public_url = box.get_public_url(3000)
Examples
Expose an agent-built app
Let an agent build a web app, then create a public URL to test it.
import { Agent, Box } from "@upstash/box"
const box = await Box.create({
runtime: "node",
agent: {
harness: Agent.ClaudeCode,
model: "anthropic/claude-opus-4-6",
apiKey: process.env.ANTHROPIC_API_KEY,
},
})
await box.agent.run({
prompt: `
Create a simple Express web server that:
- Listens on port 3000
- Has a / route that returns "Hello World"
- Has a /health route that returns {"status": "ok"}
- Start the server in the background
`,
})
const publicUrl = await box.getPublicURL(3000)
console.log(`Public URL available at: ${publicUrl.url}`)
// Test the endpoints
const response = await fetch(`${publicUrl.url}/health`)
console.log(await response.json()) // { status: "ok" }
import os
from upstash_box import Box, Agent
box = Box.create(
runtime="node",
agent={
"harness": Agent.CLAUDE_CODE,
"model": "anthropic/claude-opus-4-6",
"api_key": os.environ["ANTHROPIC_API_KEY"],
},
)
box.agent.run(
prompt="""
Create a simple Express web server that:
- Listens on port 3000
- Has a / route that returns "Hello World"
- Has a /health route that returns {"status": "ok"}
- Start the server in the background
""",
)
public_url = box.get_public_url(3000)
print(f"Public URL available at: {public_url.url}")
# Test the endpoints
import httpx
response = httpx.get(f"{public_url.url}/health")
print(response.json()) # {"status": "ok"}
Share a secure public URL
Create a public URL with authentication for sharing with team members.
import { Agent, Box } from "@upstash/box"
const box = await Box.create({ runtime: "python" })
// Set up a Flask app
await box.files.write({
path: "/work/app.py",
content: `
from flask import Flask
app = Flask(__name__)
@app.route('/')
def home():
return 'Internal Dashboard'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080)
`,
})
await box.exec.command("pip install flask && python /work/app.py &")
// Create authenticated public URL
const publicUrl = await box.getPublicURL(8080, { basicAuth: true })
console.log(`Public URL: ${publicUrl.url}`)
console.log(`Username: ${publicUrl.username}`)
console.log(`Password: ${publicUrl.password}`)
// Share these credentials with your team
import httpx
from upstash_box import Box
box = Box.create(runtime="python")
# Set up a Flask app
box.files.write(
path="/work/app.py",
content="""
from flask import Flask
app = Flask(__name__)
@app.route('/')
def home():
return 'Internal Dashboard'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080)
""",
)
box.exec.command("pip install flask && python /work/app.py &")
# Create authenticated public URL
public_url = box.get_public_url(8080, basic_auth=True)
print(f"Public URL: {public_url.url}")
print(f"Username: {public_url.username}")
print(f"Password: {public_url.password}")
# Share these credentials with your team
Multi-port application
Create multiple public URLs for different services in the same box.
import { Agent, Box } from "@upstash/box"
const box = await Box.create({ runtime: "node" })
// Start frontend on port 3000
await box.files.write({
path: "/work/frontend.js",
content: `
const express = require('express')
const app = express()
app.get('/', (req, res) => res.send('Frontend'))
app.listen(3000)
`,
})
// Start API on port 8080
await box.files.write({
path: "/work/api.js",
content: `
const express = require('express')
const app = express()
app.get('/api/status', (req, res) => res.json({ status: 'ok' }))
app.listen(8080)
`,
})
await box.exec.command("npm install express")
await box.exec.command("node /work/frontend.js & node /work/api.js &")
// Create a public URL for each service
const frontendPublicUrl = await box.getPublicURL(3000)
const apiPublicUrl = await box.getPublicURL(8080)
console.log(`Frontend: ${frontendPublicUrl.url}`)
console.log(`API: ${apiPublicUrl.url}`)
from upstash_box import Box
box = Box.create(runtime="node")
# Start frontend on port 3000
box.files.write(
path="/work/frontend.js",
content="""
const express = require('express')
const app = express()
app.get('/', (req, res) => res.send('Frontend'))
app.listen(3000)
""",
)
# Start API on port 8080
box.files.write(
path="/work/api.js",
content="""
const express = require('express')
const app = express()
app.get('/api/status', (req, res) => res.json({ status: 'ok' }))
app.listen(8080)
""",
)
box.exec.command("npm install express")
box.exec.command("node /work/frontend.js & node /work/api.js &")
# Create a public URL for each service
frontend_public_url = box.get_public_url(3000)
api_public_url = box.get_public_url(8080)
print(f"Frontend: {frontend_public_url.url}")
print(f"API: {api_public_url.url}")
Temporary testing public URL
Create a public URL, run tests against it, then clean up.
import { Agent, Box } from "@upstash/box"
const box = await Box.create({ runtime: "node" })
// Start test server
await box.exec.command("npx http-server /work -p 3000 &")
// Create a public URL for testing
const publicUrl = await box.getPublicURL(3000)
// Run your tests against the public URL
const response = await fetch(publicUrl.url)
console.log(response.status) // 200
// Clean up
await box.deletePublicURL(3000)
await box.delete()
import httpx
from upstash_box import Box
box = Box.create(runtime="node")
# Start test server
box.exec.command("npx http-server /work -p 3000 &")
# Create a public URL for testing
public_url = box.get_public_url(3000)
# Run your tests against the public URL
response = httpx.get(public_url.url)
print(response.status_code) # 200
# Clean up
box.delete_public_url(3000)
box.delete()
The SDK still supports getPreviewUrl, listPreviews, and deletePreview, but they are deprecated aliases for getPublicURL, listPublicURLs, and deletePublicURL.