# Yedek Depolama

https://dev.wisecp.com/tr/yedek-depolama

Yedeklerin gönderileceği depolama hedeflerini kuran, sınayan ve kaldıran dokuz uç.

## Genel Bakış

Depolama hedefi, yedeklerin **nereye gönderileceğini** tanımlar. Dokuz uç bu hedefleri kurar, sınar ve kaldırır. Yedeklerin ne zaman alınacağı ayrı bir konudur.

Sağlayıcılar iki gruba ayrılır. **Sunucu tipi** olanlar adres ve şifreyle kurulur. **Bulut tipi** olanlar ise kullanıcının tarayıcıda onay vermesini bekler. O yolda üç adım vardır: onay adresi al, kullanıcıyı gönder, dönen belirteçle hedefi oluştur.

Bir hedef kaydedilmeden önce **gerçekten bağlanılır**. Yanlış şifre yedek gecesinde değil, hedefi yazdığınız anda ortaya çıkar.

## Referans

### Sağlayıcıları Listeleme

get/api/v1/admin/settings/backup/storage/providers

`Settings/GetBackupStorageProviders` admin

Yedeklerin gönderilebileceği kurulu depolama sağlayıcılarını döndürür.

Dönen alanlar data[] — 5

keystringSağlayıcının anahtarı. Hedef oluştururken bu kullanılır.

namestringSağlayıcının adı.

descriptionstringNe yaptığı.

oauthboolKullanıcı onayı gerektirip gerektirmediği. Doğruysa yalnız ayar yazmak yetmez.

fieldsarraySağlayıcının istediği ayarların tanımı.

Hatalar 1

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

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

```bash
curl 'https://panel.ornek.com/api/v1/admin/settings/backup/storage/providers' \
  -H "Authorization: Bearer $API_KEY"
```

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

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

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

```php
// Sunucu-tipi saglayici ayarla kurulur; bulut saglayici KULLANICI ONAYI ister.
$providers = Api::Settings()->GetBackupStorageProviders()['data'];
$simple    = array_filter($providers, fn ($p) => ! $p['oauth']);
```

### Bağlantıyı Sınama

post/api/v1/admin/settings/backup/storage/validate

`Settings/ValidateBackupStorage` admin

Bir yapılandırmayı kaydetmeden bağlantı sınamasından geçirir.

Gövde 3

typestringreqSınanacak sağlayıcı. Hedef kimliği vermezseniz zorunludur.

idintVar olan hedefin kimliği. Ayarları ondan alınır.

configobjectSağlayıcının ayarları. Gizli alanlar maskeyle korunur.

Dönen alanlar data — 2

validatedboolBağlantı kuruldu mu.

messagestringSonucun açıklaması.

Hatalar 3

unknown_provider422Sağlayıcı tanınmıyor.

module_not_loadable422Sağlayıcı yüklenemedi.

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/settings/backup/storage/validate' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"type":"FTP","config":{"host":"ftp.ornek.com","username":"backup","password":"gizli"}}'
```

```javascript
const res = await fetch('https://panel.ornek.com/api/v1/admin/settings/backup/storage/validate', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    type: 'FTP',
    config: { host: 'ftp.example.com', username: 'backup', password: secret },
  }),
});

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

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/settings/backup/storage/validate');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'type'   => 'FTP',
        'config' => ['host' => 'ftp.example.com', 'username' => 'backup', 'password' => $secret],
    ]),
]);

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

```php
// Sinama HICBIR SEY KAYDETMEZ: gecmesi hedefin olustugu anlamina gelmez.
$check = Api::Settings()->ValidateBackupStorage([
    'type'   => 'FTP',
    'config' => $config,
])['data'];

if ($check['validated']) Api::Settings()->CreateBackupStorage($payload);
```

### Onay Adresi Alma

post/api/v1/admin/settings/backup/storage/oauth-url

`Settings/GetBackupOauthUrl` admin

Bulut sağlayıcılar için kullanıcının onay vereceği adresi üretir.

Gövde 3

typestringreqOnay isteyen sağlayıcı.

idintVar olan hedefin kimliği.

configobjectSağlayıcının ayarları.

Dönen alanlar data — 2

authorize_urlstringKullanıcının yönlendirileceği adres.

statestringİmzalı durum değeri. Dönüşte bunun eşleşmesi beklenir.

Hatalar 4

unknown_provider422Sağlayıcı tanınmıyor.

oauth_unsupported422Sağlayıcı onay akışı kullanmıyor.

oauth_url_failed422Adres üretilemedi.

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/settings/backup/storage/oauth-url' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"type":"GoogleDrive"}'
```

```javascript
const res = await fetch('https://panel.ornek.com/api/v1/admin/settings/backup/storage/oauth-url', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ type: 'GoogleDrive' }),
});

const { data } = await res.json();
window.location.href = data.authorize_url;
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/settings/backup/storage/oauth-url');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['type' => 'GoogleDrive']),
]);

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

```php
// Adres tek basina yetmez: kullanici onay verip donmeden hedef OLUSTURULAMAZ.
$url = Api::Settings()->GetBackupOauthUrl(['type' => 'GoogleDrive'])['data']['authorize_url'];
```

### Bunny Alanlarını Getirme

post/api/v1/admin/settings/backup/storage/bunny-zones

`Settings/GetBunnyZones` admin

Verilen hesap anahtarına bağlı Bunny depolama alanlarını döndürür.

Gövde 2

account_api_keystringreqBunny hesap anahtarı. Maske gönderirseniz hedef kimliği de gerekir.

idintVar olan hedefin kimliği.

Dönen alanlar data — 1

zonesarrayHesaba bağlı depolama alanları.

Hatalar 3

api_key_required422Hesap anahtarı verilmedi.

fetch_zones_failed422Alan listesi alınamadı.

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/settings/backup/storage/bunny-zones' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"account_api_key":"'"$BUNNY_KEY"'"}'
```

```javascript
const res = await fetch('https://panel.ornek.com/api/v1/admin/settings/backup/storage/bunny-zones', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ account_api_key: bunnyKey }),
});

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

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/settings/backup/storage/bunny-zones');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['account_api_key' => $bunnyKey]),
]);

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

```php
// Kayitli hedefin anahtari maskeli doner; maskeyi geri gonderirken KIMLIGI de verin.
$zones = Api::Settings()->GetBunnyZones([
    'account_api_key' => '*****',
    'id'              => $storageId,
])['data']['zones'];
```

### Hedefleri Listeleme

get/api/v1/admin/settings/backup/storage

`Settings/GetBackupStorages` admin

Tanımlı yedek depolama hedeflerini döndürür.

Sorgu 1

searchstringAda göre arar.

Dönen alanlar data[] — 6

idintHedefin kimliği.

namestringHedefin adı.

typestringSağlayıcı tipi.

statusstringHedefin durumu.

validated_atstring | nullBağlantının son sınandığı an. Boşsa hedef hiç sınanmamıştır.

created_atstring | nullOluşturulma anı.

Hatalar 1

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

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

```bash
curl 'https://panel.ornek.com/api/v1/admin/settings/backup/storage' \
  -H "Authorization: Bearer $API_KEY"
```

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

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

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

```php
// Son sinama ani ESKI olabilir: sifre o gunden beri degismis olabilir.
$targets = Api::Settings()->GetBackupStorages()['data'];
$stale   = array_filter($targets, fn ($t) => $t['validated_at'] === null);
```

### Hedef Oluşturma

post/api/v1/admin/settings/backup/storage

`Settings/CreateBackupStorage` admin önce bağlanır

Yeni bir depolama hedefi kurar; kaydetmeden önce bağlanmayı dener.

Gövde 3

namestringreqHedefin adı. En çok 150 karakter.

typestringreqSağlayıcı anahtarı.

configobjectSağlayıcının ayarları. Bulut sağlayıcıda onay belirteci de gerekir. Gönderilmeyen onay kutusu kapalı kaydedilir: FTP'nin `ssl` (FTPS) alanı panel formunda açık gelir; bağlantının şifreli kalması için `"ssl": 1` gönderin.

Dönen alanlar 201 — data

dataobjectOluşan hedef. Detay ucuyla aynı şekildedir ve gizli alanlar maskelenir.

Hatalar 5

name_required422Ad boş.

invalid_provider422Sağlayıcı geçersiz.

oauth_required422Bulut sağlayıcı için onay eksik.

storage_test_failed422Bağlantı kurulamadı.

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/settings/backup/storage' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"name":"Uzak FTP","type":"FTP","config":{"host":"ftp.ornek.com","username":"backup","password":"gizli","folder_path":"/backups"}}'
```

```javascript
const res = await fetch('https://panel.ornek.com/api/v1/admin/settings/backup/storage', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: 'Offsite FTP',
    type: 'FTP',
    config: {
      host: 'ftp.example.com',
      username: 'backup',
      password: secret,
      folder_path: '/backups',
    },
  }),
});

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

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/settings/backup/storage');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'name'   => 'Offsite FTP',
        'type'   => 'FTP',
        'config' => [
            'host'        => 'ftp.example.com',
            'username'    => 'backup',
            'password'    => $secret,
            'folder_path' => '/backups',
        ],
    ]),
]);

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

```php
// Maske burada ISE YARAMAZ: korunacak eski deger yok, gercek sifreyi gonderin.
Api::Settings()->CreateBackupStorage([
    'name'   => 'Offsite FTP',
    'type'   => 'FTP',
    'config' => ['host' => $host, 'username' => $user, 'password' => $secret],
]);
```

### Hedef Detayı

get/api/v1/admin/settings/backup/storage/{id}

`Settings/GetBackupStorage` admin

Tek bir hedefi ayarlarıyla birlikte döndürür.

Dönen alanlar data — 7

idintHedefin kimliği.

namestringHedefin adı.

typestringSağlayıcı tipi.

statusstringHedefin durumu.

configobjectSağlayıcının ayarları. Gizli alanlar maskelenmiş gelir.

validated_atstring | nullBağlantının son sınandığı an.

created_atstring | nullOluşturulma anı.

Hatalar 2

not_found404Hedef bulunamadı.

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

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

```bash
curl 'https://panel.ornek.com/api/v1/admin/settings/backup/storage/12' \
  -H "Authorization: Bearer $API_KEY"
```

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

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

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

```php
// Okudugunuzu OLDUGU GIBI baska bir hedef olusturmak icin kullanmayin: sifre maskelidir.
$target = Api::Settings()->GetBackupStorage(['id' => $id])['data'];
```

### Hedefi Güncelleme

patch/api/v1/admin/settings/backup/storage/{id}

`Settings/UpdateBackupStorage` admin

Hedefin adını ve ayarlarını değiştirir.

Gövde 2

namestringYeni ad.

configobjectSağlayıcının ayarları; nesne bütün olarak yazılır. Tüm alanları gönderin: eksik bıraktığınız metin alanı düşer, onay kutusu ve sayı alanları sıfıra döner. `*****` şifreli alanın eski değerini korur.

Dönen alanlar data

dataobjectHedefin son hâli. Detay ucuyla aynı şekildedir ve gizli alanlar maskelenir.

Hatalar 5

not_found404Hedef bulunamadı.

name_required422Ad boş.

oauth_required422Bulut sağlayıcı için onay eksik.

storage_test_failed422Bağlantı kurulamadı.

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/settings/backup/storage/12' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"name":"Uzak FTP (AB)","config":{"folder_path":"/backups-eu","password":"*****"}}'
```

```javascript
const res = await fetch(`https://panel.ornek.com/api/v1/admin/settings/backup/storage/${id}`, {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: 'Offsite FTP (EU)',
    config: { folder_path: '/backups-eu', password: '*****' },
  }),
});

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

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/settings/backup/storage/' . $id);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'PATCH',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'name'   => 'Offsite FTP (EU)',
        'config' => ['folder_path' => '/backups-eu', 'password' => '*****'],
    ]),
]);

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

```php
// Yol degisirse baglanti YENIDEN sinanir; yeni klasor yoksa guncelleme reddedilir.
Api::Settings()->UpdateBackupStorage([
    'id'     => $id,
    'config' => ['folder_path' => '/backups-eu', 'password' => '*****'],
]);
```

### Hedefi Silme

delete/api/v1/admin/settings/backup/storage/{id}

`Settings/DeleteBackupStorage` admin onay geri alınır

Bir depolama hedefini kaldırır.

Dönen alanlar data — 2

deletedboolSilme çalıştı mı.

idintSilinen hedefin kimliği.

Hatalar 3

not_found404Hedef bulunamadı.

storage_in_use422Bir zamanlama bu hedefi kullanıyor.

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/settings/backup/storage/12' \
  -H "Authorization: Bearer $API_KEY"
```

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

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

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/settings/backup/storage/' . $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
// Bulut hedefte silme ONAYI da geri alir: ayni hesabi yeniden eklemek yeni onay ister.
Api::Settings()->DeleteBackupStorage(['id' => $id]);
```

## Tuzaklar

> **Maske okumada korur, oluşturmada işe yaramaz**
> 
> Detay ve liste uçları gizli alanları maskeyle döndürür. Güncellemede maskeyi geri göndermek **eski değeri korur**. Oluşturmada ise korunacak eski değer yoktur: okuduğunuzu olduğu gibi yeni bir hedefe verirseniz şifre olarak maskenin kendisi kaydedilir ve bağlantı sınaması düşer.

> **Sınamak kaydetmek değildir**
> 
> Sınama ucu hiçbir şey kaydetmez; yalnız bağlantıyı dener. Geçmesi hedefin oluştuğu anlamına **gelmez**. Panelde iki adım arka arkaya göründüğü için bu karışır: sınama başarılı çıkar, oluşturma çağrısı unutulur ve zamanlamaya verecek bir hedef bulunamaz.

> **Bulut sağlayıcı ayarla kurulmaz**
> 
> Onay isteyen bir sağlayıcıda ayarları yazmak yetmez: kullanıcının tarayıcıda erişim vermesi gerekir. Belirteç olmadan oluşturma çağrısı **onay eksik** diyerek düşer. Sağlayıcı listesindeki onay alanı, hangi sağlayıcının bu üç adımlı yolu istediğini önceden söyler.

> **Zamanlamanın kullandığı hedef silinmez**
> 
> Bir zamanlama hedefe bağlıyken silme çağrısı reddedilir. Önce zamanlamayı başka bir hedefe taşıyın ya da kaldırın. Bu koruma **kasıtlıdır**: hedefi sessizce silmek, zamanlamayı her gece boşa çalışan bir işe çevirirdi.

> **Silmek onayı da geri alır**
> 
> Bulut hedefi silinirken sağlayıcıdaki erişim izni de **iptal edilir**. Aynı hesabı yeniden eklemek yeni bir onay turu ister; eski belirteç işe yaramaz. İptal elden geldiğince denenir, yani sağlayıcıya ulaşılamazsa hedef yine de silinir ve izin sağlayıcı tarafında kalabilir.

## İlgili Makaleler

- [Yedek Zamanlamaları](https://dev.wisecp.com/tr/yedek-zamanlamalari)
- [Yedek Tanılaması](https://dev.wisecp.com/tr/yedek-tanilamasi)
- [Zamanlanmış Görev Ekleme](https://dev.wisecp.com/tr/zamanlanmis-gorev-ekleme)
