---
title: "Upload an organization logo"
method: POST
path: "/v1/organizations/{id}/logo"
tags: ["Organizations"]
---

# Upload an organization logo

`POST /v1/organizations/{id}/logo`

## Request

- Base URL: `https://api.squirrelscan.com`
- URL: `https://api.squirrelscan.com/v1/organizations/{id}/logo`
- Auth: HTTP bearer

Owner/admin only. Multipart upload with a `file` field. Accepts PNG/JPEG/WebP validated by magic bytes (SVG and non-images are rejected regardless of declared content type), max 1MB. Stores the image and persists its public URL on `organizations.avatarUrl`.

## Path parameters

- `id` string, required

## Response `200`

Logo stored; returns the served URL.

- object
  - `avatarUrl` string, uri, required

## Other responses

- `400`: Request body or query failed validation. `error.issues` lists up to 10 failed fields (`{ path, message }`); when more failed, `error.truncated: true` and `error.totalIssues` indicate the full count.
- `401`: Missing or invalid credentials (including the shared auth middleware: no/invalid bearer token). Typed envelope with code `UNAUTHORIZED`. Branch on the `401` status, not the message.
- `403`: Authenticated but not permitted (e.g. not a member of the requested organization). Typed envelope; code `FORBIDDEN`, or `NO_ORG` when no active organization is resolved on credit/org-scoped routes. Branch on the `403` status.
- `404`: Resource not found (or hidden from the caller).
- `413`: The request body exceeds the maximum allowed size.
- `415`: The bytes are not a PNG/JPEG/WebP image (e.g. SVG). Typed envelope with code `UNSUPPORTED_MEDIA_TYPE`.
- `429`: Too many requests. Retry after the window resets. (Rate limiting is planned — issue #69 — these headers document the intended contract.)

---

[API](https://skmtc.dev/squirrelscan/apis/squirrelscan-public-api.md) · [All operations](https://skmtc.dev/squirrelscan/apis/squirrelscan-public-api/llms.txt) · [OpenAPI document](https://skmtc.dev/squirrelscan/apis/squirrelscan-public-api/revisions/82c8183fe8bc?raw)
