curl --request GET \
--url https://api.blaxel.ai/v0/sandboxes \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.blaxel.ai/v0/sandboxes"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.blaxel.ai/v0/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.blaxel.ai/v0/sandboxes",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.blaxel.ai/v0/sandboxes"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.blaxel.ai/v0/sandboxes")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.blaxel.ai/v0/sandboxes")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": [
{
"metadata": {
"name": "my-resource",
"createdAt": "<string>",
"updatedAt": "<string>",
"createdBy": "<string>",
"updatedBy": "<string>",
"displayName": "My Resource",
"externalId": "my-session-123",
"labels": {},
"plan": "<string>",
"url": "<string>",
"workspace": "<string>"
},
"spec": {
"enabled": true,
"lifecycle": {
"expirationPolicies": [
{
"action": "delete",
"type": "ttl-idle",
"value": "24h"
}
],
"terminatedRetention": "24h"
},
"network": {
"allowedDomains": "[\"api.stripe.com\", \"api.openai.com\", \"*.s3.amazonaws.com\"]",
"egress": {
"gateway": "egress-ip-gw-1",
"mode": "dedicated",
"policies": [
{
"destinations": "[\"api.stripe.com\"]",
"mode": "dedicated",
"name": "payment-apis"
}
]
},
"firewall": {
"rulesets": "[\"proxy\", \"dedicated-ip\"]"
},
"forbiddenDomains": "[\"*.malware.com\", \"evil.example.org\"]",
"proxy": {
"allowedDomains": "[\"api.stripe.com\", \"api.openai.com\", \"*.s3.amazonaws.com\"]",
"bypass": "[\"*.s3.amazonaws.com\"]",
"forbiddenDomains": "[\"*.malware.com\", \"evil.example.org\"]",
"routing": [
{
"body": "{\"api_key\": \"{{SECRET:stripe-key}}\"}",
"destinations": "[\"api.stripe.com\"]",
"headers": "{\"Authorization\": \"Bearer {{SECRET:stripe-key}}\"}",
"secrets": "{\"stripe-key\": \"sk-live-abc123...\"}"
}
]
},
"subnet": "default"
},
"region": "us-pdx-1",
"runtime": {
"envs": [
{
"name": "MY_ENV_VAR",
"secret": true,
"value": "my-value"
}
],
"expires": "2025-12-31T23:59:59Z",
"extraArgs": {},
"image": "blaxel/base-image:latest",
"memory": 4096,
"ports": [
{
"target": 8080,
"name": "http",
"protocol": "HTTP"
}
],
"terminationGracePeriodSeconds": 30,
"ttl": "24h"
},
"volumes": [
{
"mountPath": "/mnt/data",
"name": "my-volume",
"readOnly": false,
"sizeMb": 102400,
"type": "persistent"
}
],
"vpc": "default"
},
"archive": {
"createdAt": "<string>",
"generation": "mk3.0",
"key": "my-workspace/my-sandbox.tar",
"restore": {
"files": 123,
"restoredBytes": 123,
"state": "extracting",
"totalBytes": 123
},
"restoreStartedAt": "<string>",
"size": 123,
"startedAt": "<string>"
},
"errors": [
{
"code": "VM_NETWORK_FAILURE",
"fatal": true,
"instance": "<string>",
"message": "<string>",
"time": "<string>"
}
],
"events": [
{
"canaryRevision": "<string>",
"message": "Deployment successful",
"revision": "rev-abc123",
"status": "DEPLOYED",
"time": "2025-01-15T10:30:00Z",
"type": "deployment"
}
],
"expiresIn": 123,
"lastUsedAt": "<string>",
"nodeGeneration": "<string>",
"state": "RUNNING",
"status": "DELETING"
}
],
"meta": {
"hasMore": true,
"nextCursor": "<string>",
"total": 123,
"totalIsPartial": true
}
}{
"error": "Resource already exists",
"code": 409,
"message": "Invalid request body"
}{
"error": "Resource already exists",
"code": 409,
"message": "Invalid request body"
}{
"error": "Resource already exists",
"code": 409,
"message": "Invalid request body"
}List sandboxes
Returns sandboxes in the workspace. Each sandbox includes its configuration, status, and endpoint URL. Terminated sandboxes are hidden by default; pass showTerminated=true to include them. Starting with API version 2026-04-28 the response is wrapped in {data, meta} and supports cursor pagination via the cursor and limit query parameters; older versions keep returning a bare array of all sandboxes.
curl --request GET \
--url https://api.blaxel.ai/v0/sandboxes \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.blaxel.ai/v0/sandboxes"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.blaxel.ai/v0/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.blaxel.ai/v0/sandboxes",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.blaxel.ai/v0/sandboxes"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.blaxel.ai/v0/sandboxes")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.blaxel.ai/v0/sandboxes")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": [
{
"metadata": {
"name": "my-resource",
"createdAt": "<string>",
"updatedAt": "<string>",
"createdBy": "<string>",
"updatedBy": "<string>",
"displayName": "My Resource",
"externalId": "my-session-123",
"labels": {},
"plan": "<string>",
"url": "<string>",
"workspace": "<string>"
},
"spec": {
"enabled": true,
"lifecycle": {
"expirationPolicies": [
{
"action": "delete",
"type": "ttl-idle",
"value": "24h"
}
],
"terminatedRetention": "24h"
},
"network": {
"allowedDomains": "[\"api.stripe.com\", \"api.openai.com\", \"*.s3.amazonaws.com\"]",
"egress": {
"gateway": "egress-ip-gw-1",
"mode": "dedicated",
"policies": [
{
"destinations": "[\"api.stripe.com\"]",
"mode": "dedicated",
"name": "payment-apis"
}
]
},
"firewall": {
"rulesets": "[\"proxy\", \"dedicated-ip\"]"
},
"forbiddenDomains": "[\"*.malware.com\", \"evil.example.org\"]",
"proxy": {
"allowedDomains": "[\"api.stripe.com\", \"api.openai.com\", \"*.s3.amazonaws.com\"]",
"bypass": "[\"*.s3.amazonaws.com\"]",
"forbiddenDomains": "[\"*.malware.com\", \"evil.example.org\"]",
"routing": [
{
"body": "{\"api_key\": \"{{SECRET:stripe-key}}\"}",
"destinations": "[\"api.stripe.com\"]",
"headers": "{\"Authorization\": \"Bearer {{SECRET:stripe-key}}\"}",
"secrets": "{\"stripe-key\": \"sk-live-abc123...\"}"
}
]
},
"subnet": "default"
},
"region": "us-pdx-1",
"runtime": {
"envs": [
{
"name": "MY_ENV_VAR",
"secret": true,
"value": "my-value"
}
],
"expires": "2025-12-31T23:59:59Z",
"extraArgs": {},
"image": "blaxel/base-image:latest",
"memory": 4096,
"ports": [
{
"target": 8080,
"name": "http",
"protocol": "HTTP"
}
],
"terminationGracePeriodSeconds": 30,
"ttl": "24h"
},
"volumes": [
{
"mountPath": "/mnt/data",
"name": "my-volume",
"readOnly": false,
"sizeMb": 102400,
"type": "persistent"
}
],
"vpc": "default"
},
"archive": {
"createdAt": "<string>",
"generation": "mk3.0",
"key": "my-workspace/my-sandbox.tar",
"restore": {
"files": 123,
"restoredBytes": 123,
"state": "extracting",
"totalBytes": 123
},
"restoreStartedAt": "<string>",
"size": 123,
"startedAt": "<string>"
},
"errors": [
{
"code": "VM_NETWORK_FAILURE",
"fatal": true,
"instance": "<string>",
"message": "<string>",
"time": "<string>"
}
],
"events": [
{
"canaryRevision": "<string>",
"message": "Deployment successful",
"revision": "rev-abc123",
"status": "DEPLOYED",
"time": "2025-01-15T10:30:00Z",
"type": "deployment"
}
],
"expiresIn": 123,
"lastUsedAt": "<string>",
"nodeGeneration": "<string>",
"state": "RUNNING",
"status": "DELETING"
}
],
"meta": {
"hasMore": true,
"nextCursor": "<string>",
"total": 123,
"totalIsPartial": true
}
}{
"error": "Resource already exists",
"code": 409,
"message": "Invalid request body"
}{
"error": "Resource already exists",
"code": 409,
"message": "Invalid request body"
}{
"error": "Resource already exists",
"code": 409,
"message": "Invalid request body"
}Authorizations
OAuth2 authentication with JWT tokens
Query Parameters
If true, include terminated sandboxes in the response. Defaults to false.
Opaque cursor returned by a previous response's meta.nextCursor. Only valid for the same query (workspace + filters); the server rejects cursors bound to a different query or older than 24h. Omit on the first page.
Maximum number of items to return per page. Defaults to 50, clamped to 200.
1 <= x <= 200Sort spec, formatted as <key>:<direction>. Allowed values are createdAt:desc (default), createdAt:asc, name:asc, name:desc. The cursor fingerprint is bound to the sort, so a cursor opened with one value cannot be reused with another. Only honoured starting on Blaxel-Version 2026-04-28.
createdAt:desc, createdAt:asc, name:asc, name:desc Substring search across metadata.name, metadata.displayName and labels (keys + values). Trimmed and lowercased server-side; queries shorter than 2 characters fall back to the unfiltered listing. Bound into the cursor fingerprint so a cursor opened with one query cannot be reused with another. Only honoured starting on Blaxel-Version 2026-04-28.
200Start from a known pagination boundary. end is only supported for createdAt listings (asc or desc) and returns the tail page directly without walking every cursor from the first page.
end Comma-separated list of statuses to filter on (e.g. DEPLOYED,FAILED). When set it takes precedence over showTerminated. Unknown values are rejected with a 400. Bound into the cursor fingerprint.
Filter sandboxes by external ID. When set, only sandboxes matching this caller-owned identifier are returned.
Response
successful operation
Cursor-paginated list of sandboxes. Returned starting with API version 2026-04-28; older API versions return a bare array.
Page of sandboxes. Items use the lite shape (no inline event history) to keep the page payload small, matching the unpaginated response.
Show child attributes
Show child attributes
Pagination metadata returned alongside a page of listing results. Always present on listing endpoints starting with API version 2026-04-28.
Show child attributes
Show child attributes
Was this page helpful?