Platform API Referansı
Achidemy platformundaki tüm API'lerin ne için ve nasıl kullanıldığı — REST endpoint'leri, istek/yanıt formatları, yetkilendirme ve örnekler.
Bu sayfa Achidemy platformunun kendi API dokümantasyonudur. Backend ve full-stack geliştiricilerin tüm API’leri ne için kullanacaklarını, hangi parametreleri göndereceklerini ve ne tür yanıt alacaklarını tek yerden görmesini sağlar. Her endpoint için amaç, yetkilendirme, istek formatı, yanıt ve örnek çağrı verilir.
Genel Bilgiler
Section titled “Genel Bilgiler”- Base URL: Uygulama kökü (yerelde
http://localhost:5173veyahttp://localhost:8787; production’dahttps://achidemy.net). API path’leri dil prefix’i içermez (/api/...). - Kimlik doğrulama: Çoğu endpoint session cookie (Better Auth) ile korunur. İstekte
Cookieheader’ı otomatik gönderilir;fetchile çağırırkencredentials: "include"kullanın. - Hata yanıtları: 400 (geçersiz istek), 401 (giriş gerekli), 403 (yetkisiz), 404 (bulunamadı), 500 (sunucu hatası). Gövde genelde
{ "error": "mesaj" }veya düz metin.
REST API’ler
Section titled “REST API’ler”1. GraphQL — Sorgu ve Mutation
Section titled “1. GraphQL — Sorgu ve Mutation”| Özellik | Değer |
|---|---|
| Path | POST /api/graphql (GET desteklenir; GraphiQL/playground) |
| Dosya | app/routes/api.graphql.ts |
| Amaç | Tüm veri okuma (courses, me, enrollments, certificates vb.) ve mutation’lar (createCourse, addToCart, toggleLessonCompletion vb.) GraphQL üzerinden yapılır. |
| Yetkilendirme | Session cookie; resolver içinde context.user ile rol ve yetki kontrolü. |
İstek (POST):
- Header:
Content-Type: application/json - Body:
{ "query": "string", "variables": { ... } } - Cookie: Session cookie (credentials: “include”)
Yanıt: 200 — { "data": { ... } } veya { "errors": [ { "message": "..." } ] }
Örnek:
curl -X POST "https://achidemy.net/api/graphql" \ -H "Content-Type: application/json" \ -d '{"query":"query { me { id email name role } }"}' \ --cookie "better-auth.session_token=..."Şema ve tipler: app/graphql/schema.ts — typeDefs + resolvers. Detay için API Referansı ve GraphQL sayfasına bakın.
2. Better Auth — Kimlik Doğrulama
Section titled “2. Better Auth — Kimlik Doğrulama”| Özellik | Değer |
|---|---|
| Path | /api/auth/* (tüm alt path’ler) |
| Dosya | app/routes/api.auth.ts → auth.handler(request) |
| Amaç | Giriş, kayıt, çıkış, OAuth (Google), e-posta doğrulama, şifre sıfırlama, session yönetimi. |
| Yetkilendirme | Public (giriş/kayıt); session gerektiren path’ler Better Auth tarafından yönetilir. |
Kullanım: Better Auth client (app/lib/auth-client.ts) ile signIn.email, signUp.email, signOut vb. çağrılır. Doğrudan REST çağrısı yerine SDK kullanılır. Path örnekleri: /api/auth/sign-in/email, /api/auth/sign-up/email, /api/auth/sign-out, /api/auth/callback/google. Detay: API Referansı ve GraphQL — Better Auth.
3. Stripe Webhook
Section titled “3. Stripe Webhook”| Özellik | Değer |
|---|---|
| Path | POST /api/stripe/webhook |
| Dosya | app/routes/api.stripe.webhook.ts |
| Amaç | Stripe’dan gelen olayları işlemek: ödeme tamamlandı (checkout.session.completed), abonelik, payment_intent vb. Enrollment oluşturma, earnings kaydı, e-posta bildirimi burada yapılır. |
| Yetkilendirme | Stripe-Signature header ile imza doğrulama; cookie/session yok. Sadece Stripe bu endpoint’e istek atar. |
İstek:
- Header:
Stripe-Signature: ...(Stripe tarafından eklenir) - Body: Raw (text); Stripe event JSON. Doğrulama için body olduğu gibi kullanılır.
Yanıt: 200 — başarı; 400 — imza hatası veya geçersiz body.
Not: Bu endpoint’i uygulama içinden çağırmazsınız; Stripe Dashboard’da webhook URL olarak tanımlanır. Yerelde test için stripe listen --forward-to localhost:8787/api/stripe/webhook kullanılır.
4. Stripe Connect Onboarding
Section titled “4. Stripe Connect Onboarding”| Özellik | Değer |
|---|---|
| Path | POST /api/stripe/connect-onboarding |
| Dosya | app/routes/api.stripe.connect-onboarding.ts |
| Amaç | Eğitmeni Stripe Connect Express hesabına yönlendirmek. Hesap yoksa oluşturulur; Account Link ile Stripe onboarding sayfasına redirect döner. |
| Yetkilendirme | Session gerekli; user.role === "instructor". Değilse 401/403. |
İstek: POST; body boş veya form. Session cookie gerekli.
Yanıt: 302 Redirect — Stripe Account Link URL’ine yönlendirme. Hata: 401 (giriş gerekli), 403 (sadece eğitmen), 500 (STRIPE_SECRET_KEY veya BASE_URL eksik).
Örnek (form submit):
<form action="/api/stripe/connect-onboarding" method="POST"> <button type="submit">Stripe Hesabını Bağla</button></form>5. Eğitmen Manuel Ödeme Bilgisi (TR)
Section titled “5. Eğitmen Manuel Ödeme Bilgisi (TR)”| Özellik | Değer |
|---|---|
| Path | POST /api/instructor/update-manual-payout |
| Dosya | app/routes/api.instructor.update-manual-payout.ts |
| Amaç | Türkiye’deki eğitmenin IBAN veya Payoneer bilgisini güncellemek. users.manualPayoutDetails ve users.payoutMethod = 'bank_transfer' yazılır. |
| Yetkilendirme | Session + user.role === "instructor". |
İstek:
- Method: POST
- Content-Type:
application/x-www-form-urlencodedveyamultipart/form-data - Body (FormData):
details(string) — IBAN veya Payoneer e-posta adresi.
Yanıt: 302 Redirect — Referer veya /tr/instructor/payouts. Hata: 401, 403 (sadece eğitmen), 404 (kullanıcı bulunamadı), 500.
Örnek:
curl -X POST "https://achidemy.net/api/instructor/update-manual-payout" \ -H "Cookie: better-auth.session_token=..." \ -F "details=TR00 0000 0000 0000 0000 0000 00"6. Ders Kaynağı Yükleme
Section titled “6. Ders Kaynağı Yükleme”| Özellik | Değer |
|---|---|
| Path | POST /api/lesson-resource-upload |
| Dosya | app/routes/api.lesson-resource-upload.ts |
| Amaç | Derse PDF vb. kaynak dosyası yüklemek; Bunny Storage’a yazılır. Yükleme sonrası dönen fileUrl ile lesson_resources tablosuna kayıt uygulama tarafında yapılabilir. |
| Yetkilendirme | Bu endpoint’te session kontrolü yok; çağıran sayfa (eğitmen müfredat sayfası) session ile korunur. İsteğe bağlı olarak action içinde eğitmen ve ders sahipliği kontrolü eklenebilir. |
İstek:
- Method: POST
- Content-Type:
multipart/form-data - Body (FormData):
lessonId(string) — Ders UUID.file(File) — Yüklenecek dosya.
Yanıt (başarı): 200 — { "title": "dosya.pdf", "fileUrl": "https://...", "fileSize": 12345, "fileType": "application/pdf" }
Hata: 400 (lessonId veya file eksik), 500 (Bunny ayarları eksik), 502 (Bunny yükleme hatası).
Ortam değişkenleri: BUNNY_STORAGE_ZONE, BUNNY_STORAGE_KEY, BUNNY_PULL_ZONE_URL.
6.1 Video Altyazısı Yükleme
Section titled “6.1 Video Altyazısı Yükleme”| Özellik | Değer |
|---|---|
| Path | POST /api/lesson/caption-upload |
| Dosya | app/routes/api.lesson.caption-upload.ts |
| Amaç | Ders videosuna .vtt altyazı yüklemek; Bunny Stream API’ye gönderilir ve lesson_captions tablosuna kayıt eklenir. |
| Yetkilendirme | Eğitmen panelinden çağrılır; action içinde session kontrolü yok (sayfa session ile korunur). |
İstek:
- Method: POST
- Content-Type:
multipart/form-data - Body (FormData):
lessonId(string) — Ders UUID.captionFile(File) — .vtt dosyası.langCode(string) — Dil kodu (örn.tr,en,de).label(string) — Görünen etiket (örn. Türkçe, English).
Yanıt (başarı): 200 — { "message": "Altyazı başarıyla yüklendi" }
Hata: 400 (eksik alan), 404 (video bulunamadı), 500 (Bunny/DB hatası veya env eksik). Tüm 500 yanıtları JSON: { "error": "..." }.
Ortam değişkenleri: BUNNY_LIBRARY_ID, BUNNY_API_KEY veya BUNNY_STREAM_API_KEY.
Detay: Video Altyazıları (Bunny Stream).
6.2 Video Altyazısı Silme
Section titled “6.2 Video Altyazısı Silme”| Özellik | Değer |
|---|---|
| Path | POST /api/lesson/caption-delete |
| Dosya | app/routes/api.lesson.caption-delete.ts |
| Amaç | Kayıtlı bir altyazıyı hem Bunny Stream’den hem lesson_captions tablosundan silmek. |
| Yetkilendirme | Eğitmen panelinden çağrılır; action içinde session kontrolü yok. |
İstek:
- Method: POST
- Content-Type:
multipart/form-dataveyaapplication/x-www-form-urlencoded - Body (FormData):
captionId(string) — lesson_captions kaydının UUID’si.
Yanıt (başarı): 200 — { "success": true }
Hata: 400 (captionId eksik), 404 (kayıt veya video bulunamadı), 500 (Bunny/DB veya env eksik).
Ortam değişkenleri: BUNNY_LIBRARY_ID, BUNNY_API_KEY veya BUNNY_STREAM_API_KEY.
6.3 Quiz Kaynağı Yükleme
Section titled “6.3 Quiz Kaynağı Yükleme”| Özellik | Değer |
|---|---|
| Path | POST /api/quiz-resource-upload |
| Dosya | app/routes/api.quiz-resource-upload.ts |
| Amaç | Quiz’e PDF vb. kaynak dosyası yüklemek; Bunny Storage’a yazılır. |
| Yetkilendirme | Eğitmen panelinden çağrılır; sayfa session ile korunur. |
İstek:
- Method: POST
- Content-Type:
multipart/form-data - Body (FormData):
quizId(string) — Quiz UUID.file(File) — Yüklenecek dosya.
Yanıt (başarı): 200 — { "title": "dosya.pdf", "fileUrl": "https://...", "fileSize": 12345, "fileType": "application/pdf" }
Hata: 400 (quizId veya file eksik), 500 (Bunny ayarları eksik).
6.4 Kod Egzersizi Kaynağı Yükleme
Section titled “6.4 Kod Egzersizi Kaynağı Yükleme”| Özellik | Değer |
|---|---|
| Path | POST /api/exercise-resource-upload |
| Dosya | app/routes/api.exercise-resource-upload.ts |
| Amaç | Coding exercise’e PDF vb. kaynak dosyası yüklemek; Bunny Storage’a yazılır. |
| Yetkilendirme | Eğitmen panelinden çağrılır; sayfa session ile korunur. |
İstek:
- Method: POST
- Content-Type:
multipart/form-data - Body (FormData):
exerciseId(string) — Coding exercise UUID.file(File) — Yüklenecek dosya.
Yanıt (başarı): 200 — { "title": "dosya.pdf", "fileUrl": "https://...", "fileSize": 12345, "fileType": "application/pdf" }
Hata: 400 (exerciseId veya file eksik), 500 (Bunny ayarları eksik).
6.5 Ders Videosu İçin Direct Upload Bileti (Bunny TUS)
Section titled “6.5 Ders Videosu İçin Direct Upload Bileti (Bunny TUS)”| Özellik | Değer |
|---|---|
| Path | POST /api/bunny/create-upload |
| Dosya | app/routes/api.bunny.create-upload.ts |
| Amaç | Bunny Stream üzerinde yeni bir video kaydı (placeholder) oluşturmak ve TUS (resumable upload) protokolü ile doğrudan CDN’e yükleme için gerekli imzalı bileti üretmek. Frontend, bu endpoint’ten dönen değerlerle tus-js-client aracılığıyla büyük boyutlu videoları (ör. 4K, 2GB) doğrudan Bunny’ye yükler. |
| Yetkilendirme | Sadece eğitmenler kullanabilir. Session gerekli; user.role === "instructor" kontrolü yapılır, değilse 401 Unauthorized döner. |
İstek:
- Method: POST
- Content-Type:
application/json - Body:
{ "title": "Ders Başlığı (opsiyonel)"}Yanıt (başarı): 200 —
{ "videoId": "bunny-guid", "libraryId": "605053", "signature": "hex-sha256-signature", "expirationTime": 1738060000}videoId: Bunny Stream tarafında oluşturulan video GUID’i (dersinbunnyVideoIdalanında saklanır).libraryId:BUNNY_LIBRARY_IDdeğeri.signature: TUS upload için Bunny’nin beklediği SHA-256 tabanlı imza (AuthorizationSignature).expirationTime: İmzanın geçerli olduğu Unix timestamp (saniye).
Hata:
401— Kullanıcı yok veya rolüinstructordeğil.500—BUNNY_LIBRARY_IDveyaBUNNY_STREAM_API_KEY/BUNNY_API_KEYeksik ya da Bunny video kaydı oluşturulamadı. Gövde her zaman JSON’dur:
{ "error": "Bunny.net yapılandırması eksik. Lütfen BUNNY_LIBRARY_ID ve BUNNY_STREAM_API_KEY (veya BUNNY_API_KEY) env değişkenlerini tanımlayın." }Ortam değişkenleri:
BUNNY_LIBRARY_IDBUNNY_STREAM_API_KEYveyaBUNNY_API_KEY(kodda fallback olarak okunur)
Kullanıldığı yer:
DirectVideoUploaderbileşeni (app/components/instructor/DirectVideoUploader.tsx), müfredat sayfasında (instructor.course.$slug.manage.curriculum.tsx) derse video yükleme akışında bu endpoint’i çağırır ve dönenvideoId,libraryId,signature,expirationTimedeğerleriyletus-js-clientüzerinden doğrudan Bunny TUS endpoint’ine upload yapar.
Not: Bu endpoint sadece bilet ve imza üretir; video binary verisi backend’e hiç uğramaz. Böylece Cloudflare Workers tarafında yük hafif tutulur, çok büyük videolar için bile ölçeklenebilir ve kesintiye dayanıklı bir upload deneyimi sağlanır.
7. Sohbet Görsel Yükleme
Section titled “7. Sohbet Görsel Yükleme”| Özellik | Değer |
|---|---|
| Path | POST /api/chat-image-upload |
| Dosya | app/routes/api.chat-image-upload.ts |
| Amaç | Mesajda gönderilecek görseli yüklemek; Bunny Storage chat-media/ altına yazılır. Dönen URL mesaj içinde kullanılır. |
| Yetkilendirme | Bu endpoint’te session kontrolü yok; mesaj sayfası session ile korunur. İsteğe bağlı action içinde session kontrolü eklenebilir. |
İstek:
- Method: POST
- Content-Type:
multipart/form-data - Body (FormData):
file(File) — Görsel; tipler:image/jpeg,image/png,image/gif,image/webp.
Yanıt (başarı): 200 — { "url": "https://pullzone.../chat-media/xxx.jpg" }
Hata: 400 (dosya yok veya tip uygun değil), 500 (Bunny ayarları eksik), 502 (yükleme hatası).
8. Sertifika PDF İndirme
Section titled “8. Sertifika PDF İndirme”| Özellik | Değer |
|---|---|
| Path | GET /api/certificate/:id/download veya GET /api/certificates/:id/download |
| Dosya | app/routes/api.certificate.$id.download.ts |
| Amaç | Kullanıcının sertifika kaydına ait PDF’i indirmek. Sertifika userId ile eşleşmeli. |
| Yetkilendirme | Session gerekli; sertifika sahibi (certificates.userId === session.user.id) olmalı. |
İstek: GET; path parametresi id — sertifika UUID.
Yanıt (başarı): 200 — Content-Type: application/pdf, Content-Disposition: attachment; filename="certificate-xxx.pdf". Gövde PDF stream.
Hata: 401 (giriş gerekli), 404 (sertifika bulunamadı veya yetkisiz), 500.
9. Fatura PDF İndirme
Section titled “9. Fatura PDF İndirme”| Özellik | Değer |
|---|---|
| Path | GET /api/invoice/:enrollmentId/download |
| Dosya | app/routes/api.invoice.$enrollmentId.download.ts |
| Amaç | Kullanıcının bir enrollment’ına ait fatura PDF’ini indirmek. Aynı checkout session’daki tüm kalemler tek faturada gösterilir. |
| Yetkilendirme | Session gerekli; enrollment sahibi (enrollments.userId === session.user.id) olmalı. |
İstek: GET; path parametresi enrollmentId — enrollment UUID.
Yanıt (başarı): 200 — Content-Type: application/pdf, Content-Disposition: attachment. Gövde PDF.
Hata: 400 (enrollmentId eksik), 401 (giriş gerekli), 404 (enrollment bulunamadı veya yetkisiz), 500.
10. Admin Aktivite Listesi
Section titled “10. Admin Aktivite Listesi”| Özellik | Değer |
|---|---|
| Path | GET /api/admin/activities |
| Dosya | app/routes/api.admin.activities.ts |
| Amaç | Admin “Tüm bildirimler” modalı için ödeme talepleri ve kurs onayları gibi aktiviteleri JSON olarak döndürmek (en fazla 500 kayıt). |
| Yetkilendirme | Session + user.role === "admin". |
İstek: GET; session cookie gerekli.
Yanıt (başarı): 200 — { "activities": [ { "id", "type", "title", "createdAt", ... } ] }
Hata: 401 (giriş gerekli), 403 (sadece admin), 500.
Örnek:
curl "https://achidemy.net/api/admin/activities" \ -H "Cookie: better-auth.session_token=..."11. Video İzlenme Telemetrisi (Heartbeat)
Section titled “11. Video İzlenme Telemetrisi (Heartbeat)”| Özellik | Değer |
|---|---|
| Path | POST /api/video-telemetry |
| Dosya | app/routes/api.video-telemetry.ts |
| Amaç | Video izlenme telemetrisini 15 saniyelik bloklar halinde kaydetmek. Sunucu watch_time_logs insert eder; daily_activities artırır; abonelik izlenmelerinde subscription_watch_logs artırır. |
| Yetkilendirme | Session zorunlu (auth.api.getSession). userId body’den alınmaz. |
Enterprise Anti‑Cheat (Payout Koruması):
- Self‑Watch Ban: Eğitmen kendi kursunu izlerse payout’a dahil edilmez (payout logları atlanır;
daily_activitiesyine güncellenir). - Human Daily Cap: Kullanıcı başına günlük maksimum “paid” süre 28.800 sn (8 saat).
- Lesson 3x Cap: Ay içinde aynı ders için maksimum “paid” süre
lessons.duration * 3.
İstek:
- Method: POST
- Content-Type:
application/json - Body:
{ "courseId": "uuid", "lessonId": "uuid", "durationSeconds": number, "timestamp"?: number }durationSeconds> 0 olmalı ve anti-cheat için tek istekte<= 25olmalıdır (pratikte15).
Yanıt (başarı): 200 — { "success": true }
Hata: 400 (Invalid payload — eksik/geçersiz alan), 401 (Unauthorized), 500.
Örnek:
curl -X POST "https://achidemy.net/api/video-telemetry" \ -H "Content-Type: application/json" \ -H "Cookie: better-auth.session_token=..." \ -d '{"courseId":"...","lessonId":"...","durationSeconds":15,"timestamp":1710000000000}'11.1 Legacy: Video İzleme İlerlemesi (Deprecated)
Section titled “11.1 Legacy: Video İzleme İlerlemesi (Deprecated)”| Özellik | Değer |
|---|---|
| Path | POST /api/update-progress |
| Dosya | app/routes/api.update-progress.ts |
| Durum | Deprecated (geriye dönük uyumluluk). Yeni akış için POST /api/video-telemetry kullanın. |
12. Kariyer CV PDF Yükleme (Bunny Storage)
Section titled “12. Kariyer CV PDF Yükleme (Bunny Storage)”| Özellik | Değer |
|---|---|
| Path | POST /api/career-cv-upload |
| Dosya | app/routes/api.career-cv-upload.ts |
| Amaç | Kariyer başvuru formunda CV PDF’i yüklemek; Bunny Storage’a yazıp url döndürmek. |
| Yetkilendirme | Session yok; public erişim (FormData: jobId, file). |
İstek:
- Method: POST
- Content-Type:
multipart/form-data - Body (FormData):
jobId(string) — ilan id’si (UUID)file(File) — sadeceapplication/pdf
Yanıt (başarı): 200 — { "url": "https://pullzone.../careers/job/.../cv.pdf" }
Hata: 400 (jobId/file/yetersiz format), 500 (Bunny config eksik), 502 (upload başarısız).
13. Admin Kariyer CV İndir (Admin-only proxy)
Section titled “13. Admin Kariyer CV İndir (Admin-only proxy)”| Özellik | Değer |
|---|---|
| Path | GET /api/admin/career-cv/:applicationId/download |
| Dosya | app/routes/api.admin.career-cv.$applicationId.download.ts |
| Amaç | Admin panelden başvurunun CV PDF’ini güvenli şekilde indirmek. Bunny Pull Zone 403/hotlink sorunlarını aşmak için Storage API ile proxy yapılır. |
| Yetkilendirme | Session gerekli; user.role === "admin". |
İstek: GET; path parametresi applicationId — career_applications.id (UUID).
Yanıt (başarı): 200 — Content-Type: application/pdf ve Content-Disposition: attachment; filename="..." (stream).
Hata: 401, 404, 500.
14. Blog Kapak Görseli Yükleme (Bunny Storage)
Section titled “14. Blog Kapak Görseli Yükleme (Bunny Storage)”| Özellik | Değer |
|---|---|
| Path | POST /api/blog-image-upload |
| Dosya | app/routes/api.blog-image-upload.ts |
| Amaç | Admin blog panelinde seçilen görseli Bunny Storage’a yüklemek ve public URL döndürmek. |
| Yetkilendirme | Session yok; public erişim (FormData: file, slug). |
İstek:
- Method: POST
- Content-Type:
multipart/form-data - Body (FormData):
slug(string) — blog yazısı slugfile(File) — sadeceimage/*
Bunny path: blog/{safeSlug}/image/{encodedName}
Yanıt (başarı): 200 — { "url": "https://pullzone.../blog/.../image/xxx.jpg" }
Hata: 400 (file yok/format uygunsuz), 500 (Bunny config veya upload hatası).
Özet Tablo — REST API’ler
Section titled “Özet Tablo — REST API’ler”| Endpoint | Method | Amaç | Yetki |
|---|---|---|---|
/api/graphql | POST | GraphQL sorgu/mutation | Session (resolver bazlı) |
/api/auth/* | * | Giriş, kayıt, OAuth, session | Public / Better Auth |
/api/stripe/webhook | POST | Stripe olayları (ödeme, abonelik) | Stripe-Signature |
/api/stripe/connect-onboarding | POST | Stripe Connect onboarding redirect | Instructor |
/api/instructor/update-manual-payout | POST | TR manuel ödeme bilgisi (IBAN/Payoneer) | Instructor |
/api/lesson-resource-upload | POST | Ders kaynağı yükleme (Bunny) | FormData: lessonId, file |
/api/quiz-resource-upload | POST | Quiz kaynağı yükleme (Bunny) | FormData: quizId, file |
/api/exercise-resource-upload | POST | Kod egzersizi kaynağı yükleme (Bunny) | FormData: exerciseId, file |
/api/lesson/caption-upload | POST | Video altyazısı (.vtt) yükleme (Bunny Stream) | FormData: lessonId, captionFile, langCode, label |
/api/lesson/caption-delete | POST | Video altyazısı silme (Bunny Stream) | FormData: captionId |
/api/chat-image-upload | POST | Sohbet görseli yükleme (Bunny) | FormData: file |
/api/blog-image-upload | POST | Blog kapak görseli yükleme (Bunny Storage) | FormData: file, slug |
/api/career-cv-upload | POST | Kariyer CV PDF yükleme (Bunny Storage) | FormData: jobId, file |
/api/admin/career-cv/:applicationId/download | GET | Admin-only CV indirme (proxy) | Admin + PDF stream |
/api/certificate/:id/download | GET | Sertifika PDF indirme | Session, sertifika sahibi |
/api/certificates/:id/download | GET | Aynı (geriye dönük URL) | Aynı |
/api/invoice/:enrollmentId/download | GET | Fatura PDF indirme | Session, enrollment sahibi |
/api/admin/activities | GET | Admin aktivite listesi (JSON) | Admin |
/api/video-telemetry | POST | Video izlenme telemetrisi (15 sn heartbeat) | Session |
/api/update-progress | POST | Video izleme süresi kaydı | Body: userId, lessonId, … |
GraphQL — Önemli Sorgular ve Mutation’lar
Section titled “GraphQL — Önemli Sorgular ve Mutation’lar”Şema tam listesi app/graphql/schema.ts içindedir. Sık kullanılanlar:
- Query:
me,courses,courseBySlug,myCertificates,conversationMessages,unreadMessagesCount,adminCourses,adminPayoutRequestsvb. - Mutation:
createCourse,updateCourse,toggleLessonCompletion,recordLearningActivity,requestPayout,createStripeCheckoutSession,addToCart,createReview,updatePayoutSettingsvb.
İstemci örneği: app/lib/graphql-client.ts — fetch("/api/graphql", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ query, variables }), credentials: "include" }).
İlgili Sayfalar
Section titled “İlgili Sayfalar”- API Referansı ve GraphQL — Şema, context, Better Auth konfigürasyonu.
- Video Altyazıları (Bunny Stream) — Altyazı yükleme/silme akışı, lesson_captions, Bunny API.
- Route Haritası — Tüm URL’lerin listesi.
- Sözlük — Terim tanımları.