openapi: 3.0.3
info:
  title: Liya AI — External API
  description: |
    Liya AI platformunu kendi uygulamalarınıza entegre etmek için REST API.

    Bu API ile chat widget'ları, 3D avatar entegrasyonları, sesli asistanlar
    veya Liya AI altyapısı üzerinde çalışan özel AI deneyimleri geliştirebilirsiniz.

    ## Kimlik Doğrulama

    `/api/v1/external/` altındaki tüm isteklerde `X-API-Key` header'ı zorunludur.
    API anahtarınızı [ai.liyalabs.com](https://ai.liyalabs.com) →
    **Projeler → API Anahtarları** bölümünden alın.

    ```
    X-API-Key: api-anahtariniz
    ```

    ## GAR — Global Application Router

    Liya AI dağıtık bir backend mimarisi kullanır. Her proje belirli bir backend
    instance'ına yönlendirilir. Backend URL'iniz dashboard'da
    **Ayarlar → API Yapılandırması** altında gösterilir:

    ```
    https://app-{X}-ai.liyalabs.com
    ```

    Tüm isteklerde bu URL'i base URL olarak kullanın.

    ## Rate Limiting

    - API anahtarı başına 120 istek / dakika
    - Kalan kota: `X-RateLimit-Remaining` response header'ı
    - Sıfırlanma zamanı (Unix): `X-RateLimit-Reset` response header'ı

    ## Hesap Türleri ve Özellik Erişimi

    | Özellik | STANDART | PREMIUM | PREMIUM PLUS |
    |---------|----------|---------|--------------|
    | Chat | ✅ | ✅ | ✅ |
    | Dosya Yükleme | ❌ | ✅ | ✅ |
    | Sesli Çıktı (TTS) | ❌ | ✅ | ✅ |
    | 3D Avatar | ❌ | ✅ | ✅ |
    | Özel Avatar Modeli | ❌ | ❌ | ✅ |
    | Kiosk Modu | ❌ | ❌ | ✅ |

    ## Kararlılık ve Versiyonlama

    Bu API [Semantic Versioning](https://semver.org) prensiplerini izler.

    - **Breaking change'ler** major versiyonu yükseltir (v1 → v2)
      ve **60 gün önceden** duyurulur.
    - **Yeni özellikler** minor versiyonu yükseltir (v0.1 → v0.2)
      ve geriye dönük uyumludur.
    - **Hata düzeltmeleri** patch versiyonunu yükseltir (v0.1.0 → v0.1.1).

    Versiyon **0.x** aşamasındayken önceden bildirim yapılmaksızın breaking change
    gerçekleşebilir. Güncel kalmak için [liyalabs.com/changelog](https://liyalabs.com/changelog)
    adresindeki değişiklik günlüğüne abone olun.

  version: 0.1.0
  contact:
    name: Liya Labs Destek
    url: https://liyalabs.com
    email: support@liyalabs.com
  license:
    name: Proprietary
    url: https://liyalabs.com/terms

servers:
  - url: https://app-1-ai.liyalabs.com
    description: Instance 1
  - url: https://app-2-ai.liyalabs.com
    description: Instance 2
  - url: https://app-3-ai.liyalabs.com
    description: Instance 3

security:
  - ApiKeyAuth: []

tags:
  - name: Assistants
    description: Projenizde tanımlı AI asistanlarını listeler
  - name: Sessions
    description: Kullanıcı başına konuşma oturumu oluşturma ve yönetme
  - name: Chat
    description: Mesaj gönderme ve AI yanıtı alma
  - name: Files
    description: Chat mesajlarına eklenecek dosya yükleme
  - name: Avatar & TTS
    description: Metin-ses dönüşümü ve 3D avatar dudak senkronizasyonu (PREMIUM+)
  - name: Tasks
    description: Asenkron görev durumu sorgulama (görsel / video üretimi)
  - name: Translation
    description: 100+ dil arasında metin çevirisi

paths:
  # ─── ASSISTANTS ────────────────────────────────────────────────────────────

  /api/v1/external/assistants/:
    get:
      tags: [Assistants]
      summary: Asistanları listele
      description: Projenize ait asistanları döndürür.
      parameters:
        - name: type
          in: query
          description: Asistan türüne göre filtrele
          required: false
          schema:
            type: string
            enum: [custom, coding_agent, linux_os]
      responses:
        "200":
          description: Asistan listesi
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Assistant"
              example:
                status: success
                data:
                  - id: "550e8400-e29b-41d4-a716-446655440000"
                    name: "Müşteri Destek Asistanı"
                    model: "gpt-4o"
                    assistant_type: "custom"
                    is_reasoning_model: false
                    total_messages: 1240
        "401":
          $ref: "#/components/responses/Unauthorized"

  # ─── SESSIONS ──────────────────────────────────────────────────────────────

  /api/v1/external/sessions/:
    get:
      tags: [Sessions]
      summary: Oturumları listele
      description: |
        Bir asistana ait oturumları sayfalı olarak döndürür.
        Kendi kullanıcılarınızla eşleştirmek için `external_session_id` kullanın.
      parameters:
        - name: assistant_id
          in: query
          required: true
          schema:
            type: string
            format: uuid
        - name: limit
          in: query
          schema:
            type: integer
            default: 20
            minimum: 1
            maximum: 50
        - name: offset
          in: query
          schema:
            type: integer
            default: 0
      responses:
        "200":
          description: Oturum listesi
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  data:
                    $ref: "#/components/schemas/SessionListResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"

    post:
      tags: [Sessions]
      summary: Yeni oturum oluştur
      description: |
        Yeni bir konuşma oturumu oluşturur. Kendi sisteminizde takip etmek için
        `external_session_id` geçebilirsiniz.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateSessionRequest"
            example:
              assistant_id: "550e8400-e29b-41d4-a716-446655440000"
              session_name: "Destek Talebi #1234"
              external_session_id: "kullanici_42"
      responses:
        "201":
          description: Oluşturulan oturum
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  data:
                    $ref: "#/components/schemas/Session"
        "401":
          $ref: "#/components/responses/Unauthorized"

  /api/v1/external/sessions/{session_id}/:
    parameters:
      - name: session_id
        in: path
        required: true
        schema:
          type: string
          format: uuid

    get:
      tags: [Sessions]
      summary: Oturum detayı
      responses:
        "200":
          description: Oturum bilgisi
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  data:
                    $ref: "#/components/schemas/Session"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"

    delete:
      tags: [Sessions]
      summary: Oturumu kapat
      description: Oturumu soft-delete ile kapatır. Geçmiş korunur, oturum pasif hale gelir.
      responses:
        "200":
          description: Oturum kapatıldı
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  message:
                    type: string
                    example: Session closed
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"

  /api/v1/external/sessions/{session_id}/history/:
    get:
      tags: [Sessions]
      summary: Oturum geçmişi
      description: Bir oturumdaki tüm mesajları sayfalı olarak getirir.
      parameters:
        - name: session_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: limit
          in: query
          schema:
            type: integer
            default: 50
            minimum: 1
            maximum: 100
        - name: offset
          in: query
          schema:
            type: integer
            default: 0
      responses:
        "200":
          description: Mesaj geçmişi
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  data:
                    $ref: "#/components/schemas/SessionHistoryResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"

  # ─── CHAT ──────────────────────────────────────────────────────────────────

  /api/v1/external/chat/:
    post:
      tags: [Chat]
      summary: Mesaj gönder
      description: |
        Asistana mesaj gönderir ve AI yanıtını alır.

        - `session_id` belirtilmezse otomatik yeni oturum oluşturulur.
        - Yanıttaki `media` dizisi, AI yanıtından ayıklanmış görsel/video URL'lerini
          içerir (MediaExtractor, örn. DALL-E veya Kling AI üretimi).
        - Yanıtta `metadata.async_task_id` varsa üretim devam etmektedir;
          `/tasks/{task_id}/status/` endpoint'ini polling ile kullanın.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SendMessageRequest"
            example:
              assistant_id: "550e8400-e29b-41d4-a716-446655440000"
              message: "Ürünleriniz hakkında bilgi alabilir miyim?"
              session_id: "660e8400-e29b-41d4-a716-446655440000"
      responses:
        "200":
          description: Asistan yanıtı
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  data:
                    $ref: "#/components/schemas/ChatResponse"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "402":
          $ref: "#/components/responses/InsufficientBalance"
        "403":
          $ref: "#/components/responses/Forbidden"
        "429":
          $ref: "#/components/responses/RateLimited"

  /api/v1/external/chat/with-files/:
    post:
      tags: [Chat]
      summary: Mesaj gönder (dosyalı)
      description: |
        Önceden yüklenmiş dosyaları referans alarak mesaj gönderir.
        Önce `/files/` ile dosya yükleyin, dönen ID'leri buraya geçin.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: "#/components/schemas/SendMessageRequest"
                - type: object
                  properties:
                    file_ids:
                      type: array
                      items:
                        type: string
                        format: uuid
                      description: Yükleme endpoint'inden dönen dosya ID'leri
            example:
              assistant_id: "550e8400-e29b-41d4-a716-446655440000"
              message: "Bu dosyayı analiz et"
              session_id: "660e8400-e29b-41d4-a716-446655440000"
              file_ids: ["770e8400-e29b-41d4-a716-446655440000"]
      responses:
        "200":
          description: Asistan yanıtı
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  data:
                    $ref: "#/components/schemas/ChatResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "402":
          $ref: "#/components/responses/InsufficientBalance"

  # ─── FILES ─────────────────────────────────────────────────────────────────

  /api/v1/external/files/:
    post:
      tags: [Files]
      summary: Dosya yükle
      description: |
        Oturuma dosya yükler. Maksimum 50 MB.

        Desteklenen formatlar: `txt`, `csv`, `md`, `pdf`, `doc`, `docx`, `xls`,
        `xlsx`, `json` ve tüm yaygın görsel formatları.

        Dönen `id`, sonraki chat isteklerinde `file_ids` alanına geçilebilir.
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required: [session_id, file]
              properties:
                session_id:
                  type: string
                  format: uuid
                file:
                  type: string
                  format: binary
      responses:
        "201":
          description: Yüklenen dosya bilgisi
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  data:
                    $ref: "#/components/schemas/FileAttachment"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"

  # ─── AVATAR & TTS ──────────────────────────────────────────────────────────

  /api/v1/external/tts/:
    post:
      tags: [Avatar & TTS]
      summary: Metni sese dönüştür
      description: |
        Verilen metni ses dosyasına dönüştürür. Yanıt doğrudan ses verisidir (binary blob, JSON değil).
        Dudak senkronizasyonu gerekmiyorsa bu endpoint tercih edilebilir.

        **Gereksinim:** PREMIUM veya üzeri hesap.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/TTSRequest"
      responses:
        "200":
          description: Ses dosyası (Opus veya MP3)
          content:
            audio/ogg:
              schema:
                type: string
                format: binary
            audio/mpeg:
              schema:
                type: string
                format: binary
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"

  /api/v1/external/avatar/speech/:
    post:
      tags: [Avatar & TTS]
      summary: Avatar konuşması (viseme + ses)
      description: |
        Metni sese dönüştürür ve ARKit uyumlu viseme zamanlama verisi döndürür.
        3D avatar modeli üzerinde gerçek zamanlı dudak senkronizasyonu için kullanılır.

        Ses verisi JSON response body içinde Base64 olarak döner.
        iOS/Safari'de format otomatik olarak MP3'e ayarlanır; diğer tarayıcılarda Opus döner.

        **Gereksinim:** PREMIUM veya üzeri hesap.

        ### Viseme morph target'ları
        `visemes` dizisi avatar modelinizdeki şu blend shape hedeflerini sürer:
        `viseme_PP`, `viseme_FF`, `viseme_TH`, `viseme_DD`, `viseme_kk`,
        `viseme_CH`, `viseme_SS`, `viseme_nn`, `viseme_RR`, `viseme_aa`,
        `viseme_E`, `viseme_I`, `viseme_O`, `viseme_U`
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/AvatarSpeechRequest"
            example:
              text: "Merhaba! Size nasıl yardımcı olabilirim?"
              voice: nova
              speed: 1.0
              include_audio: true
      responses:
        "200":
          description: Viseme verisi ve Base64 ses
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  data:
                    $ref: "#/components/schemas/AvatarSpeechResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"

  /api/v1/external/avatar/model/:
    get:
      tags: [Avatar & TTS]
      summary: Avatar model URL'i
      description: |
        Bir asistana atanmış GLB/GLTF avatar model dosyasının HTTPS URL'ini döndürür.

        - PREMIUM hesaplar varsayılan Liya avatar modelini alır.
        - PREMIUM PLUS hesaplar asistana özel model atanmış olabilir.

        **Gereksinim:** PREMIUM veya üzeri hesap.
      parameters:
        - name: assistant_id
          in: query
          required: false
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: Avatar model bilgisi
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  data:
                    $ref: "#/components/schemas/AvatarModelResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"

  /api/v1/external/user/access/:
    get:
      tags: [Avatar & TTS]
      summary: Özellik erişim kontrolü
      description: |
        Hesap türünü ve mevcut premium özellikleri döndürür.
        Widget yüklenirken avatar butonu, ses butonu veya dosya yükleme
        özelliğini koşullu göstermek için kullanın.
      responses:
        "200":
          description: Erişim bilgisi
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  data:
                    $ref: "#/components/schemas/UserAccessResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"

  # ─── TASKS ─────────────────────────────────────────────────────────────────

  /api/v1/external/tasks/{task_id}/status/:
    get:
      tags: [Tasks]
      summary: Asenkron görev durumu
      description: |
        Görsel veya video üretimi gibi asenkron görevlerin durumunu sorgular (örn. Kling AI).

        Chat yanıtında `metadata.async_task_id` bulunuyorsa medya henüz üretilmektedir.
        `status` değeri `completed` veya `failed` olana kadar bu endpoint'i polling ile kullanın,
        ardından `result_urls` ile çıktıyı görüntüleyin.

        **Önerilen polling aralığı:** 3–5 saniye.
      parameters:
        - name: task_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: Görev durumu
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  data:
                    $ref: "#/components/schemas/TaskStatusResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"

  # ─── TRANSLATION ────────────────────────────────────────────────────────────

  /api/v1/external/translate/:
    post:
      tags: [Translation]
      summary: Metin çevirisi
      description: |
        OpenAI çeviri yeteneklerini kullanarak metni bir dilden başka bir dile çevirir.
        100'den fazla dili destekler.

        Kaynak dil belirtilmediğinde otomatik algılanır.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/TranslationRequest"
            example:
              text: "Hello, how are you?"
              target_language: "tr"
              source_language: "en"
      responses:
        "200":
          description: Çeviri sonucu
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  data:
                    $ref: "#/components/schemas/TranslationResponse"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "429":
          $ref: "#/components/responses/RateLimited"

  /api/v1/external/translate/languages/:
    get:
      tags: [Translation]
      summary: Desteklenen dilleri listele
      description: |
        Çeviri için desteklenen tüm dillerin listesini döndürür.
        `code` alanını `target_language` veya `source_language` parametresi olarak kullanın.
      responses:
        "200":
          description: Desteklenen diller listesi
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/LanguageInfo"
              example:
                status: success
                data:
                  - code: "en"
                    name: "İngilizce"
                    native_name: "English"
                  - code: "tr"
                    name: "Türkçe"
                    native_name: "Türkçe"
                  - code: "zh"
                    name: "Çince"
                    native_name: "中文"
        "401":
          $ref: "#/components/responses/Unauthorized"

# ─── COMPONENTS ──────────────────────────────────────────────────────────────

components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: Dashboard'dan aldığınız Liya AI API anahtarı

  schemas:
    # ── Temel nesneler ────────────────────────────────────────────────────────

    Assistant:
      type: object
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
          example: Müşteri Destek Asistanı
        description:
          type: string
        model:
          type: string
          example: gpt-4o
        model_display:
          type: string
          example: GPT-4o
        assistant_type:
          type: string
          enum: [custom, coding_agent, linux_os]
          example: custom
        is_reasoning_model:
          type: boolean
        total_messages:
          type: integer

    Session:
      type: object
      properties:
        id:
          type: string
          format: uuid
        assistant_id:
          type: string
          format: uuid
        session_name:
          type: string
          example: Yeni Sohbet
        message_count:
          type: integer
        created_at:
          type: string
          format: date-time
        last_message_at:
          type: string
          format: date-time
          nullable: true
        external_session_id:
          type: string
          nullable: true

    SessionListResponse:
      type: object
      properties:
        sessions:
          type: array
          items:
            $ref: "#/components/schemas/Session"
        total:
          type: integer
        limit:
          type: integer
        offset:
          type: integer

    SessionHistoryResponse:
      type: object
      properties:
        session_id:
          type: string
          format: uuid
        messages:
          type: array
          items:
            $ref: "#/components/schemas/Message"
        total:
          type: integer

    Message:
      type: object
      properties:
        id:
          type: string
          format: uuid
        content:
          type: string
          description: Mesaj metni (asistan mesajlarında markdown desteklenir)
        role:
          type: string
          enum: [user, assistant]
        created_at:
          type: string
          format: date-time
        response_time:
          type: number
          format: float
          description: Asistan yanıt süresi (saniye)
          nullable: true

    MessageMediaItem:
      type: object
      description: Asistan yanıtından ayıklanmış görsel veya video
      properties:
        type:
          type: string
          enum: [image, video]
        url:
          type: string
          format: uri
        alt:
          type: string
          nullable: true
        source:
          type: string
          description: İçerik kaynağı (örn. dall-e, klingai)
          nullable: true

    FileAttachment:
      type: object
      properties:
        id:
          type: string
          format: uuid
        file_name:
          type: string
        file_size:
          type: integer
          description: Dosya boyutu (bayt)
        file_type:
          type: string
        openai_file_id:
          type: string
          nullable: true
        created_at:
          type: string
          format: date-time

    # ── İstekler ──────────────────────────────────────────────────────────────

    CreateSessionRequest:
      type: object
      required: [assistant_id]
      properties:
        assistant_id:
          type: string
          format: uuid
        session_name:
          type: string
          example: Destek Talebi #1234
        external_session_id:
          type: string
          description: Kendi sisteminizde kullanıcı/oturum eşleştirmesi için harici ID

    SendMessageRequest:
      type: object
      required: [assistant_id, message]
      properties:
        assistant_id:
          type: string
          format: uuid
        message:
          type: string
          example: Çalışma saatleriniz nedir?
        session_id:
          type: string
          format: uuid
          description: Belirtilmezse otomatik yeni oturum oluşturulur
        external_session_id:
          type: string
          description: Bu oturum için kendi sisteminizden ID

    TTSRequest:
      type: object
      required: [text]
      properties:
        text:
          type: string
          maxLength: 4096
          example: Merhaba, size nasıl yardımcı olabilirim?
        voice:
          type: string
          default: nova
          description: OpenAI TTS ses adı
          example: nova
        speed:
          type: number
          format: float
          default: 1.0
          minimum: 0.25
          maximum: 4.0

    AvatarSpeechRequest:
      type: object
      required: [text]
      properties:
        text:
          type: string
          maxLength: 4096
        voice:
          type: string
          default: nova
        speed:
          type: number
          format: float
          default: 1.0
        include_audio:
          type: boolean
          default: true
          description: false ise yalnızca viseme verisi döner, ses eklenmez

    # ── Yanıtlar ──────────────────────────────────────────────────────────────

    ChatResponse:
      type: object
      properties:
        session_id:
          type: string
          format: uuid
        message_id:
          type: string
          format: uuid
        response:
          type: string
          description: Asistan yanıt metni (markdown destekli)
        response_time:
          type: number
          format: float
          description: Yanıt oluşturma süresi (saniye)
        suggestions:
          type: array
          items:
            type: string
          description: Kullanıcıya gösterilecek hızlı yanıt önerileri
        metadata:
          type: object
          nullable: true
          properties:
            async_task_id:
              type: string
              format: uuid
              description: Asenkron görev başlatıldıysa görev ID'si
            async_task_type:
              type: string
              example: klingai
        annotations:
          type: array
          description: Web arama alıntıları (web araması kullanıldıysa)
          items:
            type: object
            properties:
              type:
                type: string
                enum: [url_citation, file_citation]
              url:
                type: string
                format: uri
              title:
                type: string
        media:
          type: array
          description: Yanıttan ayıklanmış görsel/video (MediaExtractor)
          items:
            $ref: "#/components/schemas/MessageMediaItem"
        usage:
          type: object
          nullable: true
          properties:
            tokens_used:
              type: integer
            cost_usd:
              type: number
              format: float

    VisemeData:
      type: object
      description: Dudak senkronizasyonu animasyonu için tek viseme zamanlama girişi
      properties:
        time:
          type: number
          format: float
          description: Saniye cinsinden zaman damgası
        viseme:
          type: integer
          description: Viseme indeksi (0–20, ARKit uyumlu)
        duration:
          type: number
          format: float
          description: Saniye cinsinden süre

    AvatarSpeechResponse:
      type: object
      properties:
        visemes:
          type: array
          items:
            $ref: "#/components/schemas/VisemeData"
        duration:
          type: number
          format: float
          description: Toplam ses süresi (saniye)
        text:
          type: string
        audio_base64:
          type: string
          format: byte
          description: Base64 kodlanmış ses verisi (include_audio=true ise mevcut)
        audio_format:
          type: string
          enum: [mp3, opus]
          description: iOS/Safari'de mp3, diğer tarayıcılarda opus
        audio_mime:
          type: string
          example: audio/mpeg

    AvatarModelResponse:
      type: object
      properties:
        model_url:
          type: string
          format: uri
          description: GLB/GLTF model dosyasının HTTPS URL'i
        model_type:
          type: string
          example: glb
        source:
          type: string
          enum: [default, custom]
          description: default = Liya varsayılan modeli, custom = asistana özel model

    UserAccessResponse:
      type: object
      properties:
        has_avatar_access:
          type: boolean
          description: PREMIUM ve üzeri hesaplarda true
        account_type:
          type: string
          enum: [standard, premium, premium_plus, enterprise, system_admin]
        can_use_custom_avatar:
          type: boolean
          description: PREMIUM_PLUS ve üzeri hesaplarda true

    TaskStatusResponse:
      type: object
      properties:
        task_id:
          type: string
          format: uuid
        status:
          type: string
          enum: [pending, submitted, processing, completed, failed, cancelled]
        task_type:
          type: string
          example: klingai
        result_urls:
          type: array
          items:
            type: string
            format: uri
          description: Görev tamamlandığında çıktı URL'leri
        error_code:
          type: string
          nullable: true
        error_message:
          type: string
          nullable: true
        created_at:
          type: string
          format: date-time
          nullable: true
        completed_at:
          type: string
          format: date-time
          nullable: true

    TranslationRequest:
      type: object
      required: [text, target_language]
      properties:
        text:
          type: string
          maxLength: 10000
          description: Çevrilecek metin
          example: "Hello, how are you?"
        target_language:
          type: string
          description: Hedef dil kodu (örn. tr, en, zh, de, fr)
          example: "tr"
        source_language:
          type: string
          description: Kaynak dil kodu (belirtilmezse otomatik algılanır)
          example: "en"

    TranslationResponse:
      type: object
      properties:
        translated_text:
          type: string
          description: Çevrilmiş metin
          example: "Merhaba, nasılsın?"
        source_language:
          type: string
          description: Algılanan veya sağlanan kaynak dil kodu
          example: "en"
        target_language:
          type: string
          description: Hedef dil kodu
          example: "tr"

    LanguageInfo:
      type: object
      properties:
        code:
          type: string
          description: ISO 639-1 dil kodu
          example: "en"
        name:
          type: string
          description: Dil adı (İngilizce)
          example: "English"
        native_name:
          type: string
          description: Dil adı (kendi alfabesiyle)
          example: "English"

    ErrorResponse:
      type: object
      properties:
        status:
          type: string
          example: error
        code:
          type: string
          example: INVALID_API_KEY
        message:
          type: string
          example: The API key provided is invalid or expired.
        data:
          type: object
          nullable: true

  responses:
    Unauthorized:
      description: API anahtarı eksik veya geçersiz
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          example:
            status: error
            code: INVALID_API_KEY
            message: The API key provided is invalid or expired.

    Forbidden:
      description: Bu özellik hesap türünüzde kullanılamaz
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          example:
            status: error
            code: FEATURE_NOT_AVAILABLE
            message: 3D Avatar features require Premium or higher subscription.

    NotFound:
      description: Kaynak bulunamadı
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          example:
            status: error
            code: NOT_FOUND
            message: The requested resource was not found.

    BadRequest:
      description: Geçersiz istek parametreleri
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          example:
            status: error
            code: BAD_REQUEST
            message: assistant_id is required.

    InsufficientBalance:
      description: Yetersiz bakiye
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          example:
            status: error
            code: INSUFFICIENT_BALANCE
            message: Insufficient balance to process this request.
            data:
              current_balance: 0.50
              estimated_cost: 0.003

    RateLimited:
      description: Rate limit aşıldı
      headers:
        X-RateLimit-Remaining:
          schema:
            type: integer
          description: Kalan istek sayısı
        X-RateLimit-Reset:
          schema:
            type: integer
          description: Rate limit sıfırlanma zamanı (Unix timestamp)
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          example:
            status: error
            code: RATE_LIMITED
            message: Rate limit exceeded. Please wait before retrying.
