# Marca blanca

> Pon tu nombre, color y logotipo en el panel, sírvelo en tu propio dominio y usa tus propios servidores de nombres.

La marca blanca permite a una agencia mostrar el panel y sus correos con su propia marca, servir el panel en su propio dominio (un CNAME a `custom.openwaf.dev`) y publicar sus zonas con sus propios servidores de nombres. Estas rutas aún no tienen métodos en los SDK; los ejemplos usan curl.

| Operación | Ruta |
|---|---|
| [Ver la marca](https://developers.openwaf.dev/es/api/white-label/#get-brand) | `GET /v1/orgs/{org}/brand` |
| [Configurar la marca](https://developers.openwaf.dev/es/api/white-label/#put-brand) | `PUT /v1/orgs/{org}/brand` |
| [Ver el logotipo](https://developers.openwaf.dev/es/api/white-label/#get-brand-logo) | `GET /v1/orgs/{org}/brand/logo` |
| [Subir el logotipo](https://developers.openwaf.dev/es/api/white-label/#put-brand-logo) | `PUT /v1/orgs/{org}/brand/logo` |
| [Borrar el logotipo](https://developers.openwaf.dev/es/api/white-label/#delete-brand-logo) | `DELETE /v1/orgs/{org}/brand/logo` |
| [Ver el dominio del panel](https://developers.openwaf.dev/es/api/white-label/#get-white-label-domain) | `GET /v1/orgs/{org}/whitelabel/domain` |
| [Configurar el dominio del panel](https://developers.openwaf.dev/es/api/white-label/#put-white-label-domain) | `PUT /v1/orgs/{org}/whitelabel/domain` |
| [Borrar el dominio del panel](https://developers.openwaf.dev/es/api/white-label/#delete-white-label-domain) | `DELETE /v1/orgs/{org}/whitelabel/domain` |
| [Verificar el dominio del panel](https://developers.openwaf.dev/es/api/white-label/#verify-white-label-domain) | `POST /v1/orgs/{org}/whitelabel/domain/verify` |
| [Ver los servidores de nombres propios](https://developers.openwaf.dev/es/api/white-label/#get-white-label-nameservers) | `GET /v1/orgs/{org}/whitelabel/nameservers` |
| [Configurar servidores de nombres propios](https://developers.openwaf.dev/es/api/white-label/#put-white-label-nameservers) | `PUT /v1/orgs/{org}/whitelabel/nameservers` |
| [Borrar los servidores de nombres propios](https://developers.openwaf.dev/es/api/white-label/#delete-white-label-nameservers) | `DELETE /v1/orgs/{org}/whitelabel/nameservers` |
| [Verificar los servidores de nombres propios](https://developers.openwaf.dev/es/api/white-label/#verify-white-label-nameservers) | `POST /v1/orgs/{org}/whitelabel/nameservers/verify` |

## Ver la marca

```http
GET /v1/orgs/{org}/brand
```

Devuelve la marca de la organización (nombre, color de acento, logotipo y correo de soporte). Sin marca propia, la respuesta es la marca de OpenWAF (`org_id` nulo).

**Rol necesario:** `readonly` o superior.

#### Parámetros

| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
| `org` | ruta | string (uuid) | Sí | Id de la organización. Cada ruta comprueba que es la del token (si no, `404`). |

#### Respuesta

- `200`: Devuelve [Brand](https://developers.openwaf.dev/es/api/schemas/#brand).

| Campo | Tipo | Descripción |
|---|---|---|
| `org_id` | string (uuid) o null | Organización de la marca; null = la marca de OpenWAF. |
| `name` | string | Nombre. |
| `logo_url` | string o null | URL del logotipo en el panel, versionada por su contenido; null sin logotipo. |
| `accent` | string | Color de acento `#rrggbb`. |
| `support_email` | string |  |
| `oauth` | boolean | Si el panel de este dominio ofrece la entrada con Google y GitHub (solo el dominio de OpenWAF). |

#### Errores

| Estado | Descripción |
|---|---|
| `503` | No disponible ahora (`unavailable`); reinténtalo más tarde. |

#### Ejemplo

Aún sin método en los SDK: usa la petición HTTP.

```sh
curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/brand" \
  -H "Authorization: Bearer $OPENWAF_TOKEN"
```

```json
{
  "org_id": "1e7c9a3b-5d2f-4b8a-9c6e-0f2a4b6c8d1e",
  "name": "example.com",
  "logo_url": "/v1/brand/logo?v=3f9a1c2b7d4e",
  "accent": "#0f766e",
  "support_email": "support@acme.example",
  "oauth": false
}
```

## Configurar la marca

```http
PUT /v1/orgs/{org}/brand
```

Configura el nombre, el color de acento y el correo de soporte que muestran el panel y sus correos para la organización.

**Rol necesario:** `admin` o superior. De toda la organización.

#### Parámetros

| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
| `org` | ruta | string (uuid) | Sí | Id de la organización. Cada ruta comprueba que es la del token (si no, `404`). |

#### Cuerpo de la petición

Tipo de contenido `application/json`. Esquema: [BrandInput](https://developers.openwaf.dev/es/api/schemas/#brand-input).

| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| `name` | string | Sí | Nombre que muestran el panel y los correos; sin saltos de línea ni `<` `>`. Como mucho 100 caracteres. |
| `accent` | string | Sí | Color de acento `#rrggbb` (se pasa a minúsculas). Patrón `^#[0-9a-f]{6}$`. |
| `support_email` | string (email) | No | Correo de soporte que muestran el panel y los correos. |

#### Respuesta

- `200`: Devuelve [Brand](https://developers.openwaf.dev/es/api/schemas/#brand).

| Campo | Tipo | Descripción |
|---|---|---|
| `org_id` | string (uuid) o null | Organización de la marca; null = la marca de OpenWAF. |
| `name` | string | Nombre. |
| `logo_url` | string o null | URL del logotipo en el panel, versionada por su contenido; null sin logotipo. |
| `accent` | string | Color de acento `#rrggbb`. |
| `support_email` | string |  |
| `oauth` | boolean | Si el panel de este dominio ofrece la entrada con Google y GitHub (solo el dominio de OpenWAF). |

#### Errores

| Estado | Descripción |
|---|---|
| `400` | Petición mal formada (`bad_request`). |
| `403` | El rol o los límites del token no lo permiten (`forbidden`). |
| `422` | Error de validación (`invalid`). |
| `503` | No disponible ahora (`unavailable`); reinténtalo más tarde. |

#### Ejemplo

Aún sin método en los SDK: usa la petición HTTP.

```sh
curl -X PUT "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/brand" \
  -H "Authorization: Bearer $OPENWAF_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{
    "name": "Acme Digital",
    "accent": "#0f766e",
    "support_email": "support@acme.example"
  }'
```

```json
{
  "org_id": "1e7c9a3b-5d2f-4b8a-9c6e-0f2a4b6c8d1e",
  "name": "example.com",
  "logo_url": "/v1/brand/logo?v=3f9a1c2b7d4e",
  "accent": "#0f766e",
  "support_email": "support@acme.example",
  "oauth": false
}
```

## Ver el logotipo

```http
GET /v1/orgs/{org}/brand/logo
```

Devuelve el logotipo de la marca como `image/svg+xml` o `image/png`.

**Rol necesario:** `readonly` o superior.

#### Parámetros

| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
| `org` | ruta | string (uuid) | Sí | Id de la organización. Cada ruta comprueba que es la del token (si no, `404`). |

#### Respuesta

- `200`: El logotipo. Cuerpo de tipo `image/png`.

#### Errores

| Estado | Descripción |
|---|---|
| `404` | No existe o el token no lo ve (`not_found`). |
| `503` | No disponible ahora (`unavailable`); reinténtalo más tarde. |

#### Ejemplo

Aún sin método en los SDK: usa la petición HTTP.

```sh
curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/brand/logo" \
  -H "Authorization: Bearer $OPENWAF_TOKEN"
```

## Subir el logotipo

```http
PUT /v1/orgs/{org}/brand/logo
```

Sube el logotipo como cuerpo de la petición, `image/svg+xml` o `image/png`, de hasta 256 KB (PNG de hasta 4096×4096 píxeles). Antes hay que configurar la marca con [Configurar la marca](https://developers.openwaf.dev/es/api/white-label/#put-brand).

**Rol necesario:** `admin` o superior. De toda la organización.

#### Parámetros

| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
| `org` | ruta | string (uuid) | Sí | Id de la organización. Cada ruta comprueba que es la del token (si no, `404`). |

#### Cuerpo de la petición

Tipo de contenido `image/png`.

Como mucho 262144 caracteres.

#### Respuesta

- `200`: Devuelve [Brand](https://developers.openwaf.dev/es/api/schemas/#brand).

| Campo | Tipo | Descripción |
|---|---|---|
| `org_id` | string (uuid) o null | Organización de la marca; null = la marca de OpenWAF. |
| `name` | string | Nombre. |
| `logo_url` | string o null | URL del logotipo en el panel, versionada por su contenido; null sin logotipo. |
| `accent` | string | Color de acento `#rrggbb`. |
| `support_email` | string |  |
| `oauth` | boolean | Si el panel de este dominio ofrece la entrada con Google y GitHub (solo el dominio de OpenWAF). |

#### Errores

| Estado | Descripción |
|---|---|
| `403` | El rol o los límites del token no lo permiten (`forbidden`). |
| `422` | `invalid`: no es un SVG o PNG válido, pasa de 256 KB o de 4096×4096 píxeles, o la marca aún no tiene nombre y color. |
| `503` | No disponible ahora (`unavailable`); reinténtalo más tarde. |

#### Ejemplo

Aún sin método en los SDK: usa la petición HTTP.

```sh
curl -X PUT "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/brand/logo" \
  -H "Authorization: Bearer $OPENWAF_TOKEN" \
  -H "Content-Type: image/png" \
  --data-binary @logo.png
```

```json
{
  "org_id": "1e7c9a3b-5d2f-4b8a-9c6e-0f2a4b6c8d1e",
  "name": "example.com",
  "logo_url": "/v1/brand/logo?v=3f9a1c2b7d4e",
  "accent": "#0f766e",
  "support_email": "support@acme.example",
  "oauth": false
}
```

## Borrar el logotipo

```http
DELETE /v1/orgs/{org}/brand/logo
```

Quita el logotipo de la marca.

**Rol necesario:** `admin` o superior. De toda la organización.

#### Parámetros

| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
| `org` | ruta | string (uuid) | Sí | Id de la organización. Cada ruta comprueba que es la del token (si no, `404`). |

#### Respuesta

- `200`: Devuelve [Brand](https://developers.openwaf.dev/es/api/schemas/#brand).

| Campo | Tipo | Descripción |
|---|---|---|
| `org_id` | string (uuid) o null | Organización de la marca; null = la marca de OpenWAF. |
| `name` | string | Nombre. |
| `logo_url` | string o null | URL del logotipo en el panel, versionada por su contenido; null sin logotipo. |
| `accent` | string | Color de acento `#rrggbb`. |
| `support_email` | string |  |
| `oauth` | boolean | Si el panel de este dominio ofrece la entrada con Google y GitHub (solo el dominio de OpenWAF). |

#### Errores

| Estado | Descripción |
|---|---|
| `403` | El rol o los límites del token no lo permiten (`forbidden`). |
| `503` | No disponible ahora (`unavailable`); reinténtalo más tarde. |

#### Ejemplo

Aún sin método en los SDK: usa la petición HTTP.

```sh
curl -X DELETE "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/brand/logo" \
  -H "Authorization: Bearer $OPENWAF_TOKEN"
```

```json
{
  "org_id": "1e7c9a3b-5d2f-4b8a-9c6e-0f2a4b6c8d1e",
  "name": "example.com",
  "logo_url": "/v1/brand/logo?v=3f9a1c2b7d4e",
  "accent": "#0f766e",
  "support_email": "support@acme.example",
  "oauth": false
}
```

## Ver el dominio del panel

```http
GET /v1/orgs/{org}/whitelabel/domain
```

Devuelve el dominio propio del panel de la organización y su estado.

**Rol necesario:** `readonly` o superior. De toda la organización.

#### Parámetros

| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
| `org` | ruta | string (uuid) | Sí | Id de la organización. Cada ruta comprueba que es la del token (si no, `404`). |

#### Respuesta

- `200`: Devuelve [WhiteLabelDomain](https://developers.openwaf.dev/es/api/schemas/#white-label-domain).

| Campo | Tipo | Descripción |
|---|---|---|
| `host` | string | Dominio propio del panel, p. ej. `panel.example.com`. |
| `status` | string | Uno de `pending`, `active`, `error`. |
| `detail` | string | Motivo del estado `error` (vacío si no hay). |
| `cname_target` | string | Destino del CNAME que hay que crear (sin proxy). |
| `checked_at` | string (date-time) | Última comprobación. |
| `activated_at` | string (date-time) | Cuándo pasó a activa. |

#### Errores

| Estado | Descripción |
|---|---|
| `403` | El rol o los límites del token no lo permiten (`forbidden`). |
| `404` | `not_found`: la organización no tiene dominio propio. |
| `503` | No disponible ahora (`unavailable`); reinténtalo más tarde. |

#### Ejemplo

Aún sin método en los SDK: usa la petición HTTP.

```sh
curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/whitelabel/domain" \
  -H "Authorization: Bearer $OPENWAF_TOKEN"
```

```json
{
  "host": "www.example.com",
  "status": "pending",
  "detail": "",
  "cname_target": "custom.openwaf.dev",
  "checked_at": "2026-10-27T09:30:00Z",
  "activated_at": "2026-10-27T09:30:00Z"
}
```

## Configurar el dominio del panel

```http
PUT /v1/orgs/{org}/whitelabel/domain
```

Configura el dominio en el que se sirve el panel con la marca de la organización. Empieza `pending`. Crea un registro CNAME de ese nombre a `cname_target` (`custom.openwaf.dev`, solo DNS, sin proxy) y luego llama a [Verificar el dominio del panel](https://developers.openwaf.dev/es/api/white-label/#verify-white-label-domain). Cambiar el dominio deja de servir el anterior.

**Rol necesario:** `admin` o superior. De toda la organización.

#### Parámetros

| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
| `org` | ruta | string (uuid) | Sí | Id de la organización. Cada ruta comprueba que es la del token (si no, `404`). |

#### Cuerpo de la petición

Tipo de contenido `application/json`.

| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| `host` | string | Sí | Dominio propio del panel, p. ej. `panel.example.com`. |

#### Respuesta

- `200`: Devuelve [WhiteLabelDomain](https://developers.openwaf.dev/es/api/schemas/#white-label-domain).

| Campo | Tipo | Descripción |
|---|---|---|
| `host` | string | Dominio propio del panel, p. ej. `panel.example.com`. |
| `status` | string | Uno de `pending`, `active`, `error`. |
| `detail` | string | Motivo del estado `error` (vacío si no hay). |
| `cname_target` | string | Destino del CNAME que hay que crear (sin proxy). |
| `checked_at` | string (date-time) | Última comprobación. |
| `activated_at` | string (date-time) | Cuándo pasó a activa. |

#### Errores

| Estado | Descripción |
|---|---|
| `400` | Petición mal formada (`bad_request`). |
| `403` | El rol o los límites del token no lo permiten (`forbidden`). |
| `409` | `host_taken`: el nombre es de otra organización. |
| `422` | Error de validación (`invalid`). |
| `503` | No disponible ahora (`unavailable`); reinténtalo más tarde. |

#### Ejemplo

Aún sin método en los SDK: usa la petición HTTP.

```sh
curl -X PUT "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/whitelabel/domain" \
  -H "Authorization: Bearer $OPENWAF_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{
    "host": "panel.acme.example"
  }'
```

```json
{
  "host": "www.example.com",
  "status": "pending",
  "detail": "",
  "cname_target": "custom.openwaf.dev",
  "checked_at": "2026-10-27T09:30:00Z",
  "activated_at": "2026-10-27T09:30:00Z"
}
```

## Borrar el dominio del panel

```http
DELETE /v1/orgs/{org}/whitelabel/domain
```

Quita el dominio propio del panel de la organización; el panel deja de servirse en él.

**Rol necesario:** `admin` o superior. De toda la organización.

#### Parámetros

| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
| `org` | ruta | string (uuid) | Sí | Id de la organización. Cada ruta comprueba que es la del token (si no, `404`). |

#### Respuesta

- `204`: Borrado. Sin cuerpo.

#### Errores

| Estado | Descripción |
|---|---|
| `403` | El rol o los límites del token no lo permiten (`forbidden`). |
| `404` | No existe o el token no lo ve (`not_found`). |
| `503` | No disponible ahora (`unavailable`); reinténtalo más tarde. |

#### Ejemplo

Aún sin método en los SDK: usa la petición HTTP.

```sh
curl -X DELETE "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/whitelabel/domain" \
  -H "Authorization: Bearer $OPENWAF_TOKEN"
```

## Verificar el dominio del panel

```http
POST /v1/orgs/{org}/whitelabel/domain/verify
```

Comprueba el registro CNAME del dominio del panel. Si apunta a `cname_target`, el dominio pasa a `active` y el panel se sirve en él con certificado; si no, el estado es `error` y `detail` dice qué corregir.

**Rol necesario:** `admin` o superior. De toda la organización.

#### Parámetros

| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
| `org` | ruta | string (uuid) | Sí | Id de la organización. Cada ruta comprueba que es la del token (si no, `404`). |

#### Respuesta

- `200`: Devuelve [WhiteLabelDomain](https://developers.openwaf.dev/es/api/schemas/#white-label-domain).

| Campo | Tipo | Descripción |
|---|---|---|
| `host` | string | Dominio propio del panel, p. ej. `panel.example.com`. |
| `status` | string | Uno de `pending`, `active`, `error`. |
| `detail` | string | Motivo del estado `error` (vacío si no hay). |
| `cname_target` | string | Destino del CNAME que hay que crear (sin proxy). |
| `checked_at` | string (date-time) | Última comprobación. |
| `activated_at` | string (date-time) | Cuándo pasó a activa. |

#### Errores

| Estado | Descripción |
|---|---|
| `403` | El rol o los límites del token no lo permiten (`forbidden`). |
| `404` | No existe o el token no lo ve (`not_found`). |
| `409` | `host_taken`: el nombre es de otra organización. |
| `503` | No disponible ahora (`unavailable`); reinténtalo más tarde. |

#### Ejemplo

Aún sin método en los SDK: usa la petición HTTP.

```sh
curl -X POST "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/whitelabel/domain/verify" \
  -H "Authorization: Bearer $OPENWAF_TOKEN"
```

```json
{
  "host": "www.example.com",
  "status": "pending",
  "detail": "",
  "cname_target": "custom.openwaf.dev",
  "checked_at": "2026-10-27T09:30:00Z",
  "activated_at": "2026-10-27T09:30:00Z"
}
```

## Ver los servidores de nombres propios

```http
GET /v1/orgs/{org}/whitelabel/nameservers
```

Devuelve los servidores de nombres propios de la organización, su estado, las direcciones a las que deben resolver y los TXT que prueban su propiedad.

**Rol necesario:** `readonly` o superior. De toda la organización.

#### Parámetros

| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
| `org` | ruta | string (uuid) | Sí | Id de la organización. Cada ruta comprueba que es la del token (si no, `404`). |

#### Respuesta

- `200`: Devuelve [WhiteLabelNameservers](https://developers.openwaf.dev/es/api/schemas/#white-label-nameservers).

| Campo | Tipo | Descripción |
|---|---|---|
| `ns` | array de string | Los dos servidores de nombres propios. |
| `status` | string | Uno de `pending`, `active`, `error`. |
| `detail` | string | Motivo del estado `error` (vacío si no hay). |
| `required_ips` | object | Direcciones a las que deben resolver exactamente los dos nombres (A y AAAA). |
| `required_ips.v4` | array de string |  |
| `required_ips.v6` | array de string |  |
| `ownership_txt` | array de object | Registros TXT que demuestran que la organización controla el dominio de sus servidores de nombres; la verificación los exige antes de activarlos. |
| `ownership_txt[].name` | string | Nombre. |
| `ownership_txt[].value` | string |  |
| `checked_at` | string (date-time) | Última comprobación. |
| `activated_at` | string (date-time) | Cuándo pasó a activa. |

#### Errores

| Estado | Descripción |
|---|---|
| `403` | El rol o los límites del token no lo permiten (`forbidden`). |
| `404` | `not_found`: la organización no tiene servidores de nombres propios. |
| `503` | No disponible ahora (`unavailable`); reinténtalo más tarde. |

#### Ejemplo

Aún sin método en los SDK: usa la petición HTTP.

```sh
curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/whitelabel/nameservers" \
  -H "Authorization: Bearer $OPENWAF_TOKEN"
```

```json
{
  "ns": [
    "ns1.example-dns.net",
    "ns2.example-dns.net"
  ],
  "status": "pending",
  "detail": "",
  "required_ips": {
    "v4": [
      "example"
    ],
    "v6": [
      "example"
    ]
  },
  "ownership_txt": [
    {
      "name": "example.com",
      "value": "4f1c2e9a7b3d"
    }
  ],
  "checked_at": "2026-10-27T09:30:00Z",
  "activated_at": "2026-10-27T09:30:00Z"
}
```

## Configurar servidores de nombres propios

```http
PUT /v1/orgs/{org}/whitelabel/nameservers
```

Configura dos servidores de nombres propios (por ejemplo `ns1.example.com` y `ns2.example.com`) para publicar las zonas delegadas de la organización en lugar de la pareja asignada. Empiezan `pending`. Antes de verificarlos:

1. Crea los registros TXT de `ownership_txt`.
2. Haz que los dos nombres resuelvan exactamente a las direcciones de `required_ips` (A y AAAA; añade registros glue en el registrador si los nombres están dentro de tu propio dominio).

Sustituir servidores activos hace que las zonas vuelvan a publicar la pareja asignada hasta que se verifiquen los nuevos.

**Rol necesario:** `admin` o superior. De toda la organización.

#### Parámetros

| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
| `org` | ruta | string (uuid) | Sí | Id de la organización. Cada ruta comprueba que es la del token (si no, `404`). |

#### Cuerpo de la petición

Tipo de contenido `application/json`.

| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| `ns` | array de string | Sí | Dos nombres distintos, p. ej. `ns1.example.com` y `ns2.example.com`. Exactamente 2 elementos. |

#### Respuesta

- `200`: Devuelve [WhiteLabelNameservers](https://developers.openwaf.dev/es/api/schemas/#white-label-nameservers).

| Campo | Tipo | Descripción |
|---|---|---|
| `ns` | array de string | Los dos servidores de nombres propios. |
| `status` | string | Uno de `pending`, `active`, `error`. |
| `detail` | string | Motivo del estado `error` (vacío si no hay). |
| `required_ips` | object | Direcciones a las que deben resolver exactamente los dos nombres (A y AAAA). |
| `required_ips.v4` | array de string |  |
| `required_ips.v6` | array de string |  |
| `ownership_txt` | array de object | Registros TXT que demuestran que la organización controla el dominio de sus servidores de nombres; la verificación los exige antes de activarlos. |
| `ownership_txt[].name` | string | Nombre. |
| `ownership_txt[].value` | string |  |
| `checked_at` | string (date-time) | Última comprobación. |
| `activated_at` | string (date-time) | Cuándo pasó a activa. |

#### Errores

| Estado | Descripción |
|---|---|
| `400` | Petición mal formada (`bad_request`). |
| `403` | El rol o los límites del token no lo permiten (`forbidden`). |
| `409` | `host_taken`: un nombre lo usa otra organización. |
| `422` | Error de validación (`invalid`). |
| `503` | No disponible ahora (`unavailable`); reinténtalo más tarde. |

#### Ejemplo

Aún sin método en los SDK: usa la petición HTTP.

```sh
curl -X PUT "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/whitelabel/nameservers" \
  -H "Authorization: Bearer $OPENWAF_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{
    "ns": [
      "ns1.acme.example",
      "ns2.acme.example"
    ]
  }'
```

```json
{
  "ns": [
    "ns1.example-dns.net",
    "ns2.example-dns.net"
  ],
  "status": "pending",
  "detail": "",
  "required_ips": {
    "v4": [
      "example"
    ],
    "v6": [
      "example"
    ]
  },
  "ownership_txt": [
    {
      "name": "example.com",
      "value": "4f1c2e9a7b3d"
    }
  ],
  "checked_at": "2026-10-27T09:30:00Z",
  "activated_at": "2026-10-27T09:30:00Z"
}
```

## Borrar los servidores de nombres propios

```http
DELETE /v1/orgs/{org}/whitelabel/nameservers
```

Quita los servidores de nombres propios de la organización; sus zonas delegadas vuelven a publicar la pareja asignada.

**Rol necesario:** `admin` o superior. De toda la organización.

#### Parámetros

| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
| `org` | ruta | string (uuid) | Sí | Id de la organización. Cada ruta comprueba que es la del token (si no, `404`). |

#### Respuesta

- `204`: Borrados. Sin cuerpo.

#### Errores

| Estado | Descripción |
|---|---|
| `403` | El rol o los límites del token no lo permiten (`forbidden`). |
| `404` | No existe o el token no lo ve (`not_found`). |
| `503` | No disponible ahora (`unavailable`); reinténtalo más tarde. |

#### Ejemplo

Aún sin método en los SDK: usa la petición HTTP.

```sh
curl -X DELETE "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/whitelabel/nameservers" \
  -H "Authorization: Bearer $OPENWAF_TOKEN"
```

## Verificar los servidores de nombres propios

```http
POST /v1/orgs/{org}/whitelabel/nameservers/verify
```

Comprueba los TXT de propiedad y que los dos nombres resuelven exactamente a `required_ips`. Si es así, los servidores pasan a `active` y todas las zonas delegadas de la organización los publican; si no, el estado es `error` y `detail` dice qué corregir.

**Rol necesario:** `admin` o superior. De toda la organización.

#### Parámetros

| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
| `org` | ruta | string (uuid) | Sí | Id de la organización. Cada ruta comprueba que es la del token (si no, `404`). |

#### Respuesta

- `200`: Devuelve [WhiteLabelNameservers](https://developers.openwaf.dev/es/api/schemas/#white-label-nameservers).

| Campo | Tipo | Descripción |
|---|---|---|
| `ns` | array de string | Los dos servidores de nombres propios. |
| `status` | string | Uno de `pending`, `active`, `error`. |
| `detail` | string | Motivo del estado `error` (vacío si no hay). |
| `required_ips` | object | Direcciones a las que deben resolver exactamente los dos nombres (A y AAAA). |
| `required_ips.v4` | array de string |  |
| `required_ips.v6` | array de string |  |
| `ownership_txt` | array de object | Registros TXT que demuestran que la organización controla el dominio de sus servidores de nombres; la verificación los exige antes de activarlos. |
| `ownership_txt[].name` | string | Nombre. |
| `ownership_txt[].value` | string |  |
| `checked_at` | string (date-time) | Última comprobación. |
| `activated_at` | string (date-time) | Cuándo pasó a activa. |

#### Errores

| Estado | Descripción |
|---|---|
| `403` | El rol o los límites del token no lo permiten (`forbidden`). |
| `404` | No existe o el token no lo ve (`not_found`). |
| `409` | `host_taken`: un nombre lo usa otra organización. |
| `503` | No disponible ahora (`unavailable`); reinténtalo más tarde. |

#### Ejemplo

Aún sin método en los SDK: usa la petición HTTP.

```sh
curl -X POST "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/whitelabel/nameservers/verify" \
  -H "Authorization: Bearer $OPENWAF_TOKEN"
```

```json
{
  "ns": [
    "ns1.example-dns.net",
    "ns2.example-dns.net"
  ],
  "status": "pending",
  "detail": "",
  "required_ips": {
    "v4": [
      "example"
    ],
    "v6": [
      "example"
    ]
  },
  "ownership_txt": [
    {
      "name": "example.com",
      "value": "4f1c2e9a7b3d"
    }
  ],
  "checked_at": "2026-10-27T09:30:00Z",
  "activated_at": "2026-10-27T09:30:00Z"
}
```
