Upload a branding asset
POST /v1/branding/assets · permission branding:write
Uploads an image for the hosted login page: a logo, a favicon or a background image. The response id is the value you put in the theme fields logo, favicon or background_image (see Update branding); the image appears on the login page after you publish.
Every image is decoded in an isolated process and re-encoded as PNG, at most 1024 × 1024 pixels, with all metadata removed. A favicon also gets 32 px and 180 px versions. The id is the SHA-256 of the processed PNG, so uploading the same image again for the same field returns the existing asset with 200 OK.
Accepted formats are PNG, JPEG and WebP, and ICO for favicons only. SVG is not accepted. Font upload is not available.
An environment can hold at most 200 assets and 50 MB in total.
Request
The body is multipart/form-data, at most 1 MiB for the file.
| Part | Type | Required | Description |
|---|---|---|---|
kind |
string | yes | logo, favicon or background_image. |
file |
file | yes | The image. At most 1 MiB and 8192 pixels on a side. |
With an Idempotency-Key, a retry must send exactly the same bytes, including the multipart boundary.
Response
201 Created for a new asset, 200 OK when the same image was already uploaded for the same field.
{
"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 is the size of all stored PNGs of the asset and counts toward the quota.
Errors
| HTTP | code | When |
|---|---|---|
| 400 | malformed_request |
The multipart body cannot be read, or has parts other than one kind and one file. |
| 401 | unauthenticated |
The credential is missing, invalid or revoked. |
| 403 | insufficient_permissions |
The credential lacks the required permission. |
| 403 | quota_exceeded |
The environment already has 200 assets or 50 MB. |
| 413 | payload_too_large |
The file is larger than 1 MiB. |
| 415 | unsupported_media_type |
The body is not multipart/form-data, or the file is not an accepted format (unsupported_media_type, svg_not_allowed, ico_favicon_only in errors[]). |
| 422 | validation_failed |
kind or file is missing or invalid (/kind font_upload_disabled for fonts), or the image cannot be used: invalid_image, image_too_large, image_dimensions_too_large, image_output_too_large, image_processing_limit. |
| 422 | idempotency_key_reuse |
The same Idempotency-Key was used with a different body. |
| 429 | rate_limited |
The rate limit was exceeded; retry after the Retry-After period. |
| 503 | service_unavailable |
Asset storage is temporarily unavailable; retry after the Retry-After period. |
Example
curl -X POST https://api.eu.keenauth.com/v1/branding/assets \
-H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
-F kind=logo \
-F file=@logo.png
With the CLI:
keenauth branding assets upload --kind logo --file logo.png