> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gmicloud.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Sandbox API Overview

> How the GMI Sandbox control plane and data plane fit together, and which token each one expects.

GMI Sandbox provides isolated execution environments created from templates. The REST API is split
into two planes with **different hosts and different credentials** — knowing which plane an endpoint
belongs to is the key to using the API correctly.

## Control plane vs. data plane

|                | Control plane                                                                | Data plane                                                   |
| -------------- | ---------------------------------------------------------------------------- | ------------------------------------------------------------ |
| What it does   | Lifecycle: create, list, connect, extend, delete sandboxes; manage templates | Work inside one sandbox: run commands, upload/download files |
| Base URL       | `https://console.gmicloud.ai/api/v2`                                         | `https://{sandbox_key}.{domain}` (per sandbox)               |
| Auth header    | `Authorization: Bearer <API key>`                                            | `X-Access-Token: <sandbox_access_token>`                     |
| Endpoints      | `/sandboxes`, `/templates`, `/products`                                      | `/executions`, `/files`                                      |
| Response shape | `{request_id, data}` envelope                                                | Raw payload (no envelope)                                    |

The two credentials are **not interchangeable**: the control plane rejects `X-Access-Token`, and the
data plane rejects `Authorization: Bearer`. A data-plane token is bound to its sandbox — using
sandbox A's token against sandbox B's host fails.

## Where the data-plane values come from

Every successful create (`POST /sandboxes`) or connect (`POST /sandboxes/{id}/connect`) response
returns three fields:

* `sandbox_key` — the per-sandbox host label;
* `domain` — the host suffix. Combine them as `https://{sandbox_key}.{domain}`; never assemble or
  derive the domain yourself;
* `sandbox_access_token` — the data-plane credential, valid for the sandbox's entire lifetime.

After extending a sandbox's lifetime (via connect or the timeout endpoint), call connect again and
overwrite all three cached values — the token may have been re-signed.

## Typical flow

1. `POST /sandboxes` with a `template_id` (send an `Idempotency-Key` header to make retries safe);
2. wait for the sandbox to reach `running` (`GET /sandboxes/{id}`);
3. run commands and transfer files against the sandbox's own host using `X-Access-Token`;
4. extend the lifetime with `POST /sandboxes/{id}/timeout` as needed;
5. `DELETE /sandboxes/{id}` when done — sandboxes also expire automatically at `end_at`.

Prefer a higher-level interface? The [Python SDK](/api-reference/sandbox-sdk/usage) wraps both
planes behind one client.
