# Ürün Medyası

https://dev.wisecp.com/tr/urun-medyasi

Ürünün galerisini, sipariş görselini ve teslimat dosyasını yöneten on bir uç.

## Genel Bakış

Bir ürünün üç ayrı görsel varlığı vardır ve bunlar karıştırılmamalıdır. **Galeri** birden çok görsel taşır ve sıralanabilir; **sipariş görseli** tektir ve sipariş ekranında görünür; **teslimat dosyası** görsel değil, yazılım ürününün müşteriye verdiği dosyadır.

Yükleme uçlarının hiçbiri çok parçalı form beklemez. Dosyayı base64 veri adresi olarak gönderirsiniz ya da indirilebilir bir bağlantı verirsiniz; sunucu adresi kendisi çeker.

## Referans

### Galeriyi Listeleme

get/api/v1/admin/products/{id}/images

`Products/GetProductImages` admin sıralı

Ürünün galeri görsellerini sıralarına göre döndürür.

Dönen alanlar data[] — 7

idintGörsel kimliği.

typestringGörselin rolü: `photo`, `header-background`, `cover` ya da `mockup`.

sizestringOkunabilir dosya boyutu.

namestringSaklanan dosya adı.

urlstringGenel erişim adresi.

titlestringGörsel başlığı.

sort_orderintGalerideki sırası.

Hatalar 2

not_found404Ürün bulunamadı.

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl 'https://panel.ornek.com/api/v1/admin/products/15/images' \
  -H "Authorization: Bearer $API_KEY"
```

```javascript
const res  = await fetch('https://panel.ornek.com/api/v1/admin/products/15/images', {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/products/15/images');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
$response = Api::Products()->GetProductImages(['id' => 15]);
```

Yanıt 200

```json
{
  "data": [
    {
      "id": 90,
      "type": "photo",
      "size": "120 KB",
      "name": "ab12.jpg",
      "url": "https://example.com/uploads/ab12.jpg",
      "title": "Screenshot",
      "sort_order": 1
    }
  ]
}
```

### Galeriye Görsel Yükleme

post/api/v1/admin/products/{id}/images

`Products/UploadProductImage` admin 201

Galeriye görsel ekler. Dosyayı base64 olarak ya da bir adres vererek gönderirsiniz.

Gövde 3

imagestringzorunluGörsel. base64 veri adresi ya da indirilebilir bir bağlantı.

titlestringGörsel başlığı.

typestringGörselin rolü: `photo`, `header-background`, `cover` ya da `mockup`. Varsayılan `photo`.

Dönen alanlar data — 5

idintYeni eklenen görselin kimliği.

typestringGörselin saklandığı rol.

titlestringGörsel başlığı.

sort_orderintGalerideki sırası.

urlstringGenel erişim adresi.

Hatalar 5

not_found404Ürün bulunamadı.

file_required422Dosya alanı boş.

file_invalid422Dosya çözümlenemedi ya da tipi kabul edilmedi.

file_failed422Dosya saklanamadı.

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl -X POST 'https://panel.ornek.com/api/v1/admin/products/15/images' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"image":"data:image/png;base64,iVBORw0KGgo...","title":"Screenshot"}'
```

```javascript
const res = await fetch('https://panel.ornek.com/api/v1/admin/products/15/images', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    image: 'data:image/png;base64,iVBORw0KGgo...',
    title: 'Screenshot',
    type: 'photo',
  }),
});

const body = await res.json();
```

```php
$data = base64_encode(file_get_contents('screenshot.png'));

$ch = curl_init('https://panel.ornek.com/api/v1/admin/products/15/images');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'image' => 'data:image/png;base64,' . $data,
        'title' => 'Screenshot',
    ]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
// Yuklenen gorsel galerinin SONUNA eklenir; sirayi ayri bir cagri belirler.
$image = Api::Products()->UploadProductImage([
    'id'    => 15,
    'image' => 'data:image/png;base64,' . base64_encode($bytes),
    'title' => 'Screenshot',
]);
```

### Görseli Güncelleme

patch/api/v1/admin/products/{id}/images/{image_id}

`Products/UpdateProductImage` admin tip dosyayı taşır

Görselin başlığını ya da rolünü değiştirir. Rol değişince dosya klasörler arasında taşınır.

Gövde 2

titlestringYeni başlık. Gönderirseniz boş olamaz.

typestringYeni rol: `photo`, `header-background`, `cover` ya da `mockup`.

Dönen alanlar data — 2

updatedboolGüncelleme başarılı mı.

idintGörsel kimliği.

Hatalar 4

not_found404Ürün ya da görsel bulunamadı.

title_required422Başlık gönderildi ama boştu.

invalid_type422Rol izinli değerlerden değil.

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl -X PATCH 'https://panel.ornek.com/api/v1/admin/products/15/images/91' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"title":"Dashboard","type":"cover"}'
```

```javascript
const res = await fetch('https://panel.ornek.com/api/v1/admin/products/15/images/91', {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ title: 'Dashboard', type: 'cover' }),
});

const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/products/15/images/91');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'PATCH',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'title' => 'Dashboard',
        'type'  => 'cover',
    ]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
// Rol degistirmek dosyayi tasir: eski adres artik calismaz.
$response = Api::Products()->UpdateProductImage([
    'id'       => 15,
    'image_id' => 91,
    'type'     => 'cover',
]);
```

### Görseli Silme

delete/api/v1/admin/products/{id}/images/{image_id}

`Products/DeleteProductImage` admin

Galeriden tek bir görseli siler.

Dönen alanlar data — 2

deletedboolSilme başarılı mı.

idintSilinen görselin kimliği.

Hatalar 2

not_found404Ürün ya da görsel bulunamadı.

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl -X DELETE 'https://panel.ornek.com/api/v1/admin/products/15/images/91' \
  -H "Authorization: Bearer $API_KEY"
```

```javascript
const res = await fetch('https://panel.ornek.com/api/v1/admin/products/15/images/91', {
  method: 'DELETE',
  headers: { Authorization: `Bearer ${apiKey}` },
});

const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/products/15/images/91');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'DELETE',
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
$response = Api::Products()->DeleteProductImage([
    'id'       => 15,
    'image_id' => 91,
]);
```

### Galeriyi Temizleme

delete/api/v1/admin/products/{id}/images

`Products/ClearProductImages` admin geri alınamaz

Ürünün tüm galeri görsellerini siler.

Dönen alanlar data — 1

clearedintSilinen görsel sayısı.

Hatalar 2

not_found404Ürün bulunamadı.

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl -X DELETE 'https://panel.ornek.com/api/v1/admin/products/15/images' \
  -H "Authorization: Bearer $API_KEY"
```

```javascript
const res = await fetch('https://panel.ornek.com/api/v1/admin/products/15/images', {
  method: 'DELETE',
  headers: { Authorization: `Bearer ${apiKey}` },
});

const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/products/15/images');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'DELETE',
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
// Adres tek gorsel silmekle AYNI, fark yalnizca gorsel kimliginin olmamasi.
$response = Api::Products()->ClearProductImages(['id' => 15]);
```

### Galeriyi Sıralama

put/api/v1/admin/products/{id}/images/order

`Products/ReorderProductImages` admin tam liste

Galeri sırasını verdiğiniz kimlik listesine göre belirler.

Gövde 1

image_idsint[]zorunluGörsel kimlikleri, istediğiniz sırada.

Dönen alanlar data[] — 7

idintGörsel kimliği.

typestringGörselin rolü: `photo`, `header-background`, `cover` ya da `mockup`.

sizestringOkunabilir dosya boyutu.

namestringSaklanan dosya adı.

urlstringGenel erişim adresi.

titlestringGörsel başlığı.

sort_orderintGalerideki sırası.

Hatalar 3

not_found404Ürün bulunamadı.

ids_required422`image_ids` boş.

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl -X PUT 'https://panel.ornek.com/api/v1/admin/products/15/images/order' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"image_ids":[92,90,91]}'
```

```javascript
const res = await fetch('https://panel.ornek.com/api/v1/admin/products/15/images/order', {
  method: 'PUT',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ image_ids: [92, 90, 91] }),
});

const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/products/15/images/order');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'PUT',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['image_ids' => [92, 90, 91]]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
// Bir gorseli one almak icin bile TUM listeyi gonderin.
$ids = array_column(Api::Products()->GetProductImages(['id' => 15])['data'], 'id');
array_unshift($ids, array_pop($ids));

$response = Api::Products()->ReorderProductImages([
    'id'        => 15,
    'image_ids' => $ids,
]);
```

### Teslimat Dosyasını Okuma

get/api/v1/admin/products/{id}/delivery-file

`Products/GetProductDeliveryFile` admin yazılım ürünleri

Yazılım ürününün müşteriye teslim edilen dosyasını döndürür.

Dönen alanlar data — 2

namestringSaklanan dosya adı.

sizestringOkunabilir dosya boyutu.

Hatalar 2

not_found404Ürün bulunamadı.

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl 'https://panel.ornek.com/api/v1/admin/products/15/delivery-file' \
  -H "Authorization: Bearer $API_KEY"
```

```javascript
const res  = await fetch('https://panel.ornek.com/api/v1/admin/products/15/delivery-file', {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();

// Dosya yuklenmemisse data null gelir.
if (body.data === null) return;
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/products/15/delivery-file');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
$response = Api::Products()->GetProductDeliveryFile(['id' => 15]);

$file = $response['data'] ?? null;
```

### Teslimat Dosyası Yükleme

put/api/v1/admin/products/{id}/delivery-file

`Products/UploadProductDeliveryFile` admin uzantı kısıtı var

Teslimat dosyasını yükler. Önceki dosya kaldırılır; ürün tek bir dosya taşır.

Gövde 1

filestringzorunluDosya. base64 veri adresi ya da indirilebilir bir bağlantı. Çalıştırılabilir sayfa uzantıları kabul edilmez.

Dönen alanlar data — 2

namestringSaklanan dosya adı.

sizestringOkunabilir dosya boyutu.

Hatalar 5

not_found404Ürün bulunamadı.

file_required422Dosya alanı boş.

file_invalid422Dosya çözümlenemedi ya da tipi kabul edilmedi.

file_failed422Dosya saklanamadı.

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl -X PUT 'https://panel.ornek.com/api/v1/admin/products/15/delivery-file' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"file":"https://cdn.example.com/setup-v2.zip"}'
```

```javascript
const res = await fetch('https://panel.ornek.com/api/v1/admin/products/15/delivery-file', {
  method: 'PUT',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ file: 'https://cdn.example.com/setup-v2.zip' }),
});

const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/products/15/delivery-file');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'PUT',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'file' => 'https://cdn.example.com/setup-v2.zip',
    ]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
// Yeni surum yuklemek eskisini kaldirir — once yedeklemek isteyebilirsiniz.
$response = Api::Products()->UploadProductDeliveryFile([
    'id'   => 15,
    'file' => 'https://cdn.example.com/setup-v2.zip',
]);
```

### Teslimat Dosyasını Silme

delete/api/v1/admin/products/{id}/delivery-file

`Products/DeleteProductDeliveryFile` admin

Teslimat dosyasını kaldırır.

Dönen alanlar data — 2

deletedboolSilme başarılı mı.

idintÜrün kimliği.

Hatalar 2

not_found404Ürün bulunamadı.

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl -X DELETE 'https://panel.ornek.com/api/v1/admin/products/15/delivery-file' \
  -H "Authorization: Bearer $API_KEY"
```

```javascript
const res = await fetch('https://panel.ornek.com/api/v1/admin/products/15/delivery-file', {
  method: 'DELETE',
  headers: { Authorization: `Bearer ${apiKey}` },
});

const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/products/15/delivery-file');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'DELETE',
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
$response = Api::Products()->DeleteProductDeliveryFile(['id' => 15]);
```

### Sipariş Görselini Ayarlama

put/api/v1/admin/products/{id}/order-image

`Products/SetProductOrderImage` admin tek görsel

Sipariş ekranında görünen görseli ayarlar. Ürün bundan bir tane taşır.

Gövde 1

imagestringzorunluGörsel. base64 veri adresi ya da indirilebilir bir bağlantı.

Dönen alanlar data — 1

urlstringGörselin genel adresi.

Hatalar 5

not_found404Ürün bulunamadı.

file_required422Dosya alanı boş.

file_invalid422Dosya çözümlenemedi ya da tipi kabul edilmedi.

file_failed422Dosya saklanamadı.

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl -X PUT 'https://panel.ornek.com/api/v1/admin/products/15/order-image' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"image":"https://cdn.example.com/plan.png"}'
```

```javascript
const res = await fetch('https://panel.ornek.com/api/v1/admin/products/15/order-image', {
  method: 'PUT',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ image: 'https://cdn.example.com/plan.png' }),
});

const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/products/15/order-image');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'PUT',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'image' => 'https://cdn.example.com/plan.png',
    ]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
$response = Api::Products()->SetProductOrderImage([
    'id'    => 15,
    'image' => 'https://cdn.example.com/plan.png',
]);
```

### Sipariş Görselini Silme

delete/api/v1/admin/products/{id}/order-image

`Products/DeleteProductOrderImage` admin

Sipariş görselini kaldırır.

Dönen alanlar data — 2

deletedboolSilme başarılı mı.

idintÜrün kimliği.

Hatalar 2

not_found404Ürün bulunamadı.

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl -X DELETE 'https://panel.ornek.com/api/v1/admin/products/15/order-image' \
  -H "Authorization: Bearer $API_KEY"
```

```javascript
const res = await fetch('https://panel.ornek.com/api/v1/admin/products/15/order-image', {
  method: 'DELETE',
  headers: { Authorization: `Bearer ${apiKey}` },
});

const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/products/15/order-image');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'DELETE',
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
$response = Api::Products()->DeleteProductOrderImage(['id' => 15]);
```

## Tuzaklar

> **Aynı adres tek görseli de tüm galeriyi de siler**
> 
> Galeriyi temizleme ile tek görsel silme **aynı adresi** kullanır; tek fark sondaki görsel kimliğidir. Kimliği boş bir değişkenden kuran kod, silmek istediği tek görsel yerine galerinin tamamını siler.

> **Sıralamada listenin tamamı gönderilir**
> 
> Sıralama ucu verdiğiniz listeyi sıra olarak kabul eder; listede olmayan görsellerin yeri belirsizleşir. Bir görseli öne almak için bile önce galeriyi okuyup tüm kimlikleri göndermek gerekir. Yeni yüklenen görsel her zaman listenin sonuna eklenir.

> **Rol değiştirmek dosyayı taşır**
> 
> Bir görselin rolünü değiştirmek dosyayı klasörler arasında taşır, yani **eski adresi çalışmaz hâle gelir**. Adresi kendi tarafınızda sakladıysanız güncellemeden sonra yeniden okuyun.

> **Teslimat dosyası tekildir ve uzantı kısıtlıdır**
> 
> Yeni bir teslimat dosyası yüklemek öncekini **kaldırır**; ürün aynı anda iki sürüm taşıyamaz. Ayrıca çalıştırılabilir sayfa uzantıları kabul edilmez: sunucuda çalışacak bir dosyayı müşteriye teslim etmenin yolu yoktur.

## İlgili Makaleler

- [Ürün Uçları](https://dev.wisecp.com/tr/urun-uclari)
- [Ürün Kategorileri](https://dev.wisecp.com/tr/urun-kategorileri)
