uVersion
Türkçe
İndir →

Wiki

REST API

uVersion sunucusunun HTTP uç noktalarının tam referansı: auth, repos, files, locks, comments, watchlist, modification requests, builds, admin.

uVersion sunucusu, JWT ile kimlik doğrulaması yapılan bir JSON HTTP API sunar. Bu sayfa, masaüstü istemcisi, editör eklentileri ve uversion CLI tarafından kullanılan tüm uç noktaları belgeler. Bunları doğrudan çağırarak uVersion'ı dahili araçlarınıza (özel dashboard, denetim betikleri, webhook'lar vb.) entegre edebilirsiniz.

Kurallar

Temel URL

Belgelenen tüm yollar, örneğinizin URL'sine göre görecelidir. Örnekler https://uversion.mygamestudio.com kullanır. Kendi URL'nizle değiştirin.

Gerekli başlıklar

BaşlıkDeğer
Authorization/api/auth/* ve /api/server-info (ve /health) hariç tüm /api/* rotalarında Bearer <jwt>
Content-TypeJSON body içeren POST/PUT için application/json. İkili yüklemeler (build files) için application/octet-stream.
Acceptapplication/json önerilir (sunucu varsayılan olarak JSON döndürür)

Tek biçimli yanıt formatı

Tüm rotalar aşağıdaki zarfla yanıt verir:

{
  "success": true,
  "data": { /* payload */ }
}

Hata durumunda:

{
  "success": false,
  "error": "Permission denied: capability 'manage_users' required"
}

success alanı her zaman bulunur ve isteğin başarılı olup olmadığını belirtir. Başarı durumunda data alanı bulunur. Başarısızlık durumunda error alanı bulunur. Asla ikisi birlikte bulunmaz.

Sayfalama

Potansiyel olarak uzun listeler döndüren rotalar, query param olarak limit ve offset kabul eder (?limit=20&offset=40). Yanıt, yinelemeyi kolaylaştırmak için total ve has_more içerir. Maksimum limit: 100.

Hız sınırlama

Genel hız sınırlama kaldırıldı (CLAUDE.md, Security bölümüne bakın). Yalnızca /api/auth/login hız sınırlamasına tabidir: her username için 15 dakikada 5 başarısız deneme. Geçerli denemeler sayılmaz.

Token sürümleme

Her JWT, DB'deki users.token_version ile eşleşen bir tv alanı (token version) içerir. Auth ara katmanı bu değeri her istekte kontrol eder. Kullanıcı POST /api/auth/logout yaptığında, bir yönetici şifresini sıfırladığında veya bir yönetici hesabını devre dışı bıraktığında, token_version artırılır ve o kullanıcının tüm makinelerindeki mevcut tüm token'lar anında geçersiz kılınır.

Curl

API'yi bir terminalden çağırmak için:

TOKEN=$(curl -s -X POST https://uversion.mygamestudio.com/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username":"alice","password":"secret"}' | jq -r '.data.token')

curl -H "Authorization: Bearer $TOKEN" \
  https://uversion.mygamestudio.com/api/repositories

Kimlik doğrulama

POST /api/auth/login

Bir kullanıcıyı kimlik doğrulaması yapar ve 30 günlük bir JWT döndürür.

Body:

{
  "username": "alice",
  "password": "secret"
}

Response 200:

{
  "success": true,
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIs...",
    "expires_at": "2026-06-13T14:30:00Z",
    "user": {
      "id": 12,
      "username": "alice",
      "email": "alice@mygamestudio.com",
      "role": "lead",
      "is_active": true
    }
  }
}

Hatalar:

  • 401: geçersiz kimlik bilgileri veya devre dışı kullanıcı
  • 429: bu username için 15 dakikalık pencerede 5 başarısız denemeye ulaşıldı

Sunucu, zamanlama saldırılarını etkisiz hale getirmek için her zaman argon2id::verify_password çalıştırır (kullanıcı yoksa sahte bir hash'e karşı). Yanıt, kullanıcı var olsa da olmasa da aynı süreyi alır.

POST /api/auth/refresh

Şifreyi yeniden girmeden JWT'yi yeniler.

Başlıklar: Authorization: Bearer <current_token>. Body yok.

Response 200: /login ile aynı, süresi 30 gün ileri atılmış ve yeni bir token içerir.

Hatalar:

  • 401: mevcut token geçersiz, süresi dolmuş veya token_version uyuşmazlığı

POST /api/auth/logout

users.token_version'ı artırarak geçerli kullanıcının tüm token'larını (tüm makinelerinde) geçersiz kılar. Kullanıcının her yerde yeniden oturum açması gerekir.

Response 200: { "success": true }.

POST /api/auth/validate

Token'ın hâlâ geçerli olup olmadığını kontrol eder. Süresinin dolmasına 7 günden az kalan token'lar için, sunucu yanıta bir refreshed_token ekler (otomatik uzatma). İstemci, eskisinin yerine bunu kalıcı hale getirmelidir.

Response 200:

{
  "success": true,
  "data": {
    "valid": true,
    "user_id": 12,
    "expires_at": "2026-06-13T14:30:00Z",
    "refreshed_token": "eyJhbGciOiJIUzI1NiIs..."
  }
}

POST /api/auth/register

Bir kullanıcı hesabı oluşturur (genel rota, kimlik doğrulaması olmadan).

POST /api/auth/change-password

Geçerli kullanıcının şifresini değiştirir. token_version'ı artırır, bu da tüm eski token'ları geçersiz kılar.

Depolar

GET /api/repositories

Geçerli kullanıcının erişebildiği depoları listeler (izinler tablosu üzerinden filtrelenir). Bir depoda hiçbir izin desenine sahip olmayan bir kullanıcı onu görmez.

Query param: limit, offset.

Response 200:

{
  "success": true,
  "data": [
    {
      "id": 1,
      "name": "hero-rpg",
      "owner": "acme",
      "description": "Main RPG project",
      "current_revision": "7f3a9b1c2d...",
      "file_count": 8432,
      "size_bytes": 14211938405,
      "created_at": "2026-01-15T10:00:00Z"
    },
    {
      "id": 2,
      "name": "shared-assets",
      "owner": "acme",
      "description": "Shared asset library",
      "current_revision": "3a4b5c6d...",
      "file_count": 412,
      "size_bytes": 980000000,
      "created_at": "2026-02-01T09:00:00Z"
    }
  ]
}

GET /api/repositories/{repo_id}

Toplu istatistikler dahil, bir deponun ayrıntısı.

Response 200:

{
  "success": true,
  "data": {
    "id": 1,
    "name": "hero-rpg",
    "owner": "acme",
    "description": "Main RPG project",
    "current_revision": "7f3a9b1c2d...",
    "file_count": 8432,
    "size_bytes": 14211938405,
    "dedup_ratio": 4.2,
    "created_at": "2026-01-15T10:00:00Z",
    "last_commit_at": "2026-05-15T08:30:00Z"
  }
}

Hatalar:

  • 403: bu depoya erişim yok
  • 404: depo mevcut değil

POST /api/repositories

Yeni bir depo oluşturur. create_repos capability gerekir (varsayılan olarak admin).

Body:

{
  "name": "new-project",
  "description": "Optional description"
}

Doğrulama:

  • name: 1 ila 64 karakter, alfasayısal + tireler + alt çizgiler. owner başına benzersiz.
  • description: 0 ila 1024 karakter. İsteğe bağlı.

Hatalar:

  • 400: geçersiz veya çok uzun ad
  • 403: create_repos capability eksik
  • 409: bu owner için bu adda bir depo zaten var

Dosyalar

POST /api/files/{repo_id}/upload-chunks

Bir ikili chunk grubu yükler. Aynı chunk'lar (SHA-256'ya göre) otomatik olarak yinelenmeden kaldırılır. Sunucu, zaten mevcut olan bir chunk'ı yeniden depolamaz. Yanıt, her chunk için hash'ini + boyutunu + sıkıştırılmış boyutunu döndürür; bunlar bir sonraki POST /commit'te kullanılır.

Body:

{
  "chunks": [
    { "data": "<base64-encoded chunk bytes>" },
    { "data": "<base64-encoded chunk bytes>" }
  ]
}

Response 200:

{
  "success": true,
  "data": {
    "chunks": [
      { "hash": "abc123...", "size": 1048576, "compressed_size": 423152 },
      { "hash": "def456...", "size": 2097152, "compressed_size": 891204 }
    ]
  }
}

Sınırlar: body maks. 1 GB (security.max_body_size_files ile yapılandırılabilir). Daha büyük dosyalar için birden çok gruba bölün.

POST /api/files/{repo_id}/commit

Bir dosya listesi ve chunk'larıyla atomik bir commit oluşturur. Ya tüm dosyalar geçer ya da hiçbiri.

Body:

{
  "message": "Updated main level + hero pose pass",
  "files": [
    {
      "path": "Content/Maps/MainLevel.umap",
      "action": "modified",
      "chunks": ["abc123...", "def456..."]
    },
    {
      "path": "Content/Characters/NewVillain.uasset",
      "action": "added",
      "chunks": ["fed789..."]
    },
    {
      "path": "Content/OldAsset.uasset",
      "action": "deleted"
    }
  ]
}

Olası eylemler: added, modified, deleted. added ve modified için chunks dizisi, /upload-chunks tarafından döndürülen hash'leri içerir. deleted için chunks'ı atlayın.

Response 200:

{
  "success": true,
  "data": {
    "commit_hash": "7f3a9b1c2d3e4f...",
    "files_changed": 3,
    "bytes_uploaded": 88080384,
    "bytes_deduped": 4194304,
    "revision": 47
  }
}

Hatalar:

  • 400: boş mesaj, eylemsiz dosya, var olmayan chunk'lara referans
  • 403: checkin capability yok veya dosyalardan birinde write izni yok
  • 409: değiştirilen bir dosyada kilit zaten başka bir kullanıcı tarafından tutuluyor veya eşzamanlı commit (aynı dosyada race condition)

GET /api/files/{repo_id}/snapshot

Deponun geçerli revizyondaki tam durumunu döndürür: tüm dosyalar, revizyonları ve chunk'ları. İstemci tarafından clone ve zorunlu sync işlemleri için kullanılır.

Query param:

  • revision (isteğe bağlı): geçmiş bir revizyondaki snapshot. Varsayılan: HEAD.

Response 200:

{
  "success": true,
  "data": {
    "revision": 47,
    "files": [
      {
        "path": "Content/Maps/MainLevel.umap",
        "revision": 12,
        "size_bytes": 84934656,
        "chunks": ["abc123...", "def456..."]
      }
    ]
  }
}

GET /api/files/{repo_id}/content

Belirli bir revizyondaki bir dosyanın içeriğini indirir (sunucu chunk'ları yeniden birleştirir). clone ve sync tarafından kullanılır.

Query param:

  • path: dosya yolu (depo köküne göre görece)
  • revision (isteğe bağlı): revizyon numarası. Varsayılan: en son.

Response 200: dosyanın ikili içeriği.

GET /api/files/{repo_id}/history

Deponun commit'lerinin sayfalanmış geçmişi.

Query param:

  • limit (1 ila 100, varsayılan 20)
  • offset (varsayılan 0)
  • path (isteğe bağlı): dosya yoluna göre filtrele (bu dosyayı değiştiren commit'ler)
  • author (isteğe bağlı): username'e göre filtrele
  • since (isteğe bağlı): ISO 8601 timestamp

Response 200:

{
  "success": true,
  "data": {
    "commits": [
      {
        "hash": "7f3a9b1c...",
        "author": "alice",
        "author_id": 12,
        "date": "2026-05-15T08:30:00Z",
        "message": "Fixed lighting in main level",
        "files_changed": 1,
        "bytes_uploaded": 84934656
      }
    ],
    "total": 423,
    "limit": 20,
    "offset": 0,
    "has_more": true
  }
}

Artımlı sync

Masaüstü istemcisinin verimli şekilde senkronize etmek için kullandığı uç noktalar:

  • GET /api/files/{repo_id}/sync: bir revizyondan bu yana değişen dosyalar, delta sync için.
  • GET /api/files/{repo_id}/deletions: sunucu tarafında silinen dosyalar, silmeleri yerele yaymak için.
  • GET /api/files/{repo_id}/list: deponun dosya listesi.
  • POST /api/files/{repo_id}/checkout: kilitleri edinir ve düzenlemeyi hazırlar.

Kilitler

POST /api/locks/{repo_id}/acquire

Bir yol listesi üzerinde kilitler edinir. Edinmeler bağımsızdır: acquired listesi başarıları, failed listesi ise başarısızlıkları nedenleriyle birlikte içerir.

Body:

{
  "paths": [
    "Content/Maps/MainLevel.umap",
    "Content/Characters/Hero.uasset"
  ]
}

Response 200:

{
  "success": true,
  "data": {
    "acquired": [
      {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "file_id": 12345,
        "file_path": "Content/Maps/MainLevel.umap",
        "user_id": 12,
        "username": "alice",
        "acquired_at": "2026-05-15T14:30:00Z",
        "last_heartbeat_at": "2026-05-15T14:30:00Z",
        "expires_at": "2026-05-15T15:30:00Z"
      }
    ],
    "failed": [
      {
        "path": "Content/Characters/Hero.uasset",
        "reason": "ALREADY_LOCKED",
        "lock_holder": "bob",
        "lock_acquired_at": "2026-05-15T13:00:00Z"
      }
    ]
  }
}

Kilitler, heartbeat olmadan 60 dakika sonra sona erer. expires_at alanı bu son tarihi yansıtır. Kilidi yenilemek için düzenli olarak /heartbeat'i, serbest bırakmak için /release'i çağırın.

failed nedenleri:

  • ALREADY_LOCKED: başka bir kullanıcı kilidi tutuyor (lock_holder ve lock_acquired_at alanları doldurulur)
  • PERMISSION_DENIED: bu yolda write izni yok
  • INVALID_PATH: bozuk yol (mutlak, .. içeriyor vb.)

POST /api/locks/{repo_id}/release

Sahip olduğunuz kilitleri serbest bırakır. Body:

{
  "paths": ["Content/Maps/MainLevel.umap"],
  "force": false
}

force: true, force_unlock capability gerektirir. Eylem denetlenir.

POST /api/locks/{repo_id}/heartbeat

Kilitlerinizde last_heartbeat_at'i günceller. Yöneticilerin etkinliği görmesini isteyen uzun süre çalışan CI işleri için her 5 dakikada bir önerilir.

GET /api/locks/{repo_id}/status

Deponun tüm aktif kilitlerini listeler; adları doğrudan döndürmek için users ve files üzerinde join yapar.

Query param: user (username'e göre filtrele), limit, offset.

Response 200:

{
  "success": true,
  "data": {
    "locks": [
      {
        "file_path": "Content/Maps/MainLevel.umap",
        "user_id": 12,
        "username": "alice",
        "acquired_at": "2026-05-15T14:30:00Z",
        "last_heartbeat_at": "2026-05-15T16:00:00Z"
      }
    ],
    "total": 1
  }
}

Yorumlar ve incelemeler

GET /api/comments/{repo_id}/comments?commit_hash=<hash>

Bir commit'in yorumlarını iş parçacığı halinde (ebeveyn → çocuklar) listeler.

Response 200:

{
  "success": true,
  "data": [
    {
      "id": 42,
      "commit_hash": "7f3a9b1c...",
      "file_path": "Content/Maps/MainLevel.umap",
      "author_id": 12,
      "author_username": "alice",
      "body": "LGTM, ship it",
      "parent_id": null,
      "created_at": "2026-05-15T15:00:00Z",
      "replies": [
        {
          "id": 43,
          "author_username": "bob",
          "body": "Thanks!",
          "parent_id": 42,
          "created_at": "2026-05-15T15:05:00Z"
        }
      ]
    }
  ]
}

POST /api/comments/{repo_id}/comments

Bir yorum oluşturur. file_path isteğe bağlıdır (commit yorumu vs. dosya yorumu). Mevcut bir iş parçacığına yanıt vermek için parent_id.

Body:

{
  "commit_hash": "7f3a9b1c...",
  "file_path": "Content/Maps/MainLevel.umap",
  "body": "LGTM, ship it",
  "parent_id": null
}

POST /api/comments/{repo_id}/reviews

Bir commit üzerine bir inceleme gönderir. approve_changes capability gerekir.

Body:

{
  "commit_hash": "7f3a9b1c...",
  "status": "approved",
  "comment": "Lighting looks great, approving"
}

Kabul edilen status: approved, changes_requested, pending.

İzleme listesi

GET /api/watchlist/{repo_id}/watchlist

Geçerli kullanıcının bu depodaki watch desenlerini listeler.

Response 200:

{
  "success": true,
  "data": [
    {
      "id": 1,
      "user_id": 12,
      "pattern": "Content/Characters/Hero/**",
      "notify_on": ["commit", "lock"],
      "created_at": "2026-04-10T10:00:00Z"
    }
  ]
}

POST /api/watchlist/{repo_id}/watchlist

Bir watch deseni ekler. Body:

{
  "pattern": "Content/Characters/Hero/**",
  "notify_on": ["commit", "lock"]
}

Olası olaylar: commit (bir commit eşleşen bir dosyayı değiştirdi), lock (bir kilit edinildi), review (bir inceleme gönderildi).

DELETE /api/watchlist/{repo_id}/watchlist/{watch_id}

Bir watch desenini kaldırır. { "success": true } döndürür.

Üretim panosu (görevler)

Eski modification-requests API'si kaldırıldı: üretim panosu onu içine alır (istekler kartlara dönüşür, origin='request'). Uç noktalar /api/tasks/{repo_id} altında iç içe yerleştirilmiştir.

RotaAçıklama
GET /api/tasks/{repo_id}/boardTam pano: sütunlar + kartlar
POST /api/tasks/{repo_id}/tasksBir kart oluşturur
PUT/DELETE /api/tasks/{repo_id}/tasks/{task_id}Bir kartı günceller / siler
PUT /api/tasks/{repo_id}/tasks/{task_id}/assigneesBir karta kullanıcılar atar
GET /api/tasks/{repo_id}/assignable-usersAtanabilir kullanıcıların listesi
POST /api/tasks/{repo_id}/columnsPanonun sütunlarını yapılandırır

Ayrıca mevcut alt rotalar: kart yorumları, assets ve commit'lere bağlantılar ve ekler (kapak resmiyle birlikte). Sütunların yapılandırılması manage_board capability (admin / lead) gerektirir.

Derlemeler

POST /api/builds/{repo_id}/upload?hash=<sha256>

Bir build dosyasını <storage_path>/builds/<hash>'e yükler. Sunucu, query param'da verilen SHA-256'yı alınan içeriğe göre doğrular. Hash sunucu tarafında zaten varsa, yeniden kopyalamadan hemen 200 döndürür (build storage tarafında dedup).

Başlıklar: Content-Type: application/octet-stream.

Body: ham ikili (JSON sarmalama yok).

Sınırlar: dosya başına 8 GB.

Hatalar:

  • 400: hash query param eksik veya bozuk, ya da hesaplanan SHA-256 != verilen hash
  • 413: dosya > 8 GB

POST /api/builds/{repo_id}/publish

Tüm dosyaları yüklendikten sonra bir build'in manifest'ini kaydeder. publish_builds capability gerekir.

Body:

{
  "version": "0.1.5-nightly",
  "config": "Development",
  "platform": "Win64",
  "executable_path": "HeroRPG/Binaries/Win64/HeroRPG.exe",
  "release_notes": "Nightly build of main branch, 2026-05-15",
  "files": [
    { "path": "HeroRPG.exe",                "hash": "abc123...", "size_bytes": 12345678 },
    { "path": "HeroRPG/Content/Paks/pak0.pak", "hash": "def456...", "size_bytes": 2147483648 }
  ]
}

GET /api/builds/{repo_id}

Yayımlanan build'leri listeler. İndirme bağlantılarını görmek için download_builds capability gerekir.

Response 200:

{
  "success": true,
  "data": [
    {
      "id": 5,
      "version": "0.1.5-nightly",
      "config": "Development",
      "platform": "Win64",
      "published_by": "ci-nightly",
      "published_at": "2026-05-15T03:00:00Z",
      "size_bytes": 2159829326,
      "file_count": 142,
      "release_notes": "Nightly build of main branch, 2026-05-15"
    }
  ]
}

GET /api/builds/{repo_id}/{build_id}/file

Bir build'den bir dosya indirir. download_builds capability gerekir. Bir build'in manifest'i GET /api/builds/{repo_id}/{build_id}/manifest üzerinden kullanılabilir.

Yönetim

Tüm /api/admin/* rotaları, kullanıcının en az bir admin capability'sine sahip olmasını gerektirir (uç noktaya göre: manage_users, manage_permissions, manage_rules vb.). Aşağıda özlü belgeler var. Çoğu, standart REST desenini (GET/POST/PUT/DELETE) izler.

RotaCapabilityAçıklama
GET/POST /api/admin/usersmanage_usersKullanıcıları listeler / oluşturur
PUT/DELETE /api/admin/users/{id}manage_usersGünceller / siler
POST /api/admin/users/{id}/reset-passwordmanage_usersŞifreyi sıfırlar, token_version'ı artırır
GET/POST /api/admin/groupsmanage_usersGrup yönetimi
GET/POST /api/admin/permissions/{repo_id}manage_permissionsYola göre glob izin kuralları
GET/POST /api/admin/repositories/{repo_id}/rulesmanage_rulesCheckin öncesi doğrulama kuralları
GET/POST /api/admin/repositories/{repo_id}/webhooksmanage_rulesDiscord / Slack / Teams / custom
GET /api/admin/auditview_all_activityFiltrelenmiş ve sayfalanmış audit log
GET /api/admin/statsview_all_activityStorage metrics, dedup ratio, büyüme
GET /api/admin/repositories/{repo_id}/gc/previewadminÇalıştırmadan GC önizlemesi
POST /api/admin/repositories/{repo_id}/gcadminGarbage collection'ı başlatır
POST /api/admin/locks/{id}/force-releaseforce_unlockÜçüncü tarafa ait bir kilidi zorla açar, denetlenir

Sağlık

GET /health

Sunucu veritabanına erişebiliyorsa 200 OK döndüren kimlik doğrulaması gerektirmeyen uç nokta. Yük dengeleyici veya izleme sağlık kontrolleri için kullanılır (Prometheus blackbox, Datadog synthetic vb.).

Response 200: OK (text/plain).

Response 503: veritabanına ulaşılamıyorsa.

GET /api/server-info

Sunucu meta verilerini (sürüm vb.) döndüren genel, kimlik doğrulaması gerektirmeyen uç nokta. /health gibi, auth ara katmanı tarafından korunmaz.

Hata biçimi

Hata durumunda yanıt, uygun bir HTTP status ile { "success": false, "error": "..." }'dir. error alanı, insan tarafından okunabilir bir mesajdır. Kararlı, makine tarafından okunabilir kodlara ihtiyaç duyan istemciler için, öneki ayrıştırın (ör.: "Permission denied: ..." her zaman "Permission denied" ile başlar).

HTTPAnlamıNe zaman
400Bad requestGeçersiz parametre, bozuk JSON, çok büyük body (sabit 413 sınırından önce)
401Not authenticatedToken yok, süresi dolmuş, imza geçersiz, ya da token_version uyuşmazlığı
403Permission deniedEksik capability, ya da yol / depo üzerinde izin yok
404Resource not foundDepo / dosya / commit / kullanıcı mevcut değil veya erişilemez
409ConflictKilit zaten tutuluyor, eşzamanlı commit, benzersiz kısıtlama ihlali
413Payload too largeBody sınırın ötesinde (/files'te 1 GB, /builds/upload'da 8 GB)
429Too many requestsYalnızca /auth/login'de (kullanıcı başına hız sınırlama)
500Internal server errorDB hatası, IO hatası. Sunucu tarafında loglanır; hatayı bildirirseniz timestamp ekleyin.
503Service unavailableVeritabanına ulaşılamıyor (health check) veya migrasyon sürüyor