Create Sandbox
curl --request POST \
--url https://api.declaw.ai/sandboxes \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"template": "<string>",
"timeout": 123,
"envs": {},
"metadata": {},
"network": {
"allow_out": [
"<string>"
],
"deny_out": [
"<string>"
],
"allow_public_traffic": true
},
"security": {},
"lifecycle": {
"on_timeout": "<string>",
"auto_resume": true
}
}
'import requests
url = "https://api.declaw.ai/sandboxes"
payload = {
"template": "<string>",
"timeout": 123,
"envs": {},
"metadata": {},
"network": {
"allow_out": ["<string>"],
"deny_out": ["<string>"],
"allow_public_traffic": True
},
"security": {},
"lifecycle": {
"on_timeout": "<string>",
"auto_resume": True
}
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
template: '<string>',
timeout: 123,
envs: {},
metadata: {},
network: {allow_out: ['<string>'], deny_out: ['<string>'], allow_public_traffic: true},
security: {},
lifecycle: {on_timeout: '<string>', auto_resume: true}
})
};
fetch('https://api.declaw.ai/sandboxes', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.declaw.ai/sandboxes",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'template' => '<string>',
'timeout' => 123,
'envs' => [
],
'metadata' => [
],
'network' => [
'allow_out' => [
'<string>'
],
'deny_out' => [
'<string>'
],
'allow_public_traffic' => true
],
'security' => [
],
'lifecycle' => [
'on_timeout' => '<string>',
'auto_resume' => true
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.declaw.ai/sandboxes"
payload := strings.NewReader("{\n \"template\": \"<string>\",\n \"timeout\": 123,\n \"envs\": {},\n \"metadata\": {},\n \"network\": {\n \"allow_out\": [\n \"<string>\"\n ],\n \"deny_out\": [\n \"<string>\"\n ],\n \"allow_public_traffic\": true\n },\n \"security\": {},\n \"lifecycle\": {\n \"on_timeout\": \"<string>\",\n \"auto_resume\": true\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.declaw.ai/sandboxes")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"template\": \"<string>\",\n \"timeout\": 123,\n \"envs\": {},\n \"metadata\": {},\n \"network\": {\n \"allow_out\": [\n \"<string>\"\n ],\n \"deny_out\": [\n \"<string>\"\n ],\n \"allow_public_traffic\": true\n },\n \"security\": {},\n \"lifecycle\": {\n \"on_timeout\": \"<string>\",\n \"auto_resume\": true\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.declaw.ai/sandboxes")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"template\": \"<string>\",\n \"timeout\": 123,\n \"envs\": {},\n \"metadata\": {},\n \"network\": {\n \"allow_out\": [\n \"<string>\"\n ],\n \"deny_out\": [\n \"<string>\"\n ],\n \"allow_public_traffic\": true\n },\n \"security\": {},\n \"lifecycle\": {\n \"on_timeout\": \"<string>\",\n \"auto_resume\": true\n }\n}"
response = http.request(request)
puts response.read_body{
"sandbox_id": "<string>",
"template_id": "<string>",
"state": "<string>",
"envd_access_token": "<string>",
"traffic_access_token": "<string>",
"guest_ip": "<string>",
"envd_port": 123,
"started_at": "<string>"
}Sandbox API
Create Sandbox
Create a new isolated sandbox sandbox.
POST
/
sandboxes
Create Sandbox
curl --request POST \
--url https://api.declaw.ai/sandboxes \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"template": "<string>",
"timeout": 123,
"envs": {},
"metadata": {},
"network": {
"allow_out": [
"<string>"
],
"deny_out": [
"<string>"
],
"allow_public_traffic": true
},
"security": {},
"lifecycle": {
"on_timeout": "<string>",
"auto_resume": true
}
}
'import requests
url = "https://api.declaw.ai/sandboxes"
payload = {
"template": "<string>",
"timeout": 123,
"envs": {},
"metadata": {},
"network": {
"allow_out": ["<string>"],
"deny_out": ["<string>"],
"allow_public_traffic": True
},
"security": {},
"lifecycle": {
"on_timeout": "<string>",
"auto_resume": True
}
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
template: '<string>',
timeout: 123,
envs: {},
metadata: {},
network: {allow_out: ['<string>'], deny_out: ['<string>'], allow_public_traffic: true},
security: {},
lifecycle: {on_timeout: '<string>', auto_resume: true}
})
};
fetch('https://api.declaw.ai/sandboxes', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.declaw.ai/sandboxes",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'template' => '<string>',
'timeout' => 123,
'envs' => [
],
'metadata' => [
],
'network' => [
'allow_out' => [
'<string>'
],
'deny_out' => [
'<string>'
],
'allow_public_traffic' => true
],
'security' => [
],
'lifecycle' => [
'on_timeout' => '<string>',
'auto_resume' => true
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.declaw.ai/sandboxes"
payload := strings.NewReader("{\n \"template\": \"<string>\",\n \"timeout\": 123,\n \"envs\": {},\n \"metadata\": {},\n \"network\": {\n \"allow_out\": [\n \"<string>\"\n ],\n \"deny_out\": [\n \"<string>\"\n ],\n \"allow_public_traffic\": true\n },\n \"security\": {},\n \"lifecycle\": {\n \"on_timeout\": \"<string>\",\n \"auto_resume\": true\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.declaw.ai/sandboxes")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"template\": \"<string>\",\n \"timeout\": 123,\n \"envs\": {},\n \"metadata\": {},\n \"network\": {\n \"allow_out\": [\n \"<string>\"\n ],\n \"deny_out\": [\n \"<string>\"\n ],\n \"allow_public_traffic\": true\n },\n \"security\": {},\n \"lifecycle\": {\n \"on_timeout\": \"<string>\",\n \"auto_resume\": true\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.declaw.ai/sandboxes")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"template\": \"<string>\",\n \"timeout\": 123,\n \"envs\": {},\n \"metadata\": {},\n \"network\": {\n \"allow_out\": [\n \"<string>\"\n ],\n \"deny_out\": [\n \"<string>\"\n ],\n \"allow_public_traffic\": true\n },\n \"security\": {},\n \"lifecycle\": {\n \"on_timeout\": \"<string>\",\n \"auto_resume\": true\n }\n}"
response = http.request(request)
puts response.read_body{
"sandbox_id": "<string>",
"template_id": "<string>",
"state": "<string>",
"envd_access_token": "<string>",
"traffic_access_token": "<string>",
"guest_ip": "<string>",
"envd_port": 123,
"started_at": "<string>"
}Provisions a new sandbox VM through the orchestrator. The API waits until the VM
reports a guest IP address before returning — typically 1–5 seconds. The returned
object contains tokens and connection details needed by the SDK.
Request Body
string
Template name to base the sandbox on. Becomes the sandbox
name and is
prefixed with tpl- for the template_id. Defaults to an empty string
(which uses the default base image).Example: "base"integer
Auto-kill timeout in seconds. When the timeout expires the sandbox state is
set to
killed and the VM is terminated. Pass 0 to disable auto-kill.Example: 300object
Environment variables to inject into the sandbox VM. Keys and values must
be strings.Example:
{ "OPENAI_API_KEY": "sk-..." }object
Arbitrary key-value metadata stored with the sandbox. Useful for tagging
sandboxes by project, run ID, or agent name.Example:
{ "project": "my-agent", "run_id": "run-001" }Resource allocation (vCPUs, memory, disk) is fixed at the template level —
the request-level
resources field is currently rejected with HTTP 403. Use
templates to size sandboxes instead.object
Outbound network access controls.
Show NetworkConfig fields
Show NetworkConfig fields
string[]
Domains or CIDR ranges allowed for outbound traffic. Wildcards supported.
Example:
["pypi.org", "*.github.com"]string[]
IPs or CIDR ranges explicitly denied, plus
ALL_TRAFFIC ("*" / "0.0.0.0/0")
to deny everything not allowlisted. allow_out takes precedence — a destination
matching both is allowed, so deny_out cannot carve an exception out of an
allow_out entry. Domain names in deny_out are ignored; express domain
restrictions by allowlisting with allow_out instead.
Example: ["10.0.0.0/8"]boolean
default:"true"
When
false, all outbound traffic is denied unless explicitly in allow_out.object
Full SecurityPolicy object (PII config, injection defense, transformation rules,
audit config). Passed as a JSON object and stored verbatim. See the
Security section for the complete schema.
object
Response
Returns a Sandbox object with staterunning.
string
Unique sandbox identifier. Format:
sbx-<8 chars>.string
Template ID used. Format:
tpl-<name>.string
Always
"running" on a freshly created sandbox.string
Bearer token for direct envd daemon access. Used internally by the SDK.
string
Bearer token for the security proxy. Used internally by the SDK.
string
Internal IP address of the sandbox VM.
integer
Port on which envd listens. Typically
49983.string
UTC timestamp of sandbox creation.
Example
curl -X POST https://api.declaw.ai/sandboxes \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"template": "base",
"timeout": 300,
"envs": { "MY_VAR": "hello" }
}'
from declaw import Sandbox
sbx = Sandbox.create(
api_key="YOUR_API_KEY",
domain="api.declaw.ai",
timeout=300,
envs={"MY_VAR": "hello"},
)
print(sbx.sandbox_id) # sbx-a1b2c3d4
import { Sandbox } from "@declaw/sdk";
const sbx = await Sandbox.create({
apiKey: "YOUR_API_KEY",
domain: "api.declaw.ai",
timeout: 300,
envs: { MY_VAR: "hello" },
});
console.log(sbx.sandboxId); // sbx-a1b2c3d4
Response
{
"sandbox_id": "sbx-a1b2c3d4",
"template_id": "tpl-base",
"name": "base",
"state": "live",
"timeout": 300,
"envs": { "MY_VAR": "hello" },
"envd_access_token": "envd-ab12cd34",
"sandbox_domain": "declaw.dev",
"traffic_access_token": "traffic-ef56gh78",
"guest_ip": "172.16.0.5",
"envd_port": 49983,
"started_at": "2024-01-15T10:30:00Z",
"end_at": "2024-01-15T10:35:00Z"
}
Error Responses
| Status | Cause |
|---|---|
400 | Invalid request body or malformed security JSON |
401 | Missing or invalid API key |
402 | Wallet (sandbox or guardrails) has insufficient balance |
403 | Per-sandbox tier limits exceeded (vCPU / memory / disk / session duration), or request-level resources field supplied |
429 | Concurrent sandbox limit reached for your tier, or sandbox create rate limit exceeded |
503 | Orchestrator is unavailable or the VM failed to start |