# tunnels (/docs/reference/api/tunnels)

> Interactive access to an instance or a node through its gateway and daemon: exec, SSH, TCP or the serial console of an instance, or the console of a node. The server's tunnels module hosts this group when the deployment configures `tunnels` with an exec ticket issuer. See [Tunnels](/docs/guides/access/tunnels).



Interactive access to an instance or a node through its gateway and daemon: exec, SSH, TCP or the serial console of an instance, or the console of a node. The server's tunnels module hosts this group when the deployment configures `tunnels` with an exec ticket issuer. See [Tunnels](/docs/guides/access/tunnels).

All 1 methods are served by this release.

| Method          | Kind     | Authorization                                                                             | Phase | Status     |
| --------------- | -------- | ----------------------------------------------------------------------------------------- | ----- | ---------- |
| [`open`](#open) | mutation | `compute:instances:exec` @ `compute-instance` or `compute:nodes:console` @ `compute-node` | v0.3  | registered |

## open [#open]

`POST /api/compute/tunnels/open`

Issues a single-use exec ticket, valid for 60 seconds, for a tunnel to an instance or a node; returns the ticket, the tunnel id, the node and the `path` (`tunnels/<ticket>`, relative to the API base path) the caller then opens.

* Give exactly one of `instanceId` or `nodeId`. An instance takes `exec`, `ssh`, `tcp` (with a `port` from 1 to 65535) or `console` (its serial console: the daemon opens the domain's console from its runtime, never a host shell), decided with `compute:instances:exec` on `compute-instance/{instanceId}`. A node takes `console` only, decided with `compute:nodes:console` on `compute-node/{nodeId}`. Any other combination is `INVALID_INPUT`.

* Instance tunnels need a daemon that advertises `tunnel.instance-dial`: an older one would reach the host rather than the instance, so the call is `UNSUPPORTED` with `details.reason: 'daemon-capability'`; upgrade the daemon.

* A sandbox's instance, or a warm one waiting for a sandbox, takes no tunnels: `INVALID_STATE` with `details.reason: 'sandbox-managed'`; `sandboxes.exec` is its only way in.

* `NOT_FOUND` when the instance is not the tenant's or is still a draft, or the node is outside the tenant's view. `UNSUPPORTED` for a provider instance, which has no node agent to tunnel through.

* `INVALID_STATE` when the instance is not `running` or its node is not connected to a gateway.

* `RATE_LIMITED` (with `retryAfterMs`) beyond the per-identity limit of each API replica, 10 tunnels per minute by default.

* Emits `tunnel.issued`.

* **Kind:** mutation

* **Authorization:** `compute:instances:exec` @ `compute-instance` or `compute:nodes:console` @ `compute-node`

* **Module:** `tunnels`

* **Phase:** v0.3 (registered)

**Input**

| Field        | Type                                   | Required | Constraints                                                |
| ------------ | -------------------------------------- | -------- | ---------------------------------------------------------- |
| `tenantId`   | string                                 | yes      | at most 128 characters; matches `^[A-Za-z0-9._:-]{1,128}$` |
| `instanceId` | string                                 |          | at most 57 characters; matches `^inst_[0-9a-z]{26,52}$`    |
| `nodeId`     | string                                 |          | at most 57 characters; matches `^node_[0-9a-z]{26,52}$`    |
| `op`         | one of `exec`, `console`, `ssh`, `tcp` | yes      |                                                            |
| `port`       | integer                                |          | 1-65535                                                    |
