# Cambios en lote

> Crea, cambia y borra hasta 500 registros DNS de una zona como un único cambio versionado de todo o nada con POST records/batch o apply_records_batch.

Un **lote** aplica altas, cambios y bajas de registros de una zona como **un** solo cambio: una versión, unas
diferencias, una vuelta atrás. O se aplican todas las operaciones o ninguna. Úsalo para migrar una zona, para
sustituir un conjunto de registros (por ejemplo los de correo de un proveedor nuevo) o para cualquier cambio que, a
medias, dejaría la zona incoherente.

El panel también usa lotes: el borrado y el cambio de proxy masivos de **DNS › Registros**, las importaciones y el
asistente de correo.

## Petición

`POST /v1/orgs/{org}/zones/{zone}/records/batch`, con el rol `tech` o superior.

```json
{
  "delete": ["0b9c6c2e-1f7a-4a39-9d1e-2b8f3c5d7e01"],
  "update": [
    {"id": "5a1e2f3b-6c7d-4e8f-9a0b-1c2d3e4f5a6b", "content": "203.0.113.20"}
  ],
  "create": [
    {"type": "MX", "name": "@", "content": "mx1.example.net", "priority": 10},
    {"type": "MX", "name": "@", "content": "mx2.example.net", "priority": 20},
    {"type": "TXT", "name": "@", "content": "v=spf1 include:_spf.example.net -all"}
  ]
}
```

| Campo | Contenido |
|---|---|
| `create` | Registros con los mismos campos que un alta suelta: `type`, `name`, `content`, `ttl`, `priority`, `proxied`, `comment`, `tags` |
| `update` | `id` del registro y solo los campos que cambian (`"priority": null` la quita) |
| `delete` | Ids de los registros que se borran |

Reglas:

- De 1 a 500 operaciones en total. Si hay más: `422 invalid` con «at most 500 operations per batch».
- Cada registro solo se puede cambiar o borrar una vez en el mismo lote.
- Las operaciones se ejecutan así: primero las bajas, luego los cambios y por último las altas. Cada registro se
  valida al escribirse, y las [reglas de convivencia](https://developers.openwaf.dev/es/dns/record-types/#coexistence) se comprueban sobre el estado
  **final** de cada nombre que toca el lote. Así, un mismo lote puede, por ejemplo, sustituir un registro `A` por un
  `CNAME` en el mismo nombre.
- Igual que en un cambio suelto, cambiar el proxy de un registro `A`, `AAAA` o `CNAME` cambia también los demás de ese
  nombre que el lote no toca.
- Un error indica en su `field` la operación que falla, por ejemplo `create[2].content`.

## Simular y aplicar

**API**

```sh
# Simular: lo valida todo y devuelve las diferencias sin aplicar nada
curl -X POST "https://dash.openwaf.dev/v1/orgs/$ORG/zones/$ZONE/records/batch?dry_run=1" \
  -H "Authorization: Bearer $OPENWAF_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Change-Reason: Correo al proveedor nuevo" \
  --data @lote.json

# Aplicar sobre la versión que simulaste
curl -X POST "https://dash.openwaf.dev/v1/orgs/$ORG/zones/$ZONE/records/batch" \
  -H "Authorization: Bearer $OPENWAF_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Change-Reason: Correo al proveedor nuevo" \
  -H 'If-Match: "41"' \
  --data @lote.json
```
Las dos responden `200` con `from_version`, `to_version`, `diff`, `warnings` y `records`, los registros de la zona
tras el cambio. Si la zona ha cambiado desde la versión de `If-Match`, el lote se rechaza con `412 version_conflict`.
**MCP**

Pide el cambio a tu asistente; llama a `apply_records_batch` con `zone`, `create`, `update` y `delete`. La primera
llamada (`confirm: false`) solo simula y devuelve las diferencias y la `current_version`; cuando das el visto bueno, la
misma llamada con `confirm: true` y `expected_version` lo aplica. La herramienta se marca como destructiva cuando borra
registros.
**Panel**

Selecciona registros en **DNS › Registros** y usa **Borrar**, **Activar proxy** o **Quitar proxy**; el cuadro de
diálogo lista todos los registros afectados y lo aplica como una sola versión.


## Deshacer un lote

Un lote es una versión, así que volver a la versión anterior deshace todas sus operaciones de una vez. Consulta
[Versiones de la zona](https://developers.openwaf.dev/es/dns/zone-versions/#rollback).
