
# 브랜딩 에셋 업로드

`POST /v1/branding/assets` · 권한 `branding:write`

호스팅 로그인 페이지에 사용할 이미지(로고, 파비콘 또는 배경 이미지)를 업로드합니다. 응답의 `id`는 테마 필드 `logo`, `favicon` 또는 `background_image`에 넣는 값입니다([브랜딩 업데이트](./update.md) 참고). 게시한 후 이미지가 로그인 페이지에 표시됩니다.

모든 이미지는 격리된 프로세스에서 디코딩된 뒤 최대 1024 × 1024 픽셀의 PNG로 다시 인코딩되며, 모든 메타데이터가 제거됩니다. 파비콘에는 32 px 및 180 px 버전이 추가로 생성됩니다. `id`는 처리된 PNG의 SHA-256 값입니다. 같은 필드에 같은 이미지를 다시 업로드하면 기존 에셋이 `200 OK`로 반환됩니다.

허용되는 형식은 PNG, JPEG, WebP이며, ICO는 파비콘에만 허용됩니다. SVG는 허용되지 않습니다. 글꼴 업로드는 사용할 수 없습니다.

환경당 최대 200개의 에셋과 총 50 MB까지 보관할 수 있습니다.

## 요청

본문은 `multipart/form-data`이며, 파일은 최대 1 MiB입니다.

| 파트 | 타입 | 필수 | 설명 |
|---|---|---|---|
| `kind` | string | 예 | `logo`, `favicon` 또는 `background_image`. |
| `file` | file | 예 | 이미지. 최대 1 MiB, 한 변당 최대 8192 픽셀. |

`Idempotency-Key`를 사용하는 경우, 재시도할 때 멀티파트 경계(boundary)를 포함해 정확히 같은 바이트를 보내야 합니다.

## 응답

새 에셋은 `201 Created`, 같은 필드에 같은 이미지가 이미 업로드되어 있으면 `200 OK`가 반환됩니다.

```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`는 에셋에 저장된 모든 PNG의 크기이며, 할당량에 포함됩니다.

## 오류

| HTTP | code | 발생 조건 |
|---|---|---|
| 400 | `malformed_request` | 멀티파트 본문을 읽을 수 없거나, `kind`와 `file` 외의 파트가 있습니다. |
| 401 | `unauthenticated` | 자격 증명이 없거나, 유효하지 않거나, 취소되었습니다. |
| 403 | `insufficient_permissions` | 자격 증명에 필요한 권한이 없습니다. |
| 403 | `quota_exceeded` | 환경에 이미 200개의 에셋 또는 50 MB가 있습니다. |
| 413 | `payload_too_large` | 파일이 1 MiB를 초과합니다. |
| 415 | `unsupported_media_type` | 본문이 `multipart/form-data`가 아니거나, 파일이 허용되지 않는 형식입니다(`errors[]`의 `unsupported_media_type`, `svg_not_allowed`, `ico_favicon_only`). |
| 422 | `validation_failed` | `kind` 또는 `file`이 없거나 잘못되었습니다(글꼴은 `/kind font_upload_disabled`), 또는 이미지를 사용할 수 없습니다: `invalid_image`, `image_too_large`, `image_dimensions_too_large`, `image_output_too_large`, `image_processing_limit`. |
| 422 | `idempotency_key_reuse` | 같은 `Idempotency-Key`가 다른 본문과 함께 사용되었습니다. |
| 429 | `rate_limited` | 요청 한도를 초과했습니다. `Retry-After` 기간이 지난 후 다시 시도하십시오. |
| 503 | `service_unavailable` | 에셋 저장소를 일시적으로 사용할 수 없습니다. `Retry-After` 기간이 지난 후 다시 시도하십시오. |

## 예제

```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
```

CLI 사용 시:

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