Geliştirici referansı · 29 Ağustos 2026

CloudUtcu API

Dosya, paylaşım, plan ve destek uçlarının tamamı. Uygulamanızı bu belgeye göre yazın; sunucu tarafındaki kurallar burada yazdığı gibi zorlanıyor.

  • KimlikBearer + refresh çerezi
  • BiçimJSON (akışlar hariç)
  • Genel sınır300 istek / dk / IP
  • Token ömrü15 dk / 30 gün

Uygulama geliştirenler için referans. Temel adres: https://cloudutcu.com

Tüm istekler ve yanıtlar JSON (dosya akışları hariç). Hata gövdesi:

{ "error": "kod_adi", "message": "Kullanıcıya gösterilebilir mesaj" }

message Türkçedir ve doğrudan gösterilebilir. error programatik kontrol içindir; sık karşılaşılanlar bölüm 12'de listeli.

Tarayıcıdan çağıracaksanız: CORS yalnızca https://cloudutcu.com kaynağına açık ve credentials gerektiriyor. Başka bir origin'den yapılan tarayıcı isteği reddedilir; mobil ve sunucu tarafı istemciler etkilenmez.


1Kimlik doğrulama

Kısa ömürlü access token (15 dakika) + uzun ömürlü refresh token (30 gün).

Korumalı uçlara erişim:

Authorization: Bearer <accessToken>

Refresh token httpOnly çerezle taşınır. Mobilde çerez saklayan bir HTTP istemcisi kullanın (OkHttp CookieJar, URLSession varsayılanı) — ya da çerezi hiç kullanmayın: belirtecModu ile refresh token gövdede döner (aşağıda "Çerezsiz (gövde tabanlı) oturum").

POST/api/auth/register

{
  "email": "[email protected]",
  "password": "EnAz8Karakter1",
  "fullName": "Ad Soyad",
  "phone": "+905550000000",
  "country": "Türkiye"
}

Şifre: en az 8 karakter, bir küçük harf, bir büyük harf, bir rakam. Küçük/büyük harf kontrolü Türkçe harfleri de tanır (ş, ı, ğ, ç, ö, ü). phone ve country isteğe bağlı.

201{ "accessToken": "...", "user": { ... } }

Kayıtta depolama hesabı otomatik açılır, doğrulama e-postası gönderilir. Doğrulama yapılmadan dosya yüklenemez (bölüm 3).

POST/api/auth/login

{ "email": "[email protected]", "password": "..." }

İki olası 200 yanıtı var; istemci ikisini de ele almalı.

Normal hesap:

{ "accessToken": "...", "user": { ... } }

İki adımlı doğrulaması açık hesap:

{ "totpRequired": true, "challenge": "..." }

İkincisinde oturum açılmazaccessToken yok, çerez yazılmaz. challenge 5 dakika geçerlidir ve yalnızca POST /api/auth/login/2fa ucunda kullanılır; erişim belirteci yerine geçmez (korumalı bir uca sunulursa 401 invalid_token).

401 hatalı bilgi · 403 account_frozen.

Var olmayan hesap için de şifre doğrulama süresi kadar beklenir; yanıt süresinden hangi adreslerin kayıtlı olduğu anlaşılmasın diye.

Dondurulmuş hesap giriş yapamaz: doğru şifreyle bile 403 account_frozen döner ve oturum açılmaz. Kontrol şifre doğrulandıktan *sonra* yapılır — aksi halde yanlış şifreyle bile bu cevap dönerdi ve uç, hesabın var olup olmadığını söyleyen bir numaralandırma aracına dönerdi.

Dondurma açık oturumları da düşürür: yönetim hesabı dondurduğu anda o kullanıcının bütün refresh token'ları iptal edilir, POST /api/auth/refresh de 403 account_frozen döner ve çerez temizlenir. İstemci bu kodu gördüğünde kullanıcıyı çıkışa alıp mesajı göstermeli. İtiraz kanalı açıktır: iletişim formu (POST /api/public/contact) oturum gerektirmez.

POST/api/auth/login/2fa

{ "challenge": "...", "code": "123456" }

code doğrulama uygulamasındaki 6 haneli kod veya bir yedek koddur (ABCD-2345; tire ve küçük harf tolere edilir).

200{ "accessToken": "...", "user": { ... } }

Yedek kod kullanıldıysa yanıt ayrıca yedekKodKullanildi: true ve kalanYedekKod taşır — kullanıcıya kaç kod kaldığını gösterin, tükenmeden yenilemesi için tek uyarı bu.

401 invalid_totp (kod hatalı) · 401 totp_expired (challenge süresi doldu — baştan giriş yapın) · 403 account_frozen.

Kod ±30 saniyelik pencereyi kabul eder (telefon saati kayması için). Sınır: hesap başına 15 dakikada 10 deneme.

Bir kod tek kullanımlıktır (RFC 6238 §5.2): doğrulandıktan sonra aynı kod penceresi bitene kadar tekrar gönderilirse 401 invalid_totp döner. Aynı kural 2FA kapatma ve yedek kod yenileme uçlarında da geçerli.

POST/api/auth/refresh

Gövde {} ve Content-Type: application/json gönderilmelidir. Gövdesiz POST 415 ile reddedilebilir.

200{ "accessToken": "...", "user": { ... } } · 401 oturum yok (no_session).

Refresh token tek kullanımlıktır. Eşzamanlı yenileme göndermeyin — biri diğerini geçersiz kılar ve kullanıcı düşer. İstemcide tüm yenilemeleri tek bir çağrıda toplayın.

Çerezsiz (gövde tabanlı) oturum

Tarayıcı için doğru olan httpOnly çerez, çerez kavramı olmayan istemcilerde (mobil uygulama, CLI, sunucu tarafı entegrasyon) kullanılamıyor. register, login ve login/2fa uçlarına belirtecModu: true gönderirseniz yenileme belirteci yanıt gövdesinde döner ve çerez yazılmaz:

// POST /api/auth/login  {"email":"...","password":"...","belirtecModu":true}
{
  "accessToken": "...",
  "refreshToken": "...",
  "refreshExpiresAt": "2026-09-27T12:00:00.000Z",
  "user": { }
}

Yenilemek için aynı /api/auth/refresh ucuna belirteci gövdede gönderin; yanıt yine gövdede yeni bir belirteç taşır:

// POST /api/auth/refresh  {"refreshToken":"..."}
{ "accessToken": "...", "refreshToken": "...", "refreshExpiresAt": "...", "user": { } }

Çıkışta da aynısı: POST /api/auth/logout gövdesinde { "refreshToken": "..." }.

Dikkat edilecekler:

Uygulama belirteçleri (API anahtarları)

Üçüncü taraf bir entegrasyona kullanıcının şifresini vermeden erişim açar. Şifreyle giriş yapmanın üç sorunu vardı: şifre entegrasyonun elinde kalıyor, yetki daraltılamıyor, tek tek iptal edilemiyordu.

Belirteç clu_ ile başlar ve normal erişim belirteci gibi gönderilir:

Authorization: Bearer clu_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Yönetimi oturum gerektirir — bir belirteç kendini çoğaltamaz, kardeşlerini iptal edemez:

Açıklama
POST /api/anahtarlargövde { "name": "Yedekleme betiği", "scopes": ["files:read"], "expiresInDays": 365 }201
GET /api/anahtarlarkendi belirteçleriniz + tanınan yetki listesi
DELETE /api/anahtarlar/:idiptal — 204, anında geçerli

Oluşturma yanıtı belirtecin açık halini bir kez döndürür:

{
  "deger": "clu_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",   // yalnızca burada
  "anahtar": { "id": "...", "name": "Yedekleme betiği", "prefix": "abcd1234",
               "scopes": ["files:read"], "expiresAt": "...", "lastUsedAt": null }
}

Sunucu yalnızca sha256 özetini saklar; "belirteci tekrar göster" diye bir uç yoktur ve olamaz. Kaybederseniz yenisini oluşturup eskisini iptal edin. Listede belirteci prefix tanıtır. Hesap başına en fazla 20 belirteç (400 too_many_keys), oluşturmak doğrulanmış e-posta ister.

#### Yetkiler

YetkiNe açar
files:readGET /api/files/* — listeleme, arama, indirme, kota, sürümler
files:writeyükleme, klasör açma, taşıma, kopyalama, silme, çöp kutusu
shares:readGET /api/shares
shares:writebağlantı oluşturma ve iptal

Bilinmeyen bir yetki sessizce atılmaz: 400 invalid_scope. Boş liste 400 no_scopes.

#### Nereye erişebilir

Belirteç yalnızca /api/files ve /api/shares altına girebilir. Bu bir izin listesi: listede olmayan her uç kapalıdır ve yarın eklenen bir uç da kendiliğinden kapalı olur. Hesap ayarları, şifre değiştirme, hesap silme, ödeme, destek ve yönetim uçları hiçbir yetkiyle açılmaz — 403 api_key_not_allowed.

Okuma/yazma ayrımı HTTP yöntemine göre: GET ve HEAD okuma, gerisi yazma sayılır. Tek istisna gövdesinde yol taşıdığı için POST olan iki uç — /api/files/onizleme-anahtari ve /api/files/kucukresim-anahtari — okuma sayılır; yoksa salt okunur bir belirteç önizleme bile açamazdı. Yetki yetmezse 403 insufficient_scope.

#### Diğer davranışlar

Webhook bildirimleri

SSE (yukarıda) yalnızca açık bir sekmeye ve yalnızca "best effort" ulaşır: hiçbir olay saklanmaz, tekrar gönderilmez. Sunucu tarafında çalışan bir entegrasyon için webhook var — aynı olaylar, kalıcı kuyruk ve tekrar denemeyle sizin adresinize gönderilir.

Yönetimi oturum gerektirir (uygulama belirteçlerine kapalı):

Açıklama
POST /api/webhooklargövde { "url": "https://…", "events": ["dosya","kota"] }201
GET /api/webhooklarabonelikleriniz + tanınan olay listesi
POST /api/webhooklar/:id/denedeneme bildirimi hemen gönderir, sonucu döndürür
POST /api/webhooklar/:id/ackendiliğinden kapanmış aboneliği yeniden açar
POST /api/webhooklar/:id/gizli-yenileimza anahtarını yeniler (eski imzalar anında geçersiz)
GET /api/webhooklar/:id/teslimatlarson 20 teslimat ve durumları
DELETE /api/webhooklar/:id204

Hesap başına en fazla 10 abonelik (400 too_many_webhooks).

#### Adres kuralları

Adresi siz yazıyorsunuz, isteği bizim sunucumuz atıyor; bu yüzden adres dar bir süzgeçten geçer:

#### Olaylar

OlayNe zaman
dosyadosyalarınızda değişiklik (yükleme, silme, taşıma, paylaşıma bırakma)
paylasimpaylaşım bağlantınızdan indirme yapıldı
kotadepolama eşiğe yaklaştı veya doldu
talepdestek talebinize yanıt geldi
planplan süresi hakkında bilgi

Liste SSE ile aynı kümedir: webhook yeni bir olay evreni açmaz, SSE'nin "yalnızca açık sekme" sınırını kaldırır. Bilinmeyen olay 400 invalid_event, boş liste 400 no_events.

#### Gövde ve imza

İstek POST, gövde JSON:

{
  "id": "3f0c…",          // teslimat kimliği — tekrar teslimatı ayırt etmek için
  "olay": "dosya",
  "zaman": 1788001995,     // unix saniye
  "veri": { "islem": "/api/files/upload" }
}

Başlıklar:

Başlıkİçerik
x-cloudutcu-olayolay adı
x-cloudutcu-teslimatteslimat kimliği
x-cloudutcu-imzat=<unix>,v1=<hmac-sha256 hex>

İmza, <zaman>.<ham gövde> dizgisinin abonelik gizli anahtarıyla üretilmiş HMAC-SHA256'sıdır. Zaman damgası imzanın içindedir: yalnızca gövde imzalansaydı, bir teslimatı yakalayan biri aynı isteği sonsuza kadar tekrar oynatabilirdi.

// Node
import { createHmac, timingSafeEqual } from 'node:crypto';

const dogrula = (gizli, baslik, hamGovde) => {
  const alanlar = Object.fromEntries(baslik.split(',').map((p) => p.split('=')));
  const beklenen = createHmac('sha256', gizli)
    .update(`${alanlar.t}.${hamGovde}`)
    .digest('hex');
  return timingSafeEqual(Buffer.from(beklenen), Buffer.from(alanlar.v1));
};

Ham gövdeyi imzalayın — JSON'a çevirip yeniden dizgeye döken bir katman imzayı bozar. İmzayı doğrulamayan bir uç, size istek atabilen herkese açıktır. Gizli anahtar yalnızca oluşturma yanıtında bir kez döner.

#### Teslimat, tekrar ve kapanma

Web Push bildirimleri

Tarayıcı kapalıyken de ulaşan bildirim. SSE açık sekme ister, webhook bir sunucu adresi ister; bu üçüncüsü doğrudan kullanıcının cihazına gider.

Bu uçlar tarayıcı içindir — uygulama belirteçlerine kapalıdır ve oturum gerektirir.

Açıklama
GET /api/push/anahtarVAPID genel anahtarı + abone olunabilir olaylar
POST /api/push/abonegövde { "endpoint": "…", "keys": { "p256dh": "…", "auth": "…" }, "events": ["kota"], "label": "Chrome · Android" }201
GET /api/pushkayıtlı cihazlarınız
POST /api/push/:id/deneo cihaza deneme bildirimi gönderir
DELETE /api/push/:idcihazı kaldırır — 204

Sunucuda VAPID anahtarı tanımlı değilse bütün uçlar 503 push_disabled döner; özellik isteğe bağlıdır.

Olaylar: paylasim, kota, talep, plan. dosya bilerek yok — o olay neredeyse her zaman kullanıcının kendi eyleminden çıkıyor ve saniyeler içinde onlarca kez tetikleniyor; telefonu titreten bir akış, özelliği ilk günde kapattırırdı. Paylaşılan klasöre bırakılan dosya paylasim olayından duyurulur.

endpoint benzersizdir: aynı tarayıcı yeniden abone olduğunda kayıt çoğaltılmaz, güncellenir (sahiplik dâhil — aynı cihazdan başka bir hesaba giren kullanıcının bildirimleri eski hesaba gitmez).

Gövde uçtan uca şifrelidir (RFC 8291, aes128gcm): anahtarlar tarayıcının ürettiği p256dh/auth değerlerinden türer, yani bildirimi taşıyan sağlayıcı (Google, Mozilla, Apple) içeriği okuyamaz. İstek VAPID ile imzalanır (RFC 8292).

Service worker'a ulaşan gövde:

{ "baslik": "Depolama alanınız doluyor", "govde": "Alanınızın %91'i kullanıldı.", "yol": "/dashboard" }

Sağlayıcı bir aboneliği tanımazsa (404/410) kayıt silinir: kullanıcı izni geri almış ya da tarayıcı verisini temizlemiştir. Geçici hatada (zaman aşımı, 5xx) silinmez — sağlayıcının beş dakikalık bir kesintisi bütün cihazları listeden düşürmemeli.

Diğer kimlik uçları

Açıklama
POST /api/auth/logoutbu cihazın oturumu
POST /api/auth/logout-alltüm cihazlar — gövde { password }
POST /api/auth/forgot-password{ email } — her durumda { success: true }
POST /api/auth/reset-password{ token, password }
POST /api/auth/verify-email{ token } — tek kullanımlık
POST /api/auth/resend-verificationoturum gerektirir
GET /api/auth/me{ user } — güncel kullanıcı
PATCH /api/auth/profile{ fullName?, phone?, country?, birthday?, avatarUrl?, colorScheme? }
POST /api/auth/change-password{ currentPassword, newPassword } — diğer oturumları kapatır
GET /api/auth/sessionsson 20 giriş kaydı (yalnızca kendi)
POST /api/auth/hesabi-silhesabı ve dosyaları kalıcı siler — gövde { password }

colorScheme: blue, purple, green, orange, rose, cyan, amber, teal, red, indigo.

Profil ucu bilinçli olarak dardır: role, currentPlan ve storageLimitBytes kullanıcı tarafından değiştirilemez. Plan yalnızca ödeme ile veya yönetim panelinden değişir.

Hesap silme geri alınamaz. POST /api/auth/hesabi-sil önce depolama hesabını ve bütün dosyaları, sonra kullanıcı kaydını siler; açık oturumlar anında düşer. Şifre istenir çünkü işlem geri alınamaz ve açık unutulmuş bir sekmeden tetiklenebilir. Siparişler silinmez: userId boşa düşer ve faturada görünen e-posta satırda anlık görüntü olarak kalır — fatura kayıtlarının saklanması yasal zorunluluk.

Kullanıcı nesnesi

{
  "id": "uuid",
  "email": "[email protected]",
  "role": "user",
  "fullName": "Ad Soyad",
  "phone": "+90...",
  "country": "Türkiye",
  "birthday": null,
  "avatarUrl": null,
  "colorScheme": "blue",
  "emailVerified": true,
  "storageLimitBytes": 5368709120,
  "currentPlan": "Ücretsiz",
  "planExpiresAt": null,
  "credits": 0,
  "accountFrozen": false,
  "totpEnabled": false,
  "createdAt": "2026-07-31T..."
}

accountFrozen true ise giriş, yenileme, dosya uçları, ödeme başlatma (POST /api/orders/checkout) ve yönetim uçları 403 account_frozen döner. Son ikisi eskiden kapsam dışıydı: dondurma açık oturumları düşürüyor ama elde duran erişim belirtecini geçersiz kılamıyor (imzalı, 15 dakika ömürlü), yani donduruluş ile belirtecin ölümü arasında bir pencere kalıyordu. totpEnabled yalnızca "açık mı" bilgisidir; sır ve yedek kodlar hiçbir uçtan dönmez.

İki adımlı doğrulama (TOTP)

İsteğe bağlıdır; kullanıcı kendi açar. Standart TOTP — SHA-1, 6 hane, 30 saniye — yani Google Authenticator, 1Password, Bitwarden ve benzerleri çalışır.

Kurulum iki aşamalıdır ve bu bilinçlidir: sır üretildiği anda iki faktör açılsaydı, QR'ı taradığını sanıp taramamış bir kullanıcı hesabına kilitlenirdi. İlk kod doğrulanana kadar 2FA devrede değildir.

Açıklama
GET /api/auth/2fa/durum{ enabled, kalanYedekKod }
POST /api/auth/2fa/kurulum{ password }{ secret, otpauth } — sır üretilir, 2FA henüz açılmaz
POST /api/auth/2fa/etkinlestir{ code }{ success, yedekKodlar } — ilk kod doğrulanır, 2FA açılır
POST /api/auth/2fa/kapat{ password, code }code TOTP ya da yedek kod olabilir
POST /api/auth/2fa/yedek-kodlar{ password, code }{ yedekKodlar } — eskiler anında geçersiz

otpauth alanı doğrudan QR'a çevrilebilir. secret elle giriş içindir.

Yedek kodlar bir kez döner. Sunucuda yalnızca argon2 özetleri saklanır — şifreyle aynı muamele, çünkü işlevleri de aynı: tek başlarına hesabı açarlar. On adet üretilir, her biri bir kez kullanılabilir.

Telefonunu ve yedek kodlarını kaybeden kullanıcı için yönetim tarafında sıfırlama vardır; kullanıcıya e-posta gider ve işlem denetim kaydına yazılır.

Hata kodları: wrong_password, invalid_totp, totp_not_started (etkinleştirmeden önce kurulum çağrılmadı), totp_already_enabled, totp_not_enabled.

Oturum kaydı

GET /api/auth/sessions{ "sessions": [ ... ] }

{
  "id": "uuid",
  "ipAddress": "1.2.3.4",
  "userAgent": "...",
  "deviceType": "mobile",
  "os": "Android",
  "browser": "Chrome",
  "loggedInAt": "2026-08-24T09:00:00.000Z",
  "active": true,
  "current": false
}

active: bu girişin oturumu hâlâ açık mı (iptal edilmemiş, süresi geçmemiş bir yenileme belirteci var mı). current: isteği yapan oturum.

DELETE /api/auth/sessions/:id tek bir oturumu uzaktan kapatır.

Parola istemez — logout-alldan farklı olarak bu işlem yıkıcı değil, yanlışlıkla kapatılan cihaz yeniden giriş yapar. Şüpheli bir oturumu görür görmez, şifre hatırlamadan kapatabilmek daha değerli.

200{ "success": true, "kapatilan": 1 } · 400 current_session (kendi oturumunuz — çıkış için /logout kullanın) · 404 açık oturum yok.

404, "başkasının kaydı" ile "zaten kapalı" durumlarını ayırmaz; ayırmak, başka bir hesabın oturum kimliğini doğrulamaya yarardı.

Canlı oturum olayları (SSE)

"Tüm cihazlardan çıkış" gibi bir işlem, açık duran diğer istemcileri anında düşürmeli. EventSource Authorization başlığı gönderemediği için adrese giden dar kapsamlı bir belirteç kullanılır.

POST /api/auth/canli-anahtar (oturum gerektirir) → { "token": "..." } — anahtar 5 dakika ömürlüdür; akış koptuğunda yeniden bağlanmadan önce yeni anahtar alın.

GET /api/auth/canli/:tokentext/event-stream.

OlayGövdeAnlamı
revoked{}Oturum topluca geçersiz kılındı. Akış kapanır; yerel oturumu kapatın.
dosya{ islem }Dosyalarda değişiklik oldu (başka bir sekme veya cihazdan). Açık listeleri tazeleyin.
paylasim{ ad, indirmeSayisi, kalanHak }Paylaşım bağlantılarınızdan biri indirildi. kalanHak sınırsızsa null.
kota{ kullanilanYuzde, kullanilanBytes, toplamBytes }Depolamanın %90'ı veya fazlası dolu.
talep{ talepId, konu }Destek talebinize yanıt geldi.
plan{ durum: "bitiyor" | "dusuruldu", kalanGun? }Plan süresi hakkında bilgi.
event: paylasim
data: {"ad":"rapor.pdf","indirmeSayisi":3,"kalanHak":2}

revoked dışındaki olaylar bağlantıyı kapatmaz; akış devam eder.

Yayın best effort: olaylar saklanmaz, kuyruklanmaz, tekrar gönderilmez. Akış kapalıyken olan biteni bir sonraki açılışta normal sorgularla öğrenin — hiçbir olay tek doğruluk kaynağı değildir.

Bağlantı 20 saniyede bir yorum satırıyla canlı tutulur. Hesap başına en fazla 5 eşzamanlı akış açık kalabilir; altıncı bağlantı açılınca en eskisi kapatılır.


2Dosyalar

Oturum gerektirir. Yollar kullanıcıya göreli, / ile başlar. .., ters eğik çizgi ve null bayt reddedilir.

Yazma işlemleri doğrulanmış e-posta gerektirir. Klasör oluşturma, yeniden adlandırma, taşıma, kopyalama, favorileme, silme, çöp kutusu işlemleri, sürüm geri yükleme ve yüklemenin tamamı doğrulanmamış hesapta 400 email_not_verified döner. Listeleme, arama, indirme, önizleme ve kota sorgulama serbesttir — doğrulamayı bekleyen kullanıcı kilitli kalmaz.

İstemcide bu kodu tek bir yerde yakalayıp doğrulama ekranına yönlendirin; kullanıcıya işlem bazında ayrı mesaj göstermeye gerek yok.

GET/api/files?path=/

200{ "path": "/", "entries": [ ... ] }

{
  "name": "belge.pdf",
  "path": "/belge.pdf",
  "isFolder": false,
  "sizeBytes": 12345,
  "mimeType": "application/pdf",
  "modifiedAt": "2026-07-31T10:00:00.000Z",
  "etag": "...",
  "fileId": "142857",
  "favorite": false
}

fileId yol değişse bile sabittir; sürüm geçmişi bu kimlikle sorgulanır.

GET/api/files/degisenler

Son sorgudan bu yana ne değişti? Elinde tam bir kopya tutan istemciler (mobil uygulama, masaüstü senkronizasyon ajanı) içindir; tüm ağacı yeniden listelemek büyük hesaplarda pahalıdır ve silinenleri hiç göstermez.

ParametreAçıklama
pathHangi klasörün altı. Varsayılan /.
tokenÖnceki yanıttan gelen imleç. Verilmezse tüm ağaç döner.
limitSayfa başına en fazla öğe (1–5000).
{
  "path": "/",
  "syncToken": "http://sabre.io/ns/sync/1234",
  "degisenler": [ /* FileEntry */ ],
  "silinenler": ["/Belgeler/eski.pdf"],
  "tamYenilemeGerekli": false
}

Akış:

  1. İmleçsiz çağrı → tüm ağaç + bir syncToken.
  2. Sonraki çağrılar token ile → yalnızca değişenler ve silinenler.
  3. tamYenilemeGerekli: true → imleç eskimiş (Nextcloud yeniden indekslenmiş olabilir). Yereldeki kopyayı atıp baştan listeleyin; yanıttaki yeni syncToken geçerlidir, ondan devam edebilirsiniz.

Altında RFC 6578 sync-collection var, yani doğruluk kaynağı depolamanın kendisi: bu API'nin dışından yapılan bir değişiklik de yakalanır.

GET/api/files/ara?q=fatura

Tüm depolamada ada göre arama (alt klasörler dahil). q en az 2, en fazla 120 karakter. 200{ "entries": [ ... ] } — girdiler listelemeyle aynı biçimde.

GET/api/files/quota

{ "usedBytes": 0, "totalBytes": 5368709120, "freeBytes": 5368709120, "usedPercent": 0 }

POST/api/files/folder

{ "parent": "/", "name": "Yeni Klasör" }201 { "path": "/Yeni Klasör" }

Ad içinde \ / : * ? " < > | ve kontrol karakterleri kullanılamaz.

GET/api/files/download?path=/dosya.jpg

Dosya içeriği. Range desteklenir — duraklat/devam ve video akışı için kullanın. Yanıt Content-Disposition: attachment taşır.

Klasör indirmek (zip) için bölüm 4'teki önizleme belirtecini indir=1 ile kullanın; bu uç yalnızca dosya akıtır.

POST/api/files/rename · /move · /copy

{ "path": "/eski.txt", "name": "yeni.txt" }
{ "from": "/dosya.txt", "toDir": "/Klasor", "overwrite": false }

Üçü de 200 { "path": "/yeni-yol" } döner. overwrite yalnızca /move ucunda vardır. Bir klasörü kendi içine taşımak/kopyalamak reddedilir (invalid_move, invalid_copy).

Taşıma ve yeniden adlandırmada o dosyanın paylaşım bağlantıları yeni yola taşınır; bağlantılar kırılmaz.

DELETE/api/files

{ "paths": ["/a.txt", "/b.txt"] }

Tek istekte en fazla 200 yol.

200{ "deleted": 2, "results": [{ "path": "/a.txt", "deleted": true }, ...] }

Her dosya için ayrı sonuç döner; başarısız olanda error alanı bulunur. Silme kalıcı değildir, çöp kutusuna gider. Silinen dosyanın paylaşım bağlantıları kaldırılır.

Çöp kutusu

Açıklama
GET /api/files/trash{ entries: [{ id, name, originalPath, deletedAt, sizeBytes, isFolder }] }
POST /api/files/trash/restore{ id }{ restored: true }
DELETE /api/files/trash{ id } tek kayıt, {} tümü — geri alınamaz

id opak bir tanımlayıcıdır, yol değildir. Saklama süresi 30 gün.

Favoriler

Açıklama
GET /api/files/favoriler{ entries: [ ... ] } — listelemeyle aynı biçim
POST /api/files/favori{ path, favorite: true | false }{ success: true }

Sürüm geçmişi

GET /api/files/surumler?fileId=142857

{ "versions": [{ "id": "1692000000", "sizeBytes": 12345, "createdAt": "2026-08-14T..." }] }

POST /api/files/surumler/geri-yukle{ fileId, versionId }{ success: true }

Geri yükleme mevcut içeriği de bir sürüm olarak saklar, yani geri alınabilir.


3Yükleme

Yükleme de doğrulanmış e-posta gerektirir — kural bütün yazma işlemleri için geçerli, ayrıntısı bölüm 2'nin başında.

Ayrı bir dosya boyutu sınırı yoktur. Tek sınır kullanıcının kotasıdır; kota dolduğunda 413 quota_exceeded döner.

Virüs tarayıcı kontrolü. Yükleme başlatma, tek dosya yükleme ve parçalı yüklemeyi tamamlama uçları, tarayıcı ayakta değilse 503 scanner_unavailable döner. Bu geçici bir durumdur, istek aynen tekrar edilebilir; kullanıcıya "birkaç dakika sonra tekrar deneyin" deyin. Tamamlama reddedilse bile parçalar silinmez: yarım kalan oturum 48 saat durur, tarayıcı toparlandığında aynı uploadId ile tamamlanabilir.

Küçük dosyalar — POST /api/files/upload?dir=/&overwrite=false

multipart/form-data, alan adı file. Akış halinde aktarılır, sunucu belleğine alınmaz.

Tek istekte pratik sınır ~100 MB'dır. Ters vekil gövdeyi 128 MB'da kesiyor (MAX_REQUEST_MB) ve Cloudflare zaten ~100 MB üstünü kendisi reddediyor. Uygulamanın kendi politika sınırı (MAX_UPLOAD_MB) çok daha yüksek ama taşıma katmanı önce devreye girer.

Pratikte: 64 MB'ın üstündeki her dosya için parçalı yüklemeyi kullanın. Web arayüzü de tam bunu yapıyor. Parçalı yüklemede toplam boyut sınırı yoktur, yalnızca kota geçerlidir.

201{ "path": "/dosya.jpg", "name": "dosya.jpg" } 400 already_existsoverwrite=true göndermediyseniz. 400 no_filefile alanı yoksa.

Büyük dosyalar — parçalı yükleme

Bağlantı koptuğunda baştan başlamamak için büyük dosyalarda bunu kullanın. Önerilen parça boyutu 64 MB; tek parça en fazla 512 MB olabilir.

1. Oturum açPOST /api/files/upload/baslat

{ "dir": "/", "name": "video.mp4", "uploadId": "istemci-uretir-8-64-karakter" }

uploadId istemci tarafından üretilir, [A-Za-z0-9_-]{8,64} olmalıdır. Dosyanın ad/boyut/tarih bilgisinden türetin: aynı dosya için aynı kimlik üretilirse yarım kalan yükleme kaldığı yerden devam eder.

201{ "uploadId": "...", "path": "/video.mp4" }

2. Durumu sorGET /api/files/upload/:uploadId/durum?parca=67108864&toplam=3221225472

{ "chunks": [0, 1, 2], "eksik": [3] }

parca (parça boyutu) ve toplam (dosya boyutu) verilmelidir. İkisi verildiğinde chunks yalnızca tam yazılmış parçaları içerir, eksik ise yarım kalanları. Bu iki parametre olmadan eski davranış geçerlidir — parçanın var olması yeterli sayılır — ve yarım kalmış bir parça "yüklenmiş" sanılıp atlanır; sonuç, ortasından bayt eksik, sessizce bozuk bir dosyadır. Üretimde tam olarak bu yaşandı.

eksik listesindeki indeksleri de yeniden gönderin.

3. Parça gönderPUT /api/files/upload/:uploadId/:chunkIndex

Gövde ham baytlar, Content-Type: application/octet-stream. chunkIndex sıfırdan başlar. 204 döner.

İsteğe bağlı ama şiddetle önerilir: parçanın SHA-256 özetini gönderin.

X-Parca-Ozeti: <64 karakter hex>

Sunucu yazdığı baytların özetini hesaplar; tutmazsa parçayı siler ve 409 chunk_corrupt döner. Bu kod yeniden denenebilir sayılmalıdır. Başlık gönderilmezse doğrulama yapılmaz (crypto.subtle bulunmayan ortamlar için).

4. TamamlaPOST /api/files/upload/:uploadId/tamamla

{ "dir": "/", "name": "video.mp4", "overwrite": false }

201{ "path": "/video.mp4", "name": "video.mp4" } 400 already_exists · 503 scanner_unavailable

İptalDELETE /api/files/upload/:uploadId (204), yarım parçaları siler.


4Önizleme ve küçük resim

<img> ve <video> etiketleri Authorization başlığı gönderemez. Bunun için kısa ömürlü, dar kapsamlı belirteçler alınır.

Tek dosya önizlemesi

POST /api/files/onizleme-anahtari{ "path": "/foto.jpg" }200 { "token": "..." }. Ömrü 10 dakika, yalnızca o yola bağlıdır.

GET /api/onizleme/:token — oturum gerektirmez. Dosyayı akıtır, Range destekler. Adresi doğrudan <img src> / <video src> içinde kullanın.

Gömülü gösterim yalnızca image/*, video/*, audio/* ve application/pdf türlerine açıktır (Content-Disposition: inline); listede olmayan her tür attachment olarak iner. HTML yükleyip site adına script çalıştırmayı kapatan bilinçli bir sınır — gevşetilmesini beklemeyin.

GET /api/onizleme/:token?indir=1 — aynı belirteçle indirme. Hedef bir klasörse zip olarak akıtılır (application/zip). <a download> de Authorization gönderemediği için indirme akışı bu yol üzerinden kurulur.

Klasör küçük resimleri

POST /api/files/kucukresim-anahtari{ "dir": "/Fotograflar" }200 { "token": "..." }. Ömrü 10 dakika. Belirteç dosyaya değil klasöre bağlıdır: 50 resimli bir klasör için 50 ayrı anahtar almanız gerekmez.

GET /api/kucukresim/:token?ad=foto.jpg&boyut=256

128/256 kare kırpar (ızgara için), 1024/1920 oranı korur (açılan görüntü için). Büyük fotoğrafta kazanç büyük: 4000×3000 bir görselde orijinal 3539 KB, 1920 px önizleme 95 KB. Tam çözünürlük gerekmedikçe bu ucu kullanın.

Yanıt image/*, cache-control: private, max-age=600.


5Paylaşım bağlantıları

POST/api/shares (oturum gerektirir)

{ "path": "/foto.jpg", "password": "enaz8karakter", "expiresInDays": 7, "maxDownloads": 10 }

Klasör paylaşımında bir alan daha: "uploadAllowed": true. Bağlantıyı açan kişi klasöre dosya bırakabilir hâle gelir (aşağıda "Klasöre dosya bırakma").

Plan kuralları sunucuda zorlanır:

ÜcretsizÜcretli
Süre7 gün (zorunlu)seçilebilir, null = süresiz
Parolayok — 400 plan_requiredvar, en az 8 karakter
İndirme limitiyok — 400 plan_requiredvar

Klasör de paylaşılabilir (aşağıda "Klasör paylaşımı"). Kök klasör paylaşılamaz, var olmayan yol 404. uploadAllowed tek dosya paylaşımında 400 not_a_folder döner — bırakılacak bir yer yok.

Yükleme izni plan gerektirmez: ücretli bir özellik değil, klasörün ne işe yaradığını belirleyen bir ayar; bırakılan dosya zaten paylaşımı açan hesabın kotasından yer kaplar.

201{ "share": { "id", "token", "name", "isFolder", "expiresAt", "maxDownloads", "downloadCount", "uploadAllowed", ... } }

Paylaşım adresi: https://cloudutcu.com/s/<token>

Açıklama
GET /api/shareskendi bağlantıları (parola hash'i dönmez, hasPassword döner)
DELETE /api/shares/:idiptal — 204

Herkese açık uçlar (oturum gerekmez)

GET /api/s/:token{ name, isFolder, hasPassword, expiresAt, zipVar, uploadAllowed } Dosyanın yolu hiçbir zaman dışarı verilmez.

POST /api/s/:token/anahtar — gövde { "password": "..." } (parolalıysa). 200{ "token": "...", "name": "..." } — bu anahtarla /api/onizleme/:token üzerinden sayfada gösterebilirsiniz. İndirme sayacını artırmaz.

Ne gösterildiği dosya türüne ve paylaşımın indirme sınırına bağlı:

TürmaxDownloads yokmaxDownloads var
Resim (jpg, png, webp, avif, bmp, tif, heic)en fazla 1920 px küçültülmüş kopya; çizilemezse orijinalen fazla 1920 px küçültülmüş kopya
Video, ses, PDF, GIF, SVGdosyanın kendisi akıtılır404 preview_disabled

Sebep: önizleme sayacı artırmıyor. Orijinal dosya önizlemeden de gelebilseydi maxDownloads hiçbir şey sınırlamazdı — bağlantıyı açan herkes sayaç hiç artmadan dosyanın tamamını alabilirdi. Ölçek belirtecin içine yazılıyor, yani istemci onu kaldırıp orijinali isteyemez.

İndirme iki adımdır. Tek adımlı POST, <a download> POST atamadığı için istemciyi dosyanın tamamını belleğe toplamaya zorluyordu; parola gövdede gittiği için de GET'e çevrilemiyordu.

POST /api/s/:token/indirme-anahtari — gövde { "password": "..." } (parolalıysa). 200{ "token": "...", "name": "..." } — 5 dakika ömürlü. Sayacı artırmaz.

#### Klasör paylaşımı

isFolder: true olan bağlantıda içerik gezilebilir.

POST /api/s/:token/liste — gövde { "password": "...", "altYol": "/alt/klasor" } (ikisi de isteğe bağlı). 200:

{
  "name": "Rapor",
  "altYol": "/alt/klasor",
  "entries": [{ "name": "ozet.pdf", "path": "/alt/klasor/ozet.pdf", "isFolder": false,
                "sizeBytes": 1024, "mimeType": "application/pdf", "modifiedAt": "..." }]
}

Dönen yollar paylaşım köküne göre görelidir; sahibinin gerçek klasör düzeni dışarı verilmez. altYol olarak da bu göreli yolu geri gönderin. Kökün dışına çıkan bir yol 400 invalid_path döner. Listelemek sayacı artırmaz.

Klasörden indirme, aynı indirme-anahtari ucundan iki şekilde:

GövdeSonuç
{ "altYol": "/alt/ozet.pdf" }O tek dosya. Sayacı 1 artırır.
{ "zip": true }Klasörün tamamı tek arşiv. Sayacı 1 artırır.

zip yalnızca indirme sınırı olmayan paylaşımlarda çalışır (400 zip_disabled) — tek istek bütün içeriği taşıdığı için sınırlı bir bağlantıda "3 indirme", içeriğin tamamını üç kez vermek anlamına gelirdi. zipVar alanı bunu önceden söyler.

Dosya paylaşımına altYol veya zip gönderilirse 400 not_a_folder; klasör paylaşımında ikisi de yoksa 400 missing_path.

Klasör bağlantılarında önizleme, küçük resim ve video uçları 404 döner.

#### Klasöre dosya bırakma

uploadAllowed: true olan klasör bağlantısında, bağlantıyı açan kişi klasöre dosya ekleyebilir. İndirme gibi bu da iki adımdır: parola bir POST gövdesinde doğrulanır, dosya ayrı bir istekte akar.

POST /api/s/:token/yukleme-anahtari — gövde { "password": "...", "altYol": "/alt/klasor" } (ikisi de isteğe bağlı; altYol verilmezse kök). 200{ "token": "..." }15 dakika ömürlü. Hedef klasör belirtecin içine imzalanır, yani ikinci adımda başka bir yola çevrilemez.

POST /api/s/yukle/:anahtarmultipart/form-data, tek file alanı. 201{ "name": "ozet.pdf" } — dosyanın kaydedildiği ad.

Kurallar:

İzinsiz bir paylaşımda her iki uç da 400 upload_not_allowed döner. Hız sınırı: anahtar için saatte 30, yükleme için saatte 20 istek (IP başına).

GET /api/s/indir/:anahtar — dosyayı attachment olarak akıtır ve indirme sayacını artırır. Süre ve maxDownloads burada tekrar denetlenir, yani anahtarı alıp bekleyen biri süresi dolmuş bir bağlantıyı indiremez.

Parolasız paylaşımlarda iki uç daha var; ikisi de sayacı artırmaz ve parolalı bağlantıda 404 döner (parolanın koruduğu şeyi önizlemeden sızdırmamak için):

Açıklama
GET /api/s/:token/kucukresim1024 px önizleme görseli — kart/paylaşım görseli için
GET /api/s/:token/videovideoyu Range destekli akıtır — WhatsApp/Discord oynatıcısı buradan çeker. maxDownloads konmuş paylaşımda 404 (ham baytları sayaçsız verdiği için)

Süresi dolmuş, silinmiş veya limiti dolmuş bağlantı 404 döner. Yanlış parola 401 invalid_password. Bir paylaşımda 15 dakika içinde 10 hatalı parola denenirse o paylaşım geçici olarak kilitlenir (429) — bu sayaç IP'ye değil paylaşıma bağlıdır.


6Planlar ve ödeme

GET/api/orders/plans

{
  "plans": [{ "id": "standart", "name": "Standart", "storageGb": 500, "monthlyPrice": 89, "featured": true }],
  "periods": [{ "months": 1, "label": "Aylık", "discount": 0 }, { "months": 12, "label": "Yıllık", "discount": 0.2 }]
}

Güncel katalog (fiyatlar aylık, ₺):

idAdDepolamaAylık
freeÜcretsiz5 GB0
baslangicBaşlangıç100 GB39
standartStandart500 GB89
plusPlus1 TB149
proPro2 TB249

discount kesirdir (0.2 = %20). Toplam: round(monthlyPrice × months × (1 − discount))

Fiyatı istemcide hesaplayıp göndermeyin — sunucu kendi kataloğundan faturalandırır, gönderilen tutar dikkate alınmaz. Katalog burası üzerinden okunmalı; sabit kodlanan fiyat, gösterilen ile tahsil edilen tutarın ayrılması demektir.

POST/api/orders/checkout

{ "planId": "standart", "months": 12 }{ "action": "https://...", "fields": { ... } }

403 account_frozen — dondurulmuş hesap ödeme başlatamaz.

Yanıt imzalı form alanlarıdır (JSON), sayfa değil. İstemci bu alanlarla bir POST isteği kurup tarayıcıyı/WebView'i action adresine göndermelidir — alanların hiçbiri değiştirilmemeli, aksi halde imza doğrulanmaz ve ödeme reddedilir. Uçtaki değerleri kaçışlamaya (HTML escape) çalışmayın; fields içindeki metin ne ise imza onun üzerinden hesaplandı.

Ödeme tamamlandığında sunucu, sağlayıcıdan gelen imzalı bildirimle siparişi etkinleştirir; uygulamanın bir şey yapması gerekmez, GET /api/auth/me ile yeni kotayı okumak yeterlidir.

Bildirimi karşılayan uç POST /api/orders/callback. Oturum istemez ama çağırmayın: gövdedeki HMAC imzası doğrulanmadan hiçbir sipariş etkinleştirilmez, imzasız istek 400 invalid_signature döner. Tarayıcı ödeme sonrası buraya düştüğünde uç, işini bitirip 303 ile /orders sayfasına yönlendirir. Tekrarlanan bildirim güvenlidir: zaten paid olan sipariş ikinci kez işlenmez, yani planın süresi iki katına çıkmaz.

Sipariş sorgulama

Açıklama
GET /api/orderskullanıcının son 100 siparişi
GET /api/orders/:orderNumbertek sipariş — başkasınınki 404

7Destek talepleri

Açıklama
GET /api/ticketsliste (son 100)
POST /api/tickets{ subject, message, priority }low | normal | high201
GET /api/tickets/:id{ ticket, replies }
POST /api/tickets/:id/replies{ message }201 { reply }
POST /api/tickets/:id/closekapatır

subject 3–200, message 10–5000 karakter (yanıtta 1–5000). Kapatılmış talebe yanıt yazmak 403 ticket_closed döner. Başkasının talebine erişim reddedilir.


8Genel uçlar (oturum gerekmez)

Açıklama
GET /api/public/settings{ settings: { maintenance, duyuru } } — bakım modu ve duyuru
GET /api/public/stats{ totalUsers, totalRatings, averageRating, allocatedStorageBytes }
GET /api/public/testimonialsonaylanmış son 24 yorum
POST /api/public/contact{ name, email, subject, message }
POST /api/public/basvurubayilik/yetkili başvurusu — ayırıcı alan type: bayi | yetkili
GET /health{ status: "ok", time } — veritabanı erişimini de sınar

POST /api/public/basvuru içindeki website alanı http veya https ile başlamalıdır. javascript: ve data: adresleri reddedilir: değer yönetim panelinde tıklanabilir bir bağlantı olarak çıkıyor ve uç kimlik doğrulaması istemiyor.

POST /api/public/testimonials (oturum gerektirir) — { content, rating }, content 10–1000 karakter, rating 1–5. Yorum pending durumunda kaydedilir; moderasyondan geçmeden yayınlanmaz.

Yönetim uçları /api/admin/* altındadır ve admin/moderator rolü ister; bu dokümanın kapsamı dışında. İki not: rol her istekte veritabanından okunur (belirtecin içindekine güvenilmez) ve dondurulmuş bir personel hesabı 403 account_frozen alır. PUT /api/admin/settings/:key gövdesinde value alanı zorunludur — alan gönderilmezse 400; null geçerli bir değerdir.


9Hız sınırları

Genel sınır IP başına dakikada 300 istek. Aşağıdaki uçlarda ek sınır var.

Anahtar sütunu önemli. IP dışındaki anahtarlar, paylaşılan bir çıkış IP'sinin (ev NAT'i, kurum ağı, mobil operatör havuzu) arkasındaki kullanıcıların birbirinin kotasını tüketmesini engeller:

Bir uçta iki sınır varsa ikisi de işler: hangisi önce dolarsa 429 o verir.

SınırAnahtar
register15 dakikada 5IP
login15 dakikada 10IP
login15 dakikada 20e-posta
login/2fa15 dakikada 10hesap
2fa/* (kurulum, açma, kapatma, kodlar)15 dakikada 5hesap
forgot-password15 dakikada 5IP
forgot-passwordsaatte 5e-posta
reset-password · verify-emailgenel sınırIP
resend-verification15 dakikada 3IP
change-password15 dakikada 5hesap
logout-all15 dakikada 5hesap
hesabi-sil15 dakikada 5hesap
POST /api/orders/checkout5 dakikada 10hesap
/api/files/* (tümü)dakikada 240hesap
/api/files/aradakikada 60IP
/api/files/degisenlerdakikada 60IP
yükleme tamamlama, sürüm geri yükleme, silme, çöp boşaltmadakikada 60hesap
GET /api/onizleme/:tokendakikada 300belirteç sahibi
klasör zip indirme (?indir=1)5 dakikada 20belirteç sahibi
GET /api/kucukresim/:tokendakikada 600belirteç sahibi
/api/tickets/* (tümü)dakikada 60hesap
POST /api/ticketssaatte 10IP
POST /api/tickets/:id/replies10 dakikada 20hesap
POST /api/s/:token/anahtarsaatte 60IP
POST /api/s/:token/listesaatte 120IP
POST /api/s/:token/indirme-anahtarisaatte 30IP
GET /api/s/indir/:anahtarsaatte 60IP
POST /api/public/basvurusaatte 3IP
POST /api/public/contactsaatte 5IP
POST /api/public/testimonials24 saatte 3IP

Parolalı paylaşımlarda tablodaki IP sınırlarının üstüne bir de paylaşım başına başarısız deneme kilidi biner (ayrıntı bölüm 5). Dağıtık bir ağdan gelen parola denemesini IP sınırı tek başına göremediği için var.

Aşıldığında 429. Kullanıcıya bekleme mesajı gösterin, sessizce yeniden denemeyin.

Tek istisna parçalı yükleme: orada 429 ve 408, 409 ile aynı kutuda — geçici sayılıp artan beklemeyle (1s, 2s, 4s… en fazla 15s, 5 deneme) yeniden gönderilir. Gerekçe, saatlerdir süren bir yüklemenin tek bir geçici yanıt yüzünden ölmemesi; sayaç bütün /api/files/* uçlarıyla paylaşıldığı için yükleme sırasında başka bir sekmede gezinmek bu sınıra değebilir.

Uygulama sınırlarının önünde ayrıca ters vekilde (nginx) bir sınır var: /api/ için saniyede 20 istek (200'lük ani yığına izin verir), şifre kabul eden uçlarda saniyede 1, IP başına 50 eşzamanlı bağlantı. Buraya çarpan istek Node sürecine hiç ulaşmaz ve gövdesiz bir 429 döner.


10Boyut sınırları

NeSınır
JSON gövde1 MB
Tek istekte dosya yükleme~100 MB (nginx 128 MB, Cloudflare ~100 MB)
Tek parça (PUT .../:chunkIndex)etkin ~100 MB (uygulama 512 MB kabul eder, ters vekil 128 MB'da keser)
Parçalı yüklemede toplam boyutsınırsız — yalnızca kota
Toplu silmede yol sayısı200
Dosya/klasör adı255 karakter
Yol1024 karakter

11İstemci tarafında dikkat edilecekler


12Hata kodları

KodHTTPAnlamı
no_session401refresh çerezi yok
invalid_credentials401e-posta/şifre hatalı
invalid_token401önizleme/doğrulama belirteci geçersiz veya süresi dolmuş
invalid_password401paylaşım parolası hatalı
preview_disabled404indirme sınırlı paylaşımda çizilemeyen türün önizlemesi kapalı
wrong_password400mevcut şifre hatalı (şifre değiştirme, 2FA)
invalid_totp401/400doğrulama kodu hatalı
totp_expired4012. adım belirteci süresi doldu — baştan giriş
totp_not_started400etkinleştirmeden önce kurulum çağrılmadı
totp_already_enabled409iki adımlı doğrulama zaten açık
totp_not_enabled400iki adımlı doğrulama kapalı
current_session400kendi oturumunuzu bu uçtan kapatamazsınız
email_not_verified400yazma işlemi için e-posta doğrulanmalı (bölüm 2)
email_taken409bu e-posta kayıtlı
account_frozen403hesap donduruldu — giriş, yenileme, depolama, ödeme ve yönetim uçları kapalı
forbidden403bu kayda erişim yok
ticket_closed403kapatılmış talebe yanıt
invalid_path400geçersiz yol (.., kök, ters eğik çizgi)
invalid_name400ad yasak karakter içeriyor
already_exists400aynı isimde dosya var (overwrite gönderin)
invalid_move / invalid_copy400klasörü kendi içine taşıma/kopyalama
not_a_folder400klasör bekleyen bir alan dosya paylaşımına gönderildi (altYol, zip, uploadAllowed)
upload_not_allowed400bu paylaşıma dosya bırakma izni yok
too_many_duplicates400aynı adın 20 kopyası zaten var — dosyayı yeniden adlandırın
plan_required400ücretli plan özelliği
invalid_api_key401uygulama belirteci tanınmıyor
api_key_expired401uygulama belirtecinin süresi dolmuş
api_key_not_allowed403bu uç uygulama belirtecine kapalı (bölüm 1)
insufficient_scope403belirtecin bu işlem için yetkisi yok
no_scopes / invalid_scope400belirteç oluştururken yetki verilmedi / bilinmeyen yetki
too_many_keys400hesap başına 20 belirteç sınırı
invalid_url / invalid_url_scheme400webhook adresi geçersiz / https değil
private_address400webhook adresi iç ağa bakıyor
no_events / invalid_event400webhook için olay seçilmedi / bilinmeyen olay
too_many_webhooks400hesap başına 10 abonelik sınırı
push_disabled503bildirim özelliği bu sunucuda kapalı (VAPID anahtarı yok)
no_file400multipart gövdede file alanı yok
file_too_large400sunucu yükleme sınırı aşıldı
chunk_corrupt409parça özeti tutmadı — yeniden gönderin
quota_exceeded413depolama kotası doldu
rate_limited429hız sınırı
scanner_unavailable503virüs tarayıcı hazır değil — biraz sonra tekrar deneyin
storage_unreachable502depolama sunucusuna ulaşılamıyor

Listede olmayan bir kod gelirse message alanını gösterin; kod adına göre dal kurmayın.