
# Publicar el borrador de marca

`POST /v1/branding:publish` · permiso `branding:write`

Toma una instantánea de todos los borradores (entorno, aplicaciones, organizaciones, textos) y la convierte en la versión activa de las páginas alojadas. Antes de publicar se comprueba el tema efectivo de cada ámbito: tokens obligatorios, rangos de valores y contraste WCAG de cada par de colores. Cualquier problema rechaza toda la publicación con `422 branding_validation_failed` y una lista `issues[]` que indica cada token que cambiar (en el contraste, con el `ratio` medido, el `threshold` y la `suggestion` válida más cercana). Se conservan las últimas 50 versiones. `Idempotency-Key` es opcional.

Si el borrador tiene CSS personalizado, también se renderiza en las pantallas alojadas antes de publicar nada (una comprobación de renderizado que puede tardar hasta 25 segundos; use un tiempo de espera del cliente de al menos 30 segundos). El CSS que rompe un elemento protegido o añade una infracción de accesibilidad que la página no tiene sin él rechaza la publicación con `422 branding_validation_failed` y una lista `render_violations[]`. Si el borrador cambia durante la comprobación, no se publica nada y recibe `409 conflict`; publique de nuevo.

## Solicitud

Esta operación no admite campos de ruta, consulta ni cuerpo. El entorno proviene de la credencial.

## Respuesta

`200 OK` con los metadatos de la nueva versión (la instantánea en sí no se devuelve).

```json
{
  "version": 4,
  "snapshot_sha256": "3f1c…",
  "source": "publish",
  "rolled_back_from": null,
  "actor_type": "api_key",
  "actor_id": "key_01jb…",
  "published_at": "2026-10-05T09:31:00Z"
}
```

```json
{
  "type": "https://docs.keenauth.com/problems/branding_validation_failed",
  "status": 422,
  "code": "branding_validation_failed",
  "issues": [
    {"scope_type": "environment", "code": "brand_contrast_insufficient", "field": "light.color.primary_contrast",
     "variant": "light", "pair": "primary_contrast_on_primary", "ratio": 2.1, "threshold": 4.5, "suggestion": "#ffffff"}
  ]
}
```

Un rechazo de la comprobación de renderizado enumera cada hallazgo: `screen` (por ejemplo `password`), `locale` (`en`, `ar` o `ja`), `width` (ancho de la ventana gráfica en píxeles CSS, 320 o 1280), `rule` (`protected_no_area`, `protected_not_visible`, `protected_transparent`, `protected_covered`, `protected_contrast` o un ID de regla de axe-core como `color-contrast`) y `target` (el nombre del elemento protegido o un selector CSS de axe-core). Los valores CSS nunca se devuelven. Se devuelven como máximo 100 hallazgos; `render_violations_truncated` es `true` cuando hay más.

```json
{
  "type": "https://docs.keenauth.com/errors/branding_validation_failed",
  "status": 422,
  "code": "branding_validation_failed",
  "render_violations": [
    {"screen": "recovery", "locale": "ar", "width": 320, "rule": "protected_covered", "target": "recovery_codes_hint"}
  ],
  "render_violations_truncated": false
}
```

## Errores

| HTTP | código | Cuándo |
|---|---|---|
| 403 | `plan_feature_unavailable` | El borrador tiene CSS personalizado o una plantilla de página que el plan no incluye (`feature` indica cuál). |
| 422 | `branding_validation_failed` | El borrador no se puede publicar; consulte `issues[]`. El CSS personalizado del borrador se vuelve a sanear al publicar; si no lo supera, las infracciones están en la extensión `violations[]` (consulte `PUT /v1/branding/css`). Si el CSS personalizado no supera la comprobación de renderizado, los hallazgos están en `render_violations[]` y `render_violations_truncated`. |
| 409 | `conflict` | El borrador cambió mientras se comprobaba su CSS personalizado; no se publicó nada. Publique de nuevo. |
| 401 | `unauthenticated` | La credencial falta, no es válida o se ha revocado. |
| 403 | `insufficient_permissions` | La credencial no tiene el permiso necesario. |
| 429 | `rate_limited` | Se superó el límite de frecuencia; vuelva a intentarlo tras el periodo `Retry-After`. |
| 503 | `service_unavailable` | Una dependencia no está disponible temporalmente (incluida la comprobación de renderizado de un borrador con CSS personalizado); vuelva a intentarlo tras el periodo `Retry-After`. |

## Ejemplo

```bash
curl -X POST https://api.eu.keenauth.com/v1/branding:publish \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Idempotency-Key: $(uuidgen)"
```
