---
title: Качване на изображение на продукт
description: Multipart качване на едно изображение към продукт. PNG/JPG/WebP, ≤5 MB, макс 20 изображения. Без Idempotency-Key (multipart не може safely да се hash-ва).
canonical: "https://www.tracepass.eu/bg/docs/upload-product-image"
locale: bg
source: "https://www.tracepass.eu/bg/docs/upload-product-image"
---

# Качване на изображение на продукт

> Multipart качване на едно изображение към продукт. PNG/JPG/WebP, ≤5 MB, макс 20 изображения. Без Idempotency-Key (multipart не може safely да се hash-ва).

```http
POST /api/v1/products/{id}/images
```

Качване на единичен файл с изображение (multipart/form-data, име на полето `file`) и добавянето му към масива `imageUrls` на продукта. Използвайте това, когато нямате готов CDN URL — изображението попада в R2 bucket-а ни и публичният URL се връща в отговора.

Само PNG / JPG / WebP, макс. 5 MB на файл, макс. 20 изображения на продукт. **Не поддържа Idempotency-Key** — multipart телата не се хешират безопасно. Клиентът трябва да проверява за съществуване + да пропуска при retry. Съответстващият `DELETE /api/v1/products/{id}/images/{index}` премахва едно изображение по zero-based индекс.

## Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `Authorization` | header | string | yes | `Bearer <token>` — или `tp_` API ключ (Developer → API Keys; най-просто, за server-to-server), или OAuth 2.0 access token (Developer → OAuth Apps; за приложения, авторизирани от потребител, scoped и отзоваеми). Страницата Authentication съдържа пълния OAuth поток и списъка със scopes. |
| `Content-Type` | header | string | yes | `multipart/form-data` с boundary, зададен от вашия HTTP клиент. |
| `id` | path | ObjectId | yes | ID на продукта. |
| `file` | body | binary (PNG / JPG / WebP, ≤ 5 MB) | yes | Байтове на изображението, изпратени като form поле `file`. |

## Examples

```bash
curl -sS -X POST \
  https://app.tracepass.eu/api/v1/products/6650a1b2c3d4e5f6a7b8c9d0/images \
  -H "Authorization: Bearer tp_REDACTED_xxxxxxxxxxxx" \
  -F "file=@./battery-hero.jpg"
```

```typescript
import { readFile } from "node:fs/promises";

const file = await readFile("./battery-hero.jpg");
const form = new FormData();
form.set("file", new Blob([file], { type: "image/jpeg" }), "battery-hero.jpg");

const res = await fetch(
  `https://app.tracepass.eu/api/v1/products/${id}/images`,
  {
    method: "POST",
    headers: { Authorization: `Bearer ${process.env.TRACEPASS_API_KEY}` },
    body: form,
  },
);
if (!res.ok) throw new Error(`Upload failed: ${res.status}`);
const { imageUrl, imageUrls } = await res.json();
```

```python
import os, requests

with open("battery-hero.jpg", "rb") as fh:
    res = requests.post(
        f"https://app.tracepass.eu/api/v1/products/{product_id}/images",
        headers={"Authorization": f"Bearer {os.environ['TRACEPASS_API_KEY']}"},
        files={"file": ("battery-hero.jpg", fh, "image/jpeg")},
    )
res.raise_for_status()
data = res.json()
print(data["imageUrl"])
```

## Responses

### 201 — Качено

```json
{
  "imageUrl": "https://r2.tracepass.eu/<companyId>/products/<id>/images/<imageId>.jpg",
  "imageUrls": [
    "https://existing-image-1.jpg",
    "https://r2.tracepass.eu/<companyId>/products/<id>/images/<imageId>.jpg"
  ]
}
```

### 400 — Няма файл

```json
{ "error": "No file provided. Send as multipart/form-data with field name 'file'." }
```

### 413 — Твърде голямо

```json
{ "error": "Image must be under 5MB" }
```

### 415 — Неподдържан тип

```json
{ "error": "Unsupported MIME type — accepts image/png, image/jpeg, image/webp" }
```

### 422 — Достигнат лимит

```json
{ "error": "Product already has 20 images (max). Delete one first." }
```

## Related

- [Актуализиране на продукт](https://www.tracepass.eu/bg/docs/update-product.md)
- [Създаване на продукт](https://www.tracepass.eu/bg/docs/create-product.md)
