# Site Kategorileri

https://dev.wisecp.com/tr/site-kategorileri

Blog ve referans kategorilerini kuran, taşıyan ve kaldıran yedi uç.

## Genel Bakış

Kategoriler **iki içerik tipinde** vardır: blog yazıları ve referanslar. Düz sayfaların, sözleşmelerin ve haberlerin kategorisi yoktur, bu yüzden bu uçlarda da yer almazlar.

Kategoriler bir **ağaç** kurar. Her kaydın bir üst kategorisi olabilir ve sıfır onu köke koyar. Bu bilgi yalnız detay ucunda döner; liste kayıtları düz sırayla verir.

Yapı sayfalarınkiyle aynıdır: içerik **dil başına** tutulur, tip oluşturmada sabitlenir ve adres her dilde benzersizdir. Görsel tarafı daha basittir; kategorinin tek bir başlık görseli vardır.

## Referans

### Kategorileri Listeleme

get/api/v1/admin/website/categories

`Website/GetCategories` admin

Seçtiğiniz tipteki kategorileri döndürür.

Sorgu 4

typestringHangi tip: `articles`, `references`. Öntanımlı olarak blog kategorileri.

searchstringBaşlıkta arar.

pageintKaçıncı sayfa.

limitintSayfa başına kayıt. En çok yüz.

Dönen alanlar data[] — 6 + meta — 5

idintKategorinin numarası.

typestringKategori tipi.

statusstringKategori yayında mı.

titlestringGeçerli dildeki başlığı.

routestringGeçerli dildeki adresi.

created_atstringOluşturulma anı.

totalintToplam kayıt. Meta altında döner.

pageintBulunulan sayfa.

limitintSayfa boyutu.

type stringSüzülen tip.

next_pageintSonraki sayfa. Sıfır, son sayfadasınız demektir.

Hatalar 2

invalid_type422Kategori tipi tanınmıyor.

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

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

```bash
curl 'https://panel.ornek.com/api/v1/admin/website/categories?type=articles' \
  -H "Authorization: Bearer $API_KEY"
```

```javascript
const url = new URL('https://panel.ornek.com/api/v1/admin/website/categories');
url.searchParams.set('type', 'articles');

const res  = await fetch(url, {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/website/categories?' . http_build_query(['type' => 'articles']));
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

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

```php
// Liste UST KATEGORIYI tasimaz: agaci kurmak icin her kaydi ayrica okumaniz gerekir.
$cats = Api::Website()->GetCategories([], ['type' => 'articles'])['data'];
```

### Kategori Detayı

get/api/v1/admin/website/categories/{id}

`Website/GetCategory` admin

Tek bir kategoriyi bütün dilleriyle döndürür.

Dönen alanlar data — 9

idintKategorinin numarası.

typestringKategori tipi: `articles`, `references`.

parentintÜst kategori. Sıfır, kategorinin kökte olduğunu söyler.

rankintListedeki sırası.

statusstringKategori yayında mı.

optionsobjectKategoriye ait seçenekler. Arama motoru tercihi burada durur.

created_atstring | nullOluşturulma anı.

languagesobjectDil başına başlık, adres, açıklama ve arama motoru alanları.

imagestring | nullBaşlık görselinin adresi.

Hatalar 2

category_not_found404Kategori bulunamadı.

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

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

```bash
curl 'https://panel.ornek.com/api/v1/admin/website/categories/3' \
  -H "Authorization: Bearer $API_KEY"
```

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

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

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

```php
// Ust kategori numarasi YALNIZ burada gelir; agac bu alandan kurulur.
$cat    = Api::Website()->GetCategory(['id' => $id])['data'];
$isRoot = $cat['parent'] === 0;
```

### Kategori Oluşturma

post/api/v1/admin/website/categories

`Website/CreateCategory` admin tip sonradan değişmez

Yeni bir kategori açar ve dillerini yazar.

Gövde 7

typestringreqKategori tipi: `articles`, `references`. Sonradan değiştirilemez.

languagesobjectreqDil başına içerik: başlık, adres, açıklama ve arama motoru alanları. Gönderdiğiniz her dilde başlık gerekir.

statusstringKategori yayında mı. Öntanımlı olarak yayında.

rankintListedeki sırası.

seo_indexintArama motorlarının kategoriyi dizine almasına izin verir.

parentintÜst kategori. Sıfır, kategoriyi köke koyar.

imagestringAynı istekte yüklenecek başlık görseli. Adres ya da gömülü veri olarak verilebilir.

Dönen alanlar 201 — data — 9

dataobjectOluşan kategori. Detay ucuyla aynı şekildedir.

Hatalar 6

invalid_type422Kategori tipi tanınmıyor.

languages_required422Hiç dil gönderilmedi.

title_required422Bir dilde başlık boş.

route_exists422Bu adres o dilde zaten kullanılıyor.

create_failed500Kategori oluşturulamadı.

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/website/categories' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"type":"articles","languages":{"tr":{"title":"Duyurular"}}}'
```

```javascript
const res = await fetch('https://panel.ornek.com/api/v1/admin/website/categories', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    type: 'articles',
    languages: { en: { title: 'Announcements' } },
  }),
});

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

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/website/categories');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'type'      => 'articles',
        'languages' => ['en' => ['title' => 'Announcements']],
    ]),
]);

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

```php
// Alt kategori kurmak icin UST numarasini verin; sifir kategoriyi koke koyar.
Api::Website()->CreateCategory([
    'type'      => 'articles',
    'parent'    => $parentId,
    'languages' => ['en' => ['title' => 'Release notes']],
]);
```

### Kategoriyi Güncelleme

patch/api/v1/admin/website/categories/{id}

`Website/UpdateCategory` admin

Kategorinin gönderdiğiniz alanlarını ve dillerini değiştirir.

Gövde 6

languagesobjectreqDil başına içerik: başlık, adres, açıklama ve arama motoru alanları. Gönderdiğiniz her dilde başlık gerekir.

statusstringKategori yayında mı. Öntanımlı olarak yayında.

rankintListedeki sırası.

seo_indexintArama motorlarının kategoriyi dizine almasına izin verir.

parentintÜst kategori. Sıfır, kategoriyi köke koyar.

imagestringAynı istekte yüklenecek başlık görseli. Adres ya da gömülü veri olarak verilebilir.

Dönen alanlar data — 9

dataobjectGüncel kategori. Detay ucuyla aynı şekildedir.

Hatalar 4

category_not_found404Kategori bulunamadı.

title_required422Bir dilde başlık boşaltıldı.

route_exists422Bu adres o dilde zaten kullanılıyor.

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/website/categories/3' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"status":"inactive"}'
```

```javascript
const res = await fetch(`https://panel.ornek.com/api/v1/admin/website/categories/${id}`, {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ status: 'inactive' }),
});

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

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/website/categories/' . $id);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'PATCH',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['status' => 'inactive']),
]);

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

```php
// Ust kategoriyi degistirmek AGACI tasir; altindakiler onunla birlikte gelir.
Api::Website()->UpdateCategory(['id' => $id, 'parent' => $newParent]);
```

### Kategoriyi Silme

delete/api/v1/admin/website/categories/{id}

`Website/DeleteCategory` admin alt kategoriler de gider

Kategoriyi ve altındaki bütün kategorileri kaldırır.

Dönen alanlar data — 3

deletedboolSilme çalıştı mı.

idintSilinen kategorinin numarası.

removedarraySilinen bütün numaralar. Alt kategoriler de bu listede yer alır.

Hatalar 2

category_not_found404Kategori 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/website/categories/3' \
  -H "Authorization: Bearer $API_KEY"
```

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

const { data } = await res.json();
console.log(data.removed);   // [3, 7, 8]
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/website/categories/' . $id);
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
// Kac kaydin gittigini DONEN listeden okuyun; tek numara sandiginiz cagri bir dal silebilir.
$gone = Api::Website()->DeleteCategory(['id' => $id])['data']['removed'];
```

### Kategori Görseli Yükleme

put/api/v1/admin/website/categories/{id}/image

`Website/UploadCategoryImage` admin

Kategorinin başlık görselini yükler ve öncekinin yerine koyar.

Gövde 1

imagestringreqYüklenecek görsel. Küçük resmi de üretilir.

Dönen alanlar 201 — data — 2

kindstringGörsel türü. Kategoride tek tür vardır.

urlstringGörselin genel adresi.

Hatalar 2

category_not_found404Kategori bulunamadı.

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/website/categories/3/image' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"image":"https://ornek.com/kapak.jpg"}'
```

```javascript
const res = await fetch(`https://panel.ornek.com/api/v1/admin/website/categories/${id}/image`, {
  method: 'PUT',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ image: 'https://example.com/cover.jpg' }),
});

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

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/website/categories/' . $id . '/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://example.com/cover.jpg']),
]);

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

```php
// Kategoride TEK gorsel vardir; sayfalardaki gibi tur secmeye gerek yoktur.
Api::Website()->UploadCategoryImage(['id' => $id, 'image' => $data]);
```

### Kategori Görselini Kaldırma

delete/api/v1/admin/website/categories/{id}/image

`Website/DeleteCategoryImage` admin

Kategorinin başlık görselini kaldırır.

Dönen alanlar data — 2

deletedboolSilme çalıştı mı.

idintKategorinin numarası.

Hatalar 2

category_not_found404Kategori 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/website/categories/3/image' \
  -H "Authorization: Bearer $API_KEY"
```

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

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

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/website/categories/' . $id . '/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
// Gorseli DEGISTIRMEK icin once silmeye gerek yok; yukleme zaten yerine koyar.
Api::Website()->DeleteCategoryImage(['id' => $id]);
```

## Tuzaklar

> **Silme dalın tamamını götürür**
> 
> Bir kategoriyi silmek **altındaki bütün kategorileri** de siler. Tek kayıt sildiğinizi sanırken bir ağaç dalı gidebilir. Yanıttaki silinenler listesi gerçekte ne gittiğini söyler; onu okumadan işlemi başarılı saymayın. Silmeden önce detayı okuyup üst kategori bağlarını görmek en güvenlisidir.

> **Liste ağacı göstermez**
> 
> Listeleme ucu üst kategori alanını **döndürmez**; kayıtları düz bir sıra hâlinde verir. Yani listeden bir ağaç kuramazsınız. Hiyerarşiye ihtiyacınız varsa her kaydı detay ucundan okumanız gerekir; kategori sayısı azdır, bu genelde sorun çıkarmaz.

> **Tip oluşturmada sabitlenir**
> 
> Kategori tipi kaydın kimliğinin parçasıdır ve **güncelleme onu yoksayar**. Blog kategorisi olarak açılmış bir kayıt referans kategorisine dönüşmez. Yanlış tiple açılan bir kategoriyi düzeltmek, doğru tiple yenisini kurup içindekileri taşımak demektir.

> **Adres dil başına benzersizdir**
> 
> Aynı adres **farklı dillerde** yan yana durabilir, ama tek bir dilde iki kategori aynı adresi taşıyamaz. Kategoriler ve sayfalar aynı adres alanını paylaştığı için bir kategorinin adresi bir sayfayla da çakışabilir. Adres göndermezseniz başlıktan üretilir.

> **Üst kategoriyi değiştirmek dalı taşır**
> 
> Güncellemede üst kategoriyi değiştirmek, kategorinin **altındakileri de birlikte** taşır. Bir kategoriyi kendi altındaki bir kategorinin altına koymak ise ağacı kendi üzerine kapatır ve o dal listelerden düşer. Taşımadan önce hedefin taşınan dalın içinde olmadığından emin olun.

## İlgili Makaleler

- [Site Sayfaları](https://dev.wisecp.com/tr/site-sayfalari)
- [Site Menüleri](https://dev.wisecp.com/tr/site-menuleri)
- [Müşteri Yorumları](https://dev.wisecp.com/tr/musteri-yorumlari)
