{"openapi":"3.1.0","info":{"title":"Derslik API","version":"1.0.0","description":"Ders odalarını kendi sisteminizden (rezervasyon, okul yönetimi, ödeme akışı) yönetmek için REST API.\n\nTüm istekler `Authorization: Bearer <API anahtarı>` başlığı ister. Anahtarları yönetim panelindeki **API** sekmesinden oluşturun. Anahtarlar sunucudan sunucuya kullanım içindir; tarayıcıya ya da mobil uygulamaya koymayın.\n\nHatalar her zaman `{ \"error\": { \"code\", \"message\", \"field\"? } }` biçimindedir. Anahtar başına dakikada 300 istek sınırı vardır (`x-ratelimit-remaining` başlığı kalan hakkı gösterir).\n\n**Sitenize gömme:** `teacherUrl` / `studentUrl` adresine `embed=1` (ve isterseniz `name=`) ekleyip iframe içinde açın; iframe `allow=\"camera; microphone; display-capture; fullscreen; autoplay; screen-wake-lock; clipboard-write; web-share\"` izinlerini vermelidir. Ders ekranı üst sayfaya `postMessage` ile `{ source: \"derslik\", type }` olayları gönderir: `ready`, `waiting`, `joined`, `left`, `ended`. Üst sayfa `{ type: \"leave\" }` göndererek dersten çıkarabilir; `{ type: \"share-url\", url }` ile ders ekranındaki \"Ders bağlantısını paylaş\" düğmesinin göstereceği adresi kendi sayfasına çevirebilir (adres üst sayfayla aynı kökende olmalıdır)."},"tags":[{"name":"Odalar","description":"Ders odası oluşturma, listeleme, güncelleme ve silme. Her odanın kalıcı bir hoca ve öğrenci bağlantısı vardır."},{"name":"Canlı ders","description":"Süren dersin katılımcıları; birini çıkarma ya da dersi bitirme."},{"name":"Notalar","description":"Derste açılacak PDF notalar. Hoca dersteyken bunlardan birini açıp sayfa çevirir."},{"name":"Hesap","description":"Anahtar doğrulama."}],"security":[{"apiKey":[]}],"paths":{"/me":{"get":{"tags":["Hesap"],"operationId":"getMe","summary":"Anahtarı doğrula","description":"Kullanılan API anahtarının adını döndürür. Entegrasyonu kurarken bağlantıyı denemek için kullanın.","responses":{"200":{"description":"Anahtar geçerli","content":{"application/json":{"example":{"key":{"id":"key_Xy12Ab34","name":"Rezervasyon sistemi","prefix":"dk_9fK2pQ"}}}}},"401":{"description":"Anahtar yok ya da geçersiz","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/rooms":{"get":{"tags":["Odalar"],"operationId":"listRooms","summary":"Odaları listele","description":"En yeni oda önce gelir. Her odanın canlı durumu (`live`) da döner.","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"description":"Sayfa boyutu"},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"default":0},"description":"Atlanacak oda sayısı"}],"responses":{"200":{"description":"Oda listesi","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Room"}},"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"}}},"example":{"data":[{"id":"aB3dE9xY","title":"Piyano · Ayşe ile Salı dersi","waitingRoom":true,"metadata":{"bookingId":"R-1042","teacher":"ayse.hoca"},"teacherUrl":"https://derslik.example/r/aB3dE9xY?t=Qm9yZWFsaXM0Mjc4Lk1fdGVzdA","studentUrl":"https://derslik.example/r/aB3dE9xY","sheetCount":0,"createdAt":"2026-10-13T09:30:00.000Z","live":{"active":false,"participants":0,"teacherPresent":false,"startedAt":null}}],"total":1,"limit":50,"offset":0}}}}}},"post":{"tags":["Odalar"],"operationId":"createRoom","summary":"Oda oluştur","description":"Yeni bir ders odası açar. Dönen `teacherUrl` hocaya, `studentUrl` öğrenciye gönderilir; bağlantılar oda silinene kadar geçerlidir.\n\nİpucu: öğrenci bağlantısının sonuna `?name=Ayşe%20Yılmaz` eklerseniz öğrencinin adı hazır doldurulur.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoomInput"},"example":{"title":"Piyano · Ayşe ile Salı dersi","waitingRoom":true,"metadata":{"bookingId":"R-1042"}}}}},"responses":{"201":{"description":"Oda oluşturuldu","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Room"},"example":{"id":"aB3dE9xY","title":"Piyano · Ayşe ile Salı dersi","waitingRoom":true,"metadata":{"bookingId":"R-1042","teacher":"ayse.hoca"},"teacherUrl":"https://derslik.example/r/aB3dE9xY?t=Qm9yZWFsaXM0Mjc4Lk1fdGVzdA","studentUrl":"https://derslik.example/r/aB3dE9xY","sheetCount":0,"createdAt":"2026-10-13T09:30:00.000Z","live":{"active":false,"participants":0,"teacherPresent":false,"startedAt":null}}}}},"400":{"description":"Geçersiz alan","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/rooms/{id}":{"parameters":[{"name":"id","in":"path","required":true,"description":"Oda kimliği","schema":{"type":"string"},"example":"aB3dE9xY"}],"get":{"tags":["Odalar"],"operationId":"getRoom","summary":"Odayı getir","description":"Oda bilgisi, bağlantılar ve canlı durum. Dersin başlayıp başlamadığını öğrenmek için `live.active` ve `live.teacherPresent` alanlarına bakın.","responses":{"200":{"description":"Oda","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Room"},"example":{"id":"aB3dE9xY","title":"Piyano · Ayşe ile Salı dersi","waitingRoom":true,"metadata":{"bookingId":"R-1042","teacher":"ayse.hoca"},"teacherUrl":"https://derslik.example/r/aB3dE9xY?t=Qm9yZWFsaXM0Mjc4Lk1fdGVzdA","studentUrl":"https://derslik.example/r/aB3dE9xY","sheetCount":0,"createdAt":"2026-10-13T09:30:00.000Z","live":{"active":true,"participants":2,"teacherPresent":true,"startedAt":"2026-10-13T10:00:12.000Z"}}}}},"404":{"description":"Oda yok","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"tags":["Odalar"],"operationId":"updateRoom","summary":"Odayı güncelle","description":"Yalnızca gönderdiğiniz alanlar değişir. `metadata` gönderilirse tamamen değiştirilir (birleştirilmez); silmek için `null` gönderin. Bekleme odası kapatılırsa sırada bekleyenler içeri alınır.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoomInput"},"example":{"title":"Piyano · Perşembe","waitingRoom":false}}}},"responses":{"200":{"description":"Güncel oda","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Room"}}}},"400":{"description":"Geçersiz alan","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Oda yok","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Odalar"],"operationId":"deleteRoom","summary":"Odayı sil","description":"Oda, bağlantıları ve yüklenen notalar kalıcı olarak silinir. Ders sürüyorsa herkesin bağlantısı kesilir.","responses":{"204":{"description":"Silindi"},"404":{"description":"Oda yok","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/rooms/{id}/end":{"parameters":[{"name":"id","in":"path","required":true,"description":"Oda kimliği","schema":{"type":"string"},"example":"aB3dE9xY"}],"post":{"tags":["Canlı ders"],"operationId":"endLesson","summary":"Dersi bitir","description":"Süren dersteki herkesin bağlantısını keser. Oda ve bağlantılar kalır; aynı bağlantılarla sonra yeni ders yapılabilir. Öğrenciler bir sonraki girişte yine bekleme odasından geçer.","responses":{"200":{"description":"Sonuç","content":{"application/json":{"example":{"ended":true}}}},"404":{"description":"Oda yok","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/rooms/{id}/teacher-link":{"parameters":[{"name":"id","in":"path","required":true,"description":"Oda kimliği","schema":{"type":"string"},"example":"aB3dE9xY"}],"post":{"tags":["Odalar"],"operationId":"rotateTeacherLink","summary":"Hoca bağlantısını yenile","description":"Yeni bir `teacherUrl` üretir; eskisi hemen geçersiz olur. Hoca bağlantısı yanlış kişiye gittiyse kullanın. Öğrenci bağlantısı değişmez.","responses":{"200":{"description":"Yeni bağlantılı oda","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Room"}}}},"404":{"description":"Oda yok","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/rooms/{id}/participants":{"parameters":[{"name":"id","in":"path","required":true,"description":"Oda kimliği","schema":{"type":"string"},"example":"aB3dE9xY"}],"get":{"tags":["Canlı ders"],"operationId":"listParticipants","summary":"Katılımcıları listele","description":"Şu an derste olanlar ve bekleme odasında hocanın onayını bekleyenler.","responses":{"200":{"description":"Katılımcılar","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Participant"}},"waiting":{"type":"array","items":{"$ref":"#/components/schemas/Waiting"}}}},"example":{"data":[{"identity":"t_Hq81kd02","name":"Ayşe Hoca","role":"teacher","joinedAt":"2026-10-13T10:00:12.000Z","microphone":true,"cameras":2,"screenShare":false},{"identity":"s_P0q7Lm3z","name":"Deniz","role":"student","joinedAt":"2026-10-13T10:01:40.000Z","microphone":true,"cameras":1,"screenShare":false}],"waiting":[{"name":"Ece","since":"2026-10-13T10:05:03.000Z"}]}}}},"404":{"description":"Oda yok","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/rooms/{id}/participants/{identity}":{"parameters":[{"name":"id","in":"path","required":true,"description":"Oda kimliği","schema":{"type":"string"},"example":"aB3dE9xY"},{"name":"identity","in":"path","required":true,"schema":{"type":"string"},"description":"Katılımcı listesindeki `identity`","example":"s_P0q7Lm3z"}],"delete":{"tags":["Canlı ders"],"operationId":"removeParticipant","summary":"Katılımcıyı dersten çıkar","description":"Kişinin bağlantısı kesilir. Öğrenci tekrar girmek isterse yeniden hocanın onayını bekler.","responses":{"204":{"description":"Çıkarıldı"},"404":{"description":"Oda yok ya da kişi derste değil","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/rooms/{id}/sheets":{"parameters":[{"name":"id","in":"path","required":true,"description":"Oda kimliği","schema":{"type":"string"},"example":"aB3dE9xY"}],"get":{"tags":["Notalar"],"operationId":"listSheets","summary":"Notaları listele","responses":{"200":{"description":"Notalar","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Sheet"}}}}}}},"404":{"description":"Oda yok","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Notalar"],"operationId":"uploadSheet","summary":"Nota yükle (PDF)","description":"PDF dosyasını gövdede ham olarak gönderin (`Content-Type: application/pdf`, en fazla 40 MB, oda başına 50 nota). Notanın adı için `name` parametresini kullanın.","parameters":[{"name":"name","in":"query","schema":{"type":"string","maxLength":80},"description":"Notanın görünen adı","example":"Czerny Op. 599 No. 12"}],"requestBody":{"required":true,"content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"responses":{"201":{"description":"Yüklendi","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Sheet"}}}},"400":{"description":"PDF değil ya da sınır aşıldı","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Dosya 40 MB'tan büyük","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Content-Type yanlış","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/rooms/{id}/sheets/{sheetId}":{"parameters":[{"name":"id","in":"path","required":true,"description":"Oda kimliği","schema":{"type":"string"},"example":"aB3dE9xY"},{"name":"sheetId","in":"path","required":true,"schema":{"type":"string"}}],"delete":{"tags":["Notalar"],"operationId":"deleteSheet","summary":"Notayı sil","description":"Nota ve üzerindeki çizimler silinir. Derste açıksa ekrandan kalkar.","responses":{"204":{"description":"Silindi"},"404":{"description":"Oda ya da nota yok","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","bearerFormat":"dk_…","description":"Yönetim paneli → API sekmesinden oluşturulan anahtar"}},"schemas":{"RoomInput":{"type":"object","additionalProperties":false,"properties":{"title":{"type":"string","minLength":1,"maxLength":80,"description":"Odanın adı; hoca ve öğrenci ekranında görünür. Verilmezse \"Ders Odası\"."},"waitingRoom":{"type":"boolean","default":true,"description":"Açıksa öğrenciler hocanın onayıyla girer."},"metadata":{"type":["object","null"],"additionalProperties":{"type":"string","maxLength":500},"maxProperties":20,"description":"Kendi kayıtlarınızı bağlamak için serbest anahtar/değer (ör. rezervasyon no). Anahtarlar en fazla 40 karakter: harf, rakam, `_ . -`."}}},"Room":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"waitingRoom":{"type":"boolean"},"metadata":{"type":"object","additionalProperties":{"type":"string"}},"teacherUrl":{"type":"string","format":"uri","description":"Hoca bağlantısı. Gizli tutun: bu bağlantıyla giren herkes hoca yetkisi alır."},"studentUrl":{"type":"string","format":"uri","description":"Öğrenci bağlantısı"},"sheetCount":{"type":"integer"},"createdAt":{"type":"string","format":"date-time"},"live":{"type":"object","properties":{"active":{"type":"boolean","description":"Derste en az bir kişi var"},"participants":{"type":"integer"},"teacherPresent":{"type":"boolean","description":"Hoca şu an derste"},"startedAt":{"type":["string","null"],"format":"date-time"}}}}},"Participant":{"type":"object","properties":{"identity":{"type":"string","description":"Tarayıcı başına sabit kimlik; aynı kişi yeniden bağlanınca değişmez"},"name":{"type":"string"},"role":{"type":"string","enum":["teacher","student"]},"joinedAt":{"type":"string","format":"date-time"},"microphone":{"type":"boolean","description":"Mikrofonu açık"},"cameras":{"type":"integer","description":"Açık kamera sayısı (ek kameralar dahil)"},"screenShare":{"type":"boolean"},"device":{"type":"string","enum":["computer","phone"],"description":"`phone`: kişinin eşleştirdiği piyano kamerası (kimliği sahibinin kimliğine `.tel` eklenmiş hâlidir)"}}},"Waiting":{"type":"object","properties":{"name":{"type":"string"},"since":{"type":"string","format":"date-time"}}},"Sheet":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"size":{"type":"integer","description":"Bayt"},"createdAt":{"type":"string","format":"date-time"},"url":{"type":"string","format":"uri","description":"PDF dosyası"}}},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized","not_found","validation_error","invalid_json","rate_limited","payload_too_large","unsupported_media_type","internal_error"]},"message":{"type":"string"},"field":{"type":"string","description":"Hatalı alan (varsa)"}}}},"example":{"error":{"code":"validation_error","message":"title 1-80 karakter olmalı","field":"title"}}}}},"servers":[{"url":"https://meeting.harmoniva.app/api/v1"}]}