# Crear por clave, iniciar, detener y destruir

Una unidad creada por tu código tiene una **clave**: su nombre, elegido por ti, que nunca cambia. Un hub que abre un mundo privado por jugador usa `plot-<jugador>`. Un ejecutor de trabajos usa `job-<id>`. La clave es también el nombre de red privado de la unidad: `<clave>.<slug-del-workload>`.

Estas rutas necesitan la política en [modo `code`](/es/guides/units-api/warm-buffer-and-allocate#pasar-la-política-a-modo-code).

## Crear una unidad por clave

`POST .../units` es **idempotente sobre la clave**, así que se puede llamar sin miedo cada vez que "un jugador abre su parcela".

**curl**

```bash
curl -sS -X POST "$UNITS" -H "$AUTH" -H "Content-Type: application/json" -d '{
  "key": "plot-ana",
  "labels": {"kind": "plot", "owner": "ana"},
  "user_data": {"world": "s3://my-bucket/plots/ana"},
  "start": true,
  "on_exit": "stop"
}'
# 201 {"created": true,  "unit": {...}}   a new unit
# 200 {"created": false, "unit": {...}}   the live unit with that key already existed
```

**TypeScript**

```ts
import { call, UNITS } from "./zaroz";

const { status, body } = await call("POST", UNITS, {
  key: "plot-ana",
  labels: { kind: "plot", owner: "ana" },
  user_data: { world: "s3://my-bucket/plots/ana" },
  start: true,
  on_exit: "stop",
});
console.log(status, body.created, body.unit.key, body.unit.state);
```

**Python**

```python
from zaroz import call, UNITS

status, body = call("POST", UNITS, {
    "key": "plot-ana",
    "labels": {"kind": "plot", "owner": "ana"},
    "user_data": {"world": "s3://my-bucket/plots/ana"},
    "start": True,
    "on_exit": "stop",
})
print(status, body["created"], body["unit"]["key"], body["unit"]["state"])
```


| Situación | Respuesta |
|---|---|
| Ninguna unidad viva tiene esta clave | `201 {created: true}` y la unidad arranca (salvo `"start": false`) |
| Una unidad viva tiene esta clave y está en marcha, con entrada igual u omitida | `200 {created: false}` con la unidad actual |
| Está **detenida** y `start` es true | Arranca. Si envías `labels` y `user_data`, reemplazan a los guardados. `200 {created: false}` |
| Está en marcha y envías `labels` o `user_data` distintos | `409 unit-input-differs`. La entrada de una unidad en marcha solo cambia con allocate o con [`PATCH` de etiquetas](/es/guides/units-api/labels-and-user-data) |

Campos: `key` (obligatorio), `labels`, `user_data`, `start` (por defecto `true`), `on_exit` (`restart`, `stop` o `destroy`; por defecto el `default_on_exit` de la política).

`"start": false` crea la unidad **detenida**: no ocupa ranura y no cuesta nada hasta que la inicies.

`on_exit` es lo que pasa cuando el proceso de la unidad termina: `restart` conserva el pod y reinicia el proceso en su sitio; `stop` y `destroy` terminan la unidad (y liberan la ranura). Usa `destroy` para una partida o un trabajo y `stop` para una parcela a la que volverás.

## Leer una unidad

**curl**

```bash
curl -sS "$UNITS/plot-ana" -H "$AUTH"
```

**TypeScript**

```ts
const { body: unit } = await call("GET", `${UNITS}/plot-ana`);
console.log(unit.state, unit.labels, unit.user_data, unit.allocation);
```

**Python**

```python
_, unit = call("GET", f"{UNITS}/plot-ana")
print(unit["state"], unit["labels"], unit["user_data"], unit["allocation"])
```


La respuesta incluye `state`, `desired_state`, `labels`, `user_data`, `origin` (`policy`, `code` o `warm`), `allocation` (nulo hasta que se asigna), `private_name`, `public_endpoints`, `billing_class` (`included` o `extra`), el pod actual y el número de reinicios.

## Detener, iniciar y destruir

**curl**

```bash
curl -sS -X POST "$UNITS/plot-ana/stop" -H "$AUTH"      # drain, then stop: costs nothing while stopped
curl -sS -X POST "$UNITS/plot-ana/start" -H "$AUTH" -H "Content-Type: application/json" -d '{}'
curl -sS -X DELETE "$UNITS/plot-ana" -H "$AUTH"         # drain, then destroy: final
```

**TypeScript**

```ts
await call("POST", `${UNITS}/plot-ana/stop`);
await call("POST", `${UNITS}/plot-ana/start`, {});          // {} starts it as it is
await call("DELETE", `${UNITS}/plot-ana`);                   // final; the key may be reused afterwards
```

**Python**

```python
call("POST", f"{UNITS}/plot-ana/stop")
call("POST", f"{UNITS}/plot-ana/start", {})   # {} starts it as it is
call("DELETE", f"{UNITS}/plot-ana")           # final; the key may be reused afterwards
```


- **stop** vacía la unidad (recibe un aviso de drenaje y deja de aceptar trabajo nuevo) y después la detiene. La clave, las etiquetas y el `user_data` se conservan, la ranura se libera y **no se factura nada mientras está detenida**. Detener una unidad detenida es un `200` sin efecto.
- **start** despierta una unidad detenida. Iniciar una unidad en marcha es un `200` sin efecto. El cuerpo puede llevar `labels` y `user_data`, que reemplazan enteros a los guardados. Envía `{}` para iniciarla tal cual.
- **destroy** vacía y después elimina la unidad. Es definitivo: después la clave responde `404` y puede reutilizarse. El éxito es `204`.

**curl**

```bash
curl -sS -X POST "$UNITS/plot-ana/start" -H "$AUTH" -H "Content-Type: application/json" \
  -d '{"labels": {"kind": "plot", "owner": "ana", "tier": "vip"}, "user_data": {"world": "s3://my-bucket/plots/ana-v2"}}'
```

**TypeScript**

```ts
await call("POST", `${UNITS}/plot-ana/start`, {
  labels: { kind: "plot", owner: "ana", tier: "vip" },
  user_data: { world: "s3://my-bucket/plots/ana-v2" },   // replaces the stored value whole
});
```

**Python**

```python
call("POST", f"{UNITS}/plot-ana/start", {
    "labels": {"kind": "plot", "owner": "ana", "tier": "vip"},
    "user_data": {"world": "s3://my-bucket/plots/ana-v2"},  # replaces the stored value whole
})
```


Toda llamada que arranca un pod (crear con `start`, `start`, un relleno, allocate con `if_none: create`) se comprueba contra tus límites y tu tope de gasto: mira [Errores](/es/guides/units-api/errors) para `container-unit-limit`, `org-unit-limit`, `start-rate` y `spend-cap`. Un rechazo nunca es un éxito parcial y un límite nunca toca las unidades en marcha.

## Las unidades detenidas se acumulan

Un Workload puede guardar 1.000 unidades detenidas (`stopped-unit-limit`). Las que llevan detenidas más que `destroy_stopped_after_days` de la política (90 por defecto) se destruyen y un evento `unit.destroyed` con motivo `expired` te lo avisa.
