On-demand sandboxes
A sandbox is a fully isolated Tango Vision tenant: its own PostgreSQL database, a seeded building graph, and a dedicated tv-api stack — at its own subdomain. You develop against it instead of production.
Why
- Isolation. Your sandbox's data is physically separate from every other tenant.
- Realism. It's seeded with a parameterized building (mall or office) with spaces, elements, and telemetry — so your module renders against real-shaped data.
- Disposability. Reset it when you've made a mess; it expires automatically.
Create one — from the dashboard
The platform console has a Sandboxes page (under the admin nav). Paste your API key, then New sandbox:
| Field | Meaning |
|---|---|
| Name | Display name; the subdomain is derived from it |
| Building type | mall or office |
| Storeys | 1–50 |
| Area (m²) | Total gross area |
| TTL (days) | 1–30; auto-cleanup after |
The row starts as provisioning and flips to ready once the database is seeded — from under a minute for a small building to a few minutes at realistic parameters — with a URL like:
https://acme-cafm-dev-x7k2.sandbox.k8s.tangovision.devCreate one — from the CLI
The SDK wraps the whole lifecycle, so you never have to hand-roll curl. Sign in once (CLI sign-in) and every sandbox command authenticates itself from your OS keyring:
npx @tv/extension-sdk login
npx @tv/extension-sdk sandbox create \
--name="acme-cafm-dev" \
--type=mall \
--storeys=3 \
--area-sqm=20000 \
--seed-telemetry-days=14In CI, or anywhere non-interactive, use a portal-minted API key instead of logging in — an explicit credential always wins over the stored session:
export TV_API_TOKEN=$SANDBOX_API_KEY # tvk_... key from the portal
npx @tv/extension-sdk sandbox listThe CLI targets https://sandbox-api.k8s.tangovision.dev by default; --api=<url> (or TV_SANDBOX_API_URL) points it elsewhere.
| Subcommand | What it does |
|---|---|
create | Provision a sandbox. --dry-run generates the seed locally without calling the service. |
list | List the sandboxes you own |
connect <id> | Print connection info + export the env your module needs |
extend <id> --days=N | Extend the TTL |
reset <id> | Wipe and re-seed without deleting |
delete <id> | Delete immediately |
Shaping knobs beyond the basics: --spaces-min / --spaces-max (default 10/30), --equipment-density=sparse|realistic|dense, --occupancy-profile=24x7|office-hours|peak-evenings, --ttl-days=N (1–30, default 14), and --seed=<string> for a deterministic build. Add --format=json to any subcommand to script it.
Create one — from the API
curl -X POST https://sandbox-api.k8s.tangovision.dev/api/v1/sandboxes \
-H "Authorization: Bearer $SANDBOX_API_KEY" \
-H "content-type: application/json" \
-d '{
"name": "acme-cafm-dev",
"buildingType": "mall",
"storeys": 3,
"areaSqm": 20000,
"ttlDays": 14
}'Response — 202 Accepted. Provisioning runs in the background (a database, a seeded building graph, and a dedicated tv-api stack take a few minutes at realistic parameters), so the record comes back in provisioning status:
{
"sandboxId": "sbx_...",
"name": "acme-cafm-dev",
"slug": "acme-cafm-dev-x7k2",
"status": "provisioning",
"apiUrl": "https://acme-cafm-dev-x7k2.sandbox.k8s.tangovision.dev",
"expiresAt": "2026-06-13T...",
"extensionsRemaining": 2
}Poll the detail endpoint until status leaves provisioning:
curl -H "Authorization: Bearer $SANDBOX_API_KEY" \
https://sandbox-api.k8s.tangovision.dev/api/v1/sandboxes/sbx_...ready means the sandbox is usable (buildingId and the final apiUrl are filled in); failed carries a failureReason. The CLI (sandbox create) polls for you and exits when the sandbox is ready.
Lifecycle
| Action | Endpoint |
|---|---|
| List | GET /api/v1/sandboxes |
| Create | POST /api/v1/sandboxes |
| Extend TTL | POST /api/v1/sandboxes/:id/extend (body { "days": 7 }) |
| Reset (wipe + re-seed) | POST /api/v1/sandboxes/:id/reset |
| Delete | DELETE /api/v1/sandboxes/:id |
Quotas
To keep the shared cluster healthy:
- 3 concurrently-active sandboxes per external developer
- 2 TTL extensions per sandbox
- 30 day maximum TTL
These are enforced by the provisioner; you'll get a clear 429/400 when you hit them.
What's inside a fresh sandbox
- An organization + site + building seeded by
@tv/sandbox-seed - Storeys, spaces, elements, and points sized by your parameters
- Up to 30 days of backfilled telemetry (configurable via
seedTelemetryDays) - The standard tv-api schema, so every platform endpoint works
Point your module's PlatformContext at the sandbox's apiUrl and develop as if it were production — because, structurally, it is.