
# Subir un recurso de marca

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

Sube una imagen para la página de inicio de sesión alojada: un logotipo, un favicon o una imagen de fondo. El `id` de la respuesta es el valor que pones en los campos de tema `logo`, `favicon` o `background_image` (consulta [Actualizar la marca](./update.md)); la imagen aparece en la página de inicio de sesión después de publicar.

Cada imagen se decodifica en un proceso aislado y se vuelve a codificar como PNG, con un máximo de 1024 × 1024 píxeles y sin metadatos. Un favicon también recibe versiones de 32 px y 180 px. El `id` es el SHA-256 del PNG procesado, así que subir de nuevo la misma imagen para el mismo campo devuelve el recurso existente con `200 OK`.

Los formatos aceptados son PNG, JPEG y WebP, e ICO solo para favicons. SVG no se acepta. No está disponible la subida de fuentes.

Un entorno puede tener como máximo 200 recursos y 50 MB en total.

## Solicitud

El cuerpo es `multipart/form-data`, y el archivo tiene como máximo 1 MiB.

| Parte | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| `kind` | string | sí | `logo`, `favicon` o `background_image`. |
| `file` | file | sí | La imagen. Como máximo 1 MiB y 8192 píxeles por lado. |

Con un `Idempotency-Key`, un reintento debe enviar exactamente los mismos bytes, incluido el separador del multipart.

## Respuesta

`201 Created` para un recurso nuevo, `200 OK` cuando la misma imagen ya se había subido para el mismo campo.

```json
{
  "id": "3f0c…e91a",
  "kind": "favicon",
  "url": "https://acme.eu1.keenauth.app/assets/3f0c…e91a.png",
  "width": 256,
  "height": 256,
  "byte_size": 48213,
  "source_format": "ico",
  "favicon_32_url": "https://acme.eu1.keenauth.app/assets/9b1d…04c2.png",
  "favicon_180_url": "https://acme.eu1.keenauth.app/assets/c7e2…5a10.png",
  "created_at": "2026-10-19T20:30:00Z"
}
```

`byte_size` es el tamaño de todos los PNG almacenados del recurso y cuenta para la cuota.

## Errores

| HTTP | code | Cuándo |
|---|---|---|
| 400 | `malformed_request` | El cuerpo multipart no se puede leer o tiene partes distintas de un `kind` y un `file`. |
| 401 | `unauthenticated` | La credencial falta, no es válida o está revocada. |
| 403 | `insufficient_permissions` | La credencial no tiene el permiso requerido. |
| 403 | `quota_exceeded` | El entorno ya tiene 200 recursos o 50 MB. |
| 413 | `payload_too_large` | El archivo supera 1 MiB. |
| 415 | `unsupported_media_type` | El cuerpo no es `multipart/form-data`, o el archivo no es un formato aceptado (`unsupported_media_type`, `svg_not_allowed`, `ico_favicon_only` en `errors[]`). |
| 422 | `validation_failed` | `kind` o `file` falta o no es válido (`/kind font_upload_disabled` para fuentes), o la imagen no se puede usar: `invalid_image`, `image_too_large`, `image_dimensions_too_large`, `image_output_too_large`, `image_processing_limit`. |
| 422 | `idempotency_key_reuse` | La misma `Idempotency-Key` se usó con un cuerpo distinto. |
| 429 | `rate_limited` | Se superó el límite de tasa; reintenta después del periodo de `Retry-After`. |
| 503 | `service_unavailable` | El almacenamiento de recursos no está disponible temporalmente; reintenta después del periodo de `Retry-After`. |

## Ejemplo

```bash
curl -X POST https://api.eu.keenauth.com/v1/branding/assets \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -F kind=logo \
  -F file=@logo.png
```

Con la CLI:

```bash
keenauth branding assets upload --kind logo --file logo.png
```
