---
title: "Create a TCP port forward"
method: POST
path: "/spaces/{spaceId}/cubes/{cubeId}/tcp-mappings"
tags: ["TCP mappings"]
---

# Create a TCP port forward

`POST /spaces/{spaceId}/cubes/{cubeId}/tcp-mappings`

## Request

- Base URL: `https://krova.cloud/api/v1`
- URL: `https://krova.cloud/api/v1/spaces/{spaceId}/cubes/{cubeId}/tcp-mappings`
- Auth: API key in header `X-API-KEY`

## Path parameters

- `spaceId` string, required
- `cubeId` string, required

## Headers

- `Idempotency-Key` string

## Request body

- object
  - `cubePort` integer, required
  - `label` string: Optional human label for the mapping.
  - `whitelistedIps` string[]: IPs/CIDRs allowed to reach the published port. Omit or send an empty array to leave the port open to the internet.
  - `whitelistIps` string[]: DEPRECATED alias for `whitelistedIps`, accepted for backwards compatibility. `whitelistedIps` wins if both are sent. Use `whitelistedIps` in new code.
  - `udpEnabled` boolean: Also forward UDP on this port. Defaults to true. Always false for the platform SSH mapping. The allowlist, if you send one, applies to both protocols.

## Response `201`

Mapping created

- object
  - `tcpMapping` TcpMapping, required
    - `id` string, required
    - `cubeId` string, required
    - `cubePort` integer, required
    - `host` string, nullable: Where to connect for this mapping: `host:hostPort`. The Cube's own stable hostname, which survives migration to another server, falling back to the server's public IP when the Cube has no DNS record yet. Identical to `host` from GET .../ssh, and the same value for every mapping on a Cube. Null only when the Cube has no server assigned, in which case there is nowhere to connect. Do NOT use `serverDomain` from the Cube object — that is the current physical host and changes when the Cube moves.
    - `hostPort` integer, required
    - `label` string, nullable, required
    - `status` string, required
    - `isSsh` boolean, required
    - `udpEnabled` boolean, required: Whether this mapping also forwards UDP on the same host port. True means TCP and UDP; false means TCP only. Always false for the platform SSH mapping.
    - `createdAt` string, date-time, required
    - `updatedAt` string, date-time, required
    - `whitelistedIps` object[], required
      - `id` string, required
      - `cidr` string, required

## Other responses

- `400`: Bad request
- `409`: Refused because the change conflicts with the Cube's current state, for example the port is already in use or the mapping is already being removed. One such conflict is temporary: in the last stretch of a move of the Cube to another server the change is refused with the error "This cube is being moved to another server. Try again in a minute." Nothing was changed then, and the same request is accepted once the move ends.
- `429`: Rate limit exceeded (10 mutations / 60s)

---

[API](https://skmtc.dev/krova/apis/krova-cloud-api.md) · [All operations](https://skmtc.dev/krova/apis/krova-cloud-api/llms.txt) · [OpenAPI document](https://skmtc.dev/krova/apis/krova-cloud-api/revisions/46bb68281ce1?raw)
