openapi: 3.0.3
info:
  title: PratikYedek API
  description: KVKK uyumlu, uçtan uca şifrelenmiş Türkiye bulut yedekleme API
  version: 0.1.0
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
  schemas: {}
paths:
  /v1/health:
    get:
      summary: Liveness probe — public, no auth
      tags:
        - system
      responses:
        "200":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    enum:
                      - ok
                  service:
                    type: string
                    enum:
                      - pratikyedek-api
                  version:
                    type: string
                  timestamp:
                    type: string
                required:
                  - status
                  - service
                  - version
                  - timestamp
                additionalProperties: false
  /v1/version:
    get:
      summary: API version info
      tags:
        - system
      responses:
        "200":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  service:
                    type: string
                    enum:
                      - pratikyedek-api
                  version:
                    type: string
                  node_env:
                    type: string
                required:
                  - service
                  - version
                  - node_env
                additionalProperties: false
  /v1/status:
    get:
      summary: Component status — public, no auth (status page tüketir)
      tags:
        - system
      responses:
        "200":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    enum:
                      - ok
                      - degraded
                      - down
                  service:
                    type: string
                    enum:
                      - pratikyedek-api
                  version:
                    type: string
                  timestamp:
                    type: string
                  components:
                    type: object
                    properties:
                      api:
                        type: object
                        properties:
                          status:
                            type: string
                            enum:
                              - ok
                              - degraded
                              - down
                              - unknown
                          latency_ms:
                            type: number
                        required:
                          - status
                        additionalProperties: false
                      db:
                        type: object
                        properties:
                          status:
                            type: string
                            enum:
                              - ok
                              - degraded
                              - down
                              - unknown
                          latency_ms:
                            type: number
                          error:
                            type: string
                        required:
                          - status
                        additionalProperties: false
                      redis:
                        type: object
                        properties:
                          status:
                            type: string
                            enum:
                              - ok
                              - degraded
                              - down
                              - unknown
                          latency_ms:
                            type: number
                          error:
                            type: string
                        required:
                          - status
                        additionalProperties: false
                    required:
                      - api
                      - db
                      - redis
                    additionalProperties: false
                required:
                  - status
                  - service
                  - version
                  - timestamp
                  - components
                additionalProperties: false
        "503":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    enum:
                      - ok
                      - degraded
                      - down
                  service:
                    type: string
                    enum:
                      - pratikyedek-api
                  version:
                    type: string
                  timestamp:
                    type: string
                  components:
                    type: object
                    properties:
                      api:
                        type: object
                        properties:
                          status:
                            type: string
                            enum:
                              - ok
                              - degraded
                              - down
                              - unknown
                          latency_ms:
                            type: number
                        required:
                          - status
                        additionalProperties: false
                      db:
                        type: object
                        properties:
                          status:
                            type: string
                            enum:
                              - ok
                              - degraded
                              - down
                              - unknown
                          latency_ms:
                            type: number
                          error:
                            type: string
                        required:
                          - status
                        additionalProperties: false
                      redis:
                        type: object
                        properties:
                          status:
                            type: string
                            enum:
                              - ok
                              - degraded
                              - down
                              - unknown
                          latency_ms:
                            type: number
                          error:
                            type: string
                        required:
                          - status
                        additionalProperties: false
                    required:
                      - api
                      - db
                      - redis
                    additionalProperties: false
                required:
                  - status
                  - service
                  - version
                  - timestamp
                  - components
                additionalProperties: false
  /v1/branding/version:
    get:
      summary: Branding asset sürüm timestamp (cache-bust)
      tags:
        - branding
      responses:
        "200":
          description: Default Response
  /v1/desktop/update/{target}/{arch}/{currentVersion}:
    get:
      summary: Tauri auto-updater manifest — public, no auth
      tags:
        - desktop
      parameters:
        - schema:
            type: string
            enum:
              - windows
              - darwin
              - linux
          in: path
          name: target
          required: true
        - schema:
            type: string
            enum:
              - x86_64
              - aarch64
          in: path
          name: arch
          required: true
        - schema:
            type: string
            minLength: 1
            maxLength: 64
            pattern: ^\d+\.\d+\.\d+(-[\w.-]+)?$
          in: path
          name: currentVersion
          required: true
      responses:
        "200":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  version:
                    type: string
                  notes:
                    type: string
                  pub_date:
                    type: string
                  platforms:
                    type: object
                    additionalProperties:
                      type: object
                      properties:
                        signature:
                          type: string
                        url:
                          type: string
                          format: uri
                      required:
                        - signature
                        - url
                      additionalProperties: false
                required:
                  - version
                  - notes
                  - pub_date
                  - platforms
                additionalProperties: false
        "204":
          description: Default Response
          content:
            application/json:
              schema:
                enum:
                  - "null"
                nullable: true
        "404":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                      message:
                        type: string
                    required:
                      - code
                      - message
                    additionalProperties: false
                required:
                  - error
                additionalProperties: false
  /v1/integrations/cozum-merkezi/identity:
    post:
      summary: ÇözümMerkezi destek widget kimlik push (HMAC SHA-256)
      tags:
        - integrations
      responses:
        "200":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                  identity_dogrulandi:
                    type: boolean
                  error:
                    type: string
                  skipped:
                    type: boolean
                required:
                  - ok
                additionalProperties: false
  /v1/integrations/cozum-merkezi/config:
    get:
      summary: ÇözümMerkezi widget config (public API key + base URL)
      tags:
        - integrations
      responses:
        "200":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  enabled:
                    type: boolean
                  apiKey:
                    type: string
                  base:
                    type: string
                required:
                  - enabled
                  - apiKey
                  - base
                additionalProperties: false
  /v1/auth/register:
    post:
      summary: Yeni hesap ve ilk kullanıcı oluşturur (Argon2id parola hash)
      tags:
        - auth
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                email:
                  type: string
                  format: email
                  maxLength: 254
                password:
                  type: string
                  minLength: 12
                  maxLength: 200
                  allOf:
                    - pattern: "[A-Z]"
                    - pattern: "[a-z]"
                    - pattern: "[0-9]"
                account_type:
                  type: string
                  enum:
                    - individual
                    - business
                    - accountant
                    - enterprise
                name:
                  type: string
                  minLength: 1
                  maxLength: 200
                display_name:
                  type: string
                  minLength: 1
                  maxLength: 200
                kvkk_consent:
                  type: boolean
                  enum:
                    - true
                kvkk_consent_version:
                  type: string
                  minLength: 1
                  maxLength: 20
                marketing_consent:
                  type: boolean
                locale:
                  type: string
                  minLength: 2
                  maxLength: 10
              required:
                - email
                - password
                - account_type
                - name
                - kvkk_consent
                - kvkk_consent_version
              additionalProperties: false
        required: true
      responses:
        "201":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  user_id:
                    type: string
                    pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
                  account_id:
                    type: string
                    pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
                  verification_required:
                    type: boolean
                    enum:
                      - true
                required:
                  - user_id
                  - account_id
                  - verification_required
                additionalProperties: false
  /v1/auth/login:
    post:
      summary: E-posta + parola (+ opsiyonel TOTP) ile oturum açar
      tags:
        - auth
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                email:
                  type: string
                  format: email
                  maxLength: 254
                password:
                  type: string
                  minLength: 1
                  maxLength: 200
                totp_code:
                  type: string
                  pattern: ^\d{6}$
                backup_code:
                  type: string
                  minLength: 4
                  maxLength: 40
              required:
                - email
                - password
              additionalProperties: false
        required: true
      responses:
        "200":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  access_token:
                    type: string
                  expires_in:
                    type: number
                  user:
                    type: object
                    properties:
                      id:
                        type: string
                        pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
                      email:
                        type: string
                      name:
                        type: string
                      role:
                        type: string
                        enum:
                          - owner
                          - admin
                          - member
                      totp_enabled:
                        type: boolean
                    required:
                      - id
                      - email
                      - name
                      - role
                      - totp_enabled
                    additionalProperties: false
                  account:
                    type: object
                    properties:
                      id:
                        type: string
                        pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
                      account_type:
                        type: string
                        enum:
                          - individual
                          - business
                          - accountant
                          - enterprise
                      display_name:
                        type: string
                      density_mode:
                        type: string
                        enum:
                          - comfort
                          - pro
                      locale:
                        type: string
                    required:
                      - id
                      - account_type
                      - display_name
                      - density_mode
                      - locale
                    additionalProperties: false
                  is_admin:
                    type: boolean
                  refresh_token:
                    type: string
                required:
                  - access_token
                  - expires_in
                  - user
                  - account
                  - is_admin
                additionalProperties: false
  /v1/auth/logout:
    post:
      summary: Refresh cookie'yi siler ve session'ı revoke eder
      tags:
        - auth
      responses:
        "200":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                    enum:
                      - true
                required:
                  - ok
                additionalProperties: false
  /v1/auth/refresh:
    post:
      summary: Refresh token rotation — cookie (web) veya body (mobile) kabul eder
      tags:
        - auth
      requestBody:
        content:
          application/json:
            schema:
              anyOf:
                - not: {}
                - type: object
                  properties:
                    refresh_token:
                      type: string
                      minLength: 10
                  additionalProperties: false
              nullable: true
      responses:
        "200":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  access_token:
                    type: string
                  expires_in:
                    type: number
                  refresh_token:
                    type: string
                required:
                  - access_token
                  - expires_in
                additionalProperties: false
  /v1/auth/2fa/setup:
    post:
      summary: 2FA TOTP secret üret + 8 backup code
      tags:
        - auth
      responses:
        "200":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  secret:
                    type: string
                  qr_url:
                    type: string
                  backup_codes:
                    type: array
                    items:
                      type: string
                    minItems: 8
                    maxItems: 8
                required:
                  - secret
                  - qr_url
                  - backup_codes
                additionalProperties: false
  /v1/auth/2fa/verify:
    post:
      summary: 2FA TOTP kodu doğrula ve aktive et
      tags:
        - auth
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                totp_code:
                  type: string
                  pattern: ^\d{6}$
              required:
                - totp_code
              additionalProperties: false
        required: true
      responses:
        "200":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                    enum:
                      - true
                required:
                  - ok
                additionalProperties: false
  /v1/auth/2fa/disable:
    post:
      summary: 2FA devre dışı bırak (parola + TOTP zorunlu)
      tags:
        - auth
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                password:
                  type: string
                  minLength: 1
                  maxLength: 200
                totp_code:
                  type: string
                  pattern: ^\d{6}$
              required:
                - password
                - totp_code
              additionalProperties: false
        required: true
      responses:
        "200":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                    enum:
                      - true
                required:
                  - ok
                additionalProperties: false
  /v1/auth/magic-link:
    post:
      summary: Tek-kullanımlık giriş bağlantısı gönder
      tags:
        - auth
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                email:
                  type: string
                  format: email
                  maxLength: 254
              required:
                - email
              additionalProperties: false
        required: true
      responses:
        "200":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                    enum:
                      - true
                required:
                  - ok
                additionalProperties: false
  /v1/auth/magic-link/{token}:
    get:
      summary: Magic link token doğrula → access + refresh tokens
      tags:
        - auth
      parameters:
        - schema:
            type: string
            minLength: 8
            maxLength: 200
          in: path
          name: token
          required: true
      responses:
        "200":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  access_token:
                    type: string
                  expires_in:
                    type: number
                  user:
                    type: object
                    properties:
                      id:
                        type: string
                        pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
                      email:
                        type: string
                      name:
                        type: string
                      role:
                        type: string
                        enum:
                          - owner
                          - admin
                          - member
                      totp_enabled:
                        type: boolean
                    required:
                      - id
                      - email
                      - name
                      - role
                      - totp_enabled
                    additionalProperties: false
                  account:
                    type: object
                    properties:
                      id:
                        type: string
                        pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
                      account_type:
                        type: string
                        enum:
                          - individual
                          - business
                          - accountant
                          - enterprise
                      display_name:
                        type: string
                      density_mode:
                        type: string
                        enum:
                          - comfort
                          - pro
                      locale:
                        type: string
                    required:
                      - id
                      - account_type
                      - display_name
                      - density_mode
                      - locale
                    additionalProperties: false
                  is_admin:
                    type: boolean
                  refresh_token:
                    type: string
                required:
                  - access_token
                  - expires_in
                  - user
                  - account
                  - is_admin
                additionalProperties: false
  /v1/auth/sms-login/request:
    post:
      summary: SMS ile giriş — doğrulama kodu iste
      tags:
        - auth
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                phone:
                  type: string
                  minLength: 10
                  maxLength: 20
              required:
                - phone
              additionalProperties: false
        required: true
      responses:
        "200":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                    enum:
                      - true
                required:
                  - ok
                additionalProperties: false
        "400":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                      message:
                        type: string
                      message_en:
                        type: string
                      details:
                        type: object
                        additionalProperties: {}
                      request_id:
                        type: string
                      timestamp:
                        type: string
                    required:
                      - code
                      - message
                      - request_id
                      - timestamp
                    additionalProperties: false
                required:
                  - error
                additionalProperties: false
        "429":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                      message:
                        type: string
                      message_en:
                        type: string
                      details:
                        type: object
                        additionalProperties: {}
                      request_id:
                        type: string
                      timestamp:
                        type: string
                    required:
                      - code
                      - message
                      - request_id
                      - timestamp
                    additionalProperties: false
                required:
                  - error
                additionalProperties: false
        "500":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                      message:
                        type: string
                      message_en:
                        type: string
                      details:
                        type: object
                        additionalProperties: {}
                      request_id:
                        type: string
                      timestamp:
                        type: string
                    required:
                      - code
                      - message
                      - request_id
                      - timestamp
                    additionalProperties: false
                required:
                  - error
                additionalProperties: false
  /v1/auth/sms-login/verify:
    post:
      summary: SMS ile giriş — kodu doğrula ve oturum aç
      tags:
        - auth
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                phone:
                  type: string
                  minLength: 10
                  maxLength: 20
                code:
                  type: string
                  minLength: 6
                  maxLength: 6
              required:
                - phone
                - code
              additionalProperties: false
        required: true
      responses:
        "200":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  access_token:
                    type: string
                  expires_in:
                    type: number
                  user:
                    type: object
                    properties:
                      id:
                        type: string
                        pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
                      email:
                        type: string
                      name:
                        type: string
                      role:
                        type: string
                        enum:
                          - owner
                          - admin
                          - member
                      totp_enabled:
                        type: boolean
                    required:
                      - id
                      - email
                      - name
                      - role
                      - totp_enabled
                    additionalProperties: false
                  account:
                    type: object
                    properties:
                      id:
                        type: string
                        pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
                      account_type:
                        type: string
                        enum:
                          - individual
                          - business
                          - accountant
                          - enterprise
                      display_name:
                        type: string
                      density_mode:
                        type: string
                        enum:
                          - comfort
                          - pro
                      locale:
                        type: string
                    required:
                      - id
                      - account_type
                      - display_name
                      - density_mode
                      - locale
                    additionalProperties: false
                  is_admin:
                    type: boolean
                  refresh_token:
                    type: string
                required:
                  - access_token
                  - expires_in
                  - user
                  - account
                  - is_admin
                additionalProperties: false
        "400":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                      message:
                        type: string
                      message_en:
                        type: string
                      details:
                        type: object
                        additionalProperties: {}
                      request_id:
                        type: string
                      timestamp:
                        type: string
                    required:
                      - code
                      - message
                      - request_id
                      - timestamp
                    additionalProperties: false
                required:
                  - error
                additionalProperties: false
        "401":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                      message:
                        type: string
                      message_en:
                        type: string
                      details:
                        type: object
                        additionalProperties: {}
                      request_id:
                        type: string
                      timestamp:
                        type: string
                    required:
                      - code
                      - message
                      - request_id
                      - timestamp
                    additionalProperties: false
                required:
                  - error
                additionalProperties: false
        "429":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                      message:
                        type: string
                      message_en:
                        type: string
                      details:
                        type: object
                        additionalProperties: {}
                      request_id:
                        type: string
                      timestamp:
                        type: string
                    required:
                      - code
                      - message
                      - request_id
                      - timestamp
                    additionalProperties: false
                required:
                  - error
                additionalProperties: false
        "500":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                      message:
                        type: string
                      message_en:
                        type: string
                      details:
                        type: object
                        additionalProperties: {}
                      request_id:
                        type: string
                      timestamp:
                        type: string
                    required:
                      - code
                      - message
                      - request_id
                      - timestamp
                    additionalProperties: false
                required:
                  - error
                additionalProperties: false
  /v1/users/me:
    get:
      summary: Oturum sahibi kullanıcı + hesap profilini döner
      tags:
        - users
      security:
        - bearerAuth: []
      responses:
        "200":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  user:
                    type: object
                    properties:
                      id:
                        type: string
                        pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
                      email:
                        type: string
                      name:
                        type: string
                      role:
                        type: string
                        enum:
                          - owner
                          - admin
                          - member
                      totp_enabled:
                        type: boolean
                    required:
                      - id
                      - email
                      - name
                      - role
                      - totp_enabled
                    additionalProperties: false
                  account:
                    type: object
                    properties:
                      id:
                        type: string
                        pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
                      account_type:
                        type: string
                        enum:
                          - individual
                          - business
                          - accountant
                          - enterprise
                      display_name:
                        type: string
                      density_mode:
                        type: string
                        enum:
                          - comfort
                          - pro
                      locale:
                        type: string
                    required:
                      - id
                      - account_type
                      - display_name
                      - density_mode
                      - locale
                    additionalProperties: false
                  is_admin:
                    type: boolean
                  is_super_admin:
                    type: boolean
                required:
                  - user
                  - account
                  - is_admin
                  - is_super_admin
                additionalProperties: false
  /v1/users/me/change-password:
    post:
      summary: Parola değiştir — tüm session'lar revoke edilir
      tags:
        - users
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                current_password:
                  type: string
                  minLength: 1
                  maxLength: 200
                new_password:
                  type: string
                  minLength: 12
                  maxLength: 200
                  allOf:
                    - pattern: "[A-Z]"
                    - pattern: "[a-z]"
                    - pattern: "[0-9]"
              required:
                - current_password
                - new_password
              additionalProperties: false
        required: true
      security:
        - bearerAuth: []
      responses:
        "200":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                    enum:
                      - true
                  reauth_required:
                    type: boolean
                    enum:
                      - true
                required:
                  - ok
                  - reauth_required
                additionalProperties: false
  /v1/users/me/preferences:
    get:
      summary: Kullanıcı tercihlerini döner (default ile doldurulmuş)
      tags:
        - users
      security:
        - bearerAuth: []
      responses:
        "200":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      notifications:
                        type: object
                        properties:
                          email:
                            type: boolean
                          sms:
                            type: boolean
                          weekly_digest:
                            type: boolean
                        additionalProperties: false
                      ui:
                        type: object
                        properties:
                          density:
                            type: string
                            enum:
                              - comfort
                              - pro
                          theme:
                            type: string
                            enum:
                              - light
                              - dark
                              - system
                        additionalProperties: false
                    additionalProperties: false
                required:
                  - data
                additionalProperties: false
    put:
      summary: Kullanıcı tercihlerini günceller (partial deep merge)
      tags:
        - users
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                notifications:
                  type: object
                  properties:
                    email:
                      type: boolean
                    sms:
                      type: boolean
                    weekly_digest:
                      type: boolean
                  additionalProperties: false
                ui:
                  type: object
                  properties:
                    density:
                      type: string
                      enum:
                        - comfort
                        - pro
                    theme:
                      type: string
                      enum:
                        - light
                        - dark
                        - system
                  additionalProperties: false
              additionalProperties: false
      security:
        - bearerAuth: []
      responses:
        "200":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      notifications:
                        type: object
                        properties:
                          email:
                            type: boolean
                          sms:
                            type: boolean
                          weekly_digest:
                            type: boolean
                        additionalProperties: false
                      ui:
                        type: object
                        properties:
                          density:
                            type: string
                            enum:
                              - comfort
                              - pro
                          theme:
                            type: string
                            enum:
                              - light
                              - dark
                              - system
                        additionalProperties: false
                    additionalProperties: false
                required:
                  - data
                additionalProperties: false
  /v1/users/me/delete-status:
    get:
      summary: Mevcut hesap silme talebi (yoksa null)
      tags:
        - users
      security:
        - bearerAuth: []
      responses:
        "200":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    anyOf:
                      - enum:
                          - "null"
                        nullable: true
                      - type: object
                        properties:
                          id:
                            type: string
                          status:
                            type: string
                            enum:
                              - pending_email
                              - confirmed
                              - canceled
                              - rejected
                              - completed
                          requested_at:
                            type: string
                          confirmed_at:
                            type: string
                            nullable: true
                          scheduled_for:
                            type: string
                            nullable: true
                          canceled_at:
                            type: string
                            nullable: true
                          rejection_reason:
                            type: string
                            nullable: true
                        required:
                          - id
                          - status
                          - requested_at
                          - confirmed_at
                          - scheduled_for
                          - canceled_at
                          - rejection_reason
                        additionalProperties: false
                required:
                  - data
                additionalProperties: false
  /v1/users/me/delete-request:
    post:
      summary: Hesap silme talebi başlat (parola onayı + email confirm)
      tags:
        - users
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                password:
                  type: string
                  minLength: 1
                  maxLength: 255
                reason:
                  type: string
                  maxLength: 500
              required:
                - password
              additionalProperties: false
        required: true
      security:
        - bearerAuth: []
      responses:
        "200":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                      status:
                        type: string
                        enum:
                          - pending_email
                          - confirmed
                          - canceled
                          - rejected
                          - completed
                      requested_at:
                        type: string
                      email_sent:
                        type: boolean
                    required:
                      - id
                      - status
                      - requested_at
                      - email_sent
                    additionalProperties: false
                required:
                  - data
                additionalProperties: false
  /v1/users/me/delete-confirm:
    post:
      summary: Email link token ile silme talebini onayla, 30 gün grace başlat
      tags:
        - users
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                token:
                  type: string
                  minLength: 20
                  maxLength: 128
              required:
                - token
              additionalProperties: false
        required: true
      security:
        - bearerAuth: []
      responses:
        "200":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                      status:
                        type: string
                        enum:
                          - pending_email
                          - confirmed
                          - canceled
                          - rejected
                          - completed
                      confirmed_at:
                        type: string
                      scheduled_for:
                        type: string
                    required:
                      - id
                      - status
                      - confirmed_at
                      - scheduled_for
                    additionalProperties: false
                required:
                  - data
                additionalProperties: false
  /v1/users/me/delete-cancel:
    post:
      summary: Aktif hesap silme talebini geri al (grace dönemi)
      tags:
        - users
      security:
        - bearerAuth: []
      responses:
        "200":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                      status:
                        type: string
                        enum:
                          - pending_email
                          - confirmed
                          - canceled
                          - rejected
                          - completed
                      canceled_at:
                        type: string
                    required:
                      - id
                      - status
                      - canceled_at
                    additionalProperties: false
                required:
                  - data
                additionalProperties: false
  /v1/accounts/me/master-kdf:
    get:
      summary: Master parola re-derive için salt + Argon2id parametreleri + sealed
        recovery key.
      tags:
        - accounts
      security:
        - bearerAuth: []
      responses:
        "200":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      salt:
                        type: string
                        minLength: 1
                        pattern: ^[A-Za-z0-9+/=]+$
                      params:
                        type: object
                        properties:
                          version:
                            type: integer
                            minimum: 1
                          algorithm:
                            type: string
                            enum:
                              - argon2id
                          m:
                            type: integer
                            minimum: 8192
                            maximum: 1048576
                          t:
                            type: integer
                            minimum: 1
                            maximum: 10
                          p:
                            type: integer
                            minimum: 1
                            maximum: 16
                        required:
                          - version
                          - algorithm
                          - m
                          - t
                          - p
                        additionalProperties: false
                      recovery_key_sealed:
                        type: string
                        minLength: 1
                        pattern: ^[A-Za-z0-9+/=]+$
                    required:
                      - salt
                      - params
                      - recovery_key_sealed
                    additionalProperties: false
                required:
                  - data
                additionalProperties: false
    post:
      summary: Sealed recovery key persist (bir kez set edilir).
      tags:
        - accounts
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                recovery_key_sealed:
                  type: string
                  minLength: 1
                  pattern: ^[A-Za-z0-9+/=]+$
              required:
                - recovery_key_sealed
              additionalProperties: false
        required: true
      security:
        - bearerAuth: []
      responses:
        "200":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      set_at:
                        type: string
                    required:
                      - set_at
                    additionalProperties: false
                required:
                  - data
                additionalProperties: false
  /v1/accounts/me/master-kdf-params:
    get:
      summary: Setup akışı için salt + Argon2id parametreleri (sealed yok).
      tags:
        - accounts
      security:
        - bearerAuth: []
      responses:
        "200":
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      salt:
                        type: string
                        minLength: 1
                        pattern: ^[A-Za-z0-9+/=]+$
                      params:
                        type: object
                        properties:
                          version:
                            type: integer
                            minimum: 1
                          algorithm:
                            type: string
                            enum:
                              - argon2id
                          m:
                            type: integer
                            minimum: 8192
                            maximum: 1048576
                          t:
                            type: integer
                            minimum: 1
                            maximum: 10
                          p:
                            type: integer
                            minimum: 1
                            maximum: 16
                        required:
                          - version
                          - algorithm
                          - m
                          - t
                          - p
                        additionalProperties: false
                    required:
                      - salt
                      - params
                    additionalProperties: false
                required:
                  - data
                additionalProperties: false
  /v1/accounts/me/master-unseal/status:
    get:
      tags:
        - master-unseal
      responses:
        "200":
          description: Default Response
  /v1/accounts/me/master-unseal/attempt:
    post:
      tags:
        - master-unseal
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                success:
                  type: boolean
                deviceFingerprint:
                  type: string
                  minLength: 1
                  maxLength: 64
              required:
                - success
              additionalProperties: false
        required: true
      responses:
        "200":
          description: Default Response
  /v1/accounts/me/master-unseal/recent:
    get:
      tags:
        - master-unseal
      responses:
        "200":
          description: Default Response
  /v1/accounts/me/turmob-key:
    get:
      tags:
        - accounts
      security:
        - bearerAuth: []
      responses:
        "200":
          description: Default Response
    put:
      tags:
        - accounts
      security:
        - bearerAuth: []
      responses:
        "200":
          description: Default Response
  /v1/snapshots/:
    post:
      summary: Yeni yedek meta kaydı oluşturur
      tags:
        - snapshots
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                musavir_id:
                  type: string
                  pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
                mukellef_id:
                  type: string
                  pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
                source_path:
                  type: string
                  minLength: 1
                  maxLength: 4096
                source_host:
                  type: string
                  maxLength: 200
                document_year:
                  type: integer
                  minimum: 1900
                  maximum: 2200
                document_type:
                  type: string
                  maxLength: 50
                kopia_repo_id:
                  type: string
                  maxLength: 64
                kopia_snapshot_id:
                  type: string
                  minLength: 1
                  maxLength: 64
                manifest_hash:
                  type: string
                  pattern: ^[a-f0-9]{64}$
                size_original:
                  type: integer
                  format: int64
                  minimum: 0
                size_compressed:
                  type: integer
                  format: int64
                  minimum: 0
                size_deduplicated:
                  type: integer
                  format: int64
                  minimum: 0
                file_count:
                  type: integer
                  minimum: 0
                storage_backend_id:
                  type: string
                  pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
                provider_path:
                  type: string
                  minLength: 1
                  maxLength: 2048
                started_at:
                  type: string
                  format: date-time
                completed_at:
                  type: string
                  format: date-time
                metadata:
                  type: object
                  additionalProperties: {}
              required:
                - source_path
                - kopia_snapshot_id
                - manifest_hash
                - size_original
                - size_compressed
                - size_deduplicated
                - file_count
                - provider_path
                - started_at
                - completed_at
              additionalProperties: false
        required: true
      responses:
        "200":
          description: Default Response
    get:
      summary: Yedekleri listeler
      tags:
        - snapshots
      parameters:
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: query
          name: musavir_id
          required: false
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: query
          name: mukellef_id
          required: false
        - schema:
            type: integer
            minimum: 1900
            maximum: 2200
          in: query
          name: document_year
          required: false
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: query
          name: storage_backend_id
          required: false
        - schema:
            type: integer
            exclusiveMinimum: true
            minimum: 0
            maximum: 100
          in: query
          name: limit
          required: false
      responses:
        "200":
          description: Default Response
  /v1/snapshots/{id}:
    get:
      summary: Yedek detayı
      tags:
        - snapshots
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 64
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
    delete:
      summary: Yedeği siler (retention süresi içinde 403)
      tags:
        - snapshots
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 64
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/snapshots/{id}/upload-url:
    post:
      summary: Yedek için presigned PUT URL üretir
      tags:
        - snapshots
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                key:
                  type: string
                  minLength: 1
                  maxLength: 512
                storage_backend_id:
                  type: string
                  pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
                expires_in:
                  type: integer
                  minimum: 60
                  maximum: 3600
                content_type:
                  type: string
                  maxLength: 200
              required:
                - key
              additionalProperties: false
        required: true
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 64
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/snapshots/{id}/stream:
    put:
      summary: Yedek blob'unu sunucu üzerinden backend'e yükler (presign desteklemeyen
        backend'ler için zorunlu yol).
      tags:
        - snapshots
      parameters:
        - schema:
            type: string
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
    get:
      summary: Yedek blob'unu sunucu üzerinden backend'den indirir (presign
        desteklemeyen backend'ler için zorunlu yol).
      tags:
        - snapshots
      parameters:
        - schema:
            type: string
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/snapshots/{id}/download-url:
    post:
      summary: Yedek için presigned GET URL üretir
      tags:
        - snapshots
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                key:
                  type: string
                  minLength: 1
                  maxLength: 512
                storage_backend_id:
                  type: string
                  pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
                expires_in:
                  type: integer
                  minimum: 60
                  maximum: 3600
                content_type:
                  type: string
                  maxLength: 200
              required:
                - key
              additionalProperties: false
        required: true
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 64
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/snapshots/{id}/restore-request:
    post:
      summary: Mobilden masaüstüne geri yükle isteği gönderir (24h TTL)
      tags:
        - snapshots
        - restore-requests
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                notes:
                  type: string
                  maxLength: 500
                  nullable: true
              additionalProperties: false
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 64
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/backup-jobs/presets:
    get:
      tags:
        - backup-jobs
      responses:
        "200":
          description: Default Response
  /v1/backup-jobs/:
    post:
      summary: Yeni yedek görev oluştur
      tags:
        - backup-jobs
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  minLength: 1
                  maxLength: 200
                type:
                  type: string
                  enum:
                    - folder
                    - database
                    - logo
                    - mikro
                    - eta
                    - netsis
                    - imap
                    - pst
                    - system
                    - vm
                    - disk_image
                description:
                  type: string
                  maxLength: 2000
                sources:
                  type: array
                  items:
                    anyOf:
                      - type: object
                        properties:
                          kind:
                            type: string
                            enum:
                              - folder
                          path:
                            type: string
                            minLength: 1
                            maxLength: 4096
                        required:
                          - kind
                          - path
                        additionalProperties: false
                      - type: object
                        properties:
                          kind:
                            type: string
                            enum:
                              - postgres
                              - mysql
                              - mariadb
                              - mssql
                              - sqlite
                          host:
                            type: string
                            maxLength: 200
                          port:
                            type: integer
                            minimum: 1
                            maximum: 65535
                          database:
                            type: string
                            minLength: 1
                            maxLength: 200
                          username:
                            type: string
                            maxLength: 100
                          passwordRef:
                            type: string
                            maxLength: 200
                        required:
                          - kind
                          - database
                        additionalProperties: false
                      - type: object
                        properties:
                          kind:
                            type: string
                            enum:
                              - imap
                          host:
                            type: string
                            minLength: 1
                            maxLength: 200
                          port:
                            type: integer
                            minimum: 1
                            maximum: 65535
                            default: 993
                          username:
                            type: string
                            format: email
                          ssl:
                            type: boolean
                            default: true
                          passwordRef:
                            type: string
                            maxLength: 200
                        required:
                          - kind
                          - host
                          - username
                        additionalProperties: false
                      - type: object
                        properties:
                          kind:
                            type: string
                            enum:
                              - pst
                          path:
                            type: string
                            minLength: 1
                            maxLength: 4096
                        required:
                          - kind
                          - path
                        additionalProperties: false
                      - type: object
                        properties:
                          kind:
                            type: string
                            enum:
                              - logo_tiger
                              - logo_go
                              - mikro_run
                              - mikro_fly
                              - eta_v8
                              - netsis_3
                          installPath:
                            type: string
                            minLength: 1
                            maxLength: 4096
                          database:
                            type: string
                            minLength: 1
                            maxLength: 200
                        required:
                          - kind
                          - installPath
                          - database
                        additionalProperties: false
                  minItems: 1
                  maxItems: 50
                schedule:
                  type: object
                  properties:
                    cron:
                      type: string
                      minLength: 1
                      maxLength: 100
                    timezone:
                      type: string
                      minLength: 1
                      maxLength: 60
                      default: Europe/Istanbul
                    window:
                      type: object
                      properties:
                        from:
                          type: string
                          pattern: ^\d{2}:\d{2}$
                        to:
                          type: string
                          pattern: ^\d{2}:\d{2}$
                      required:
                        - from
                        - to
                      additionalProperties: false
                      nullable: true
                    missedPolicy:
                      type: string
                      enum:
                        - run_on_startup
                        - wait_next
                        - notify
                      default: run_on_startup
                  required:
                    - cron
                  additionalProperties: false
                retention:
                  type: object
                  properties:
                    keepLatest:
                      type: integer
                      minimum: 1
                      maximum: 1000
                    keepHourly:
                      type: integer
                      minimum: 0
                      maximum: 168
                    keepDaily:
                      type: integer
                      minimum: 0
                      maximum: 3650
                    keepWeekly:
                      type: integer
                      minimum: 0
                      maximum: 520
                    keepMonthly:
                      type: integer
                      minimum: 0
                      maximum: 120
                    keepAnnual:
                      type: integer
                      minimum: 0
                      maximum: 50
                  additionalProperties: false
                bandwidth:
                  type: object
                  properties:
                    officeMbps:
                      type: number
                      minimum: 0
                      maximum: 10000
                      default: 0
                    afterHoursMbps:
                      type: number
                      minimum: 0
                      maximum: 10000
                      default: 0
                  additionalProperties: false
                excludePatterns:
                  type: array
                  items:
                    type: string
                    maxLength: 500
                  maxItems: 200
                hooks:
                  type: object
                  properties:
                    pre:
                      type: string
                      maxLength: 4096
                      nullable: true
                    post:
                      type: string
                      maxLength: 4096
                      nullable: true
                  additionalProperties: false
                tags:
                  type: array
                  items:
                    type: string
                    maxLength: 40
                  maxItems: 20
                enabled:
                  type: boolean
                  default: true
                status:
                  type: string
                  enum:
                    - active
                    - paused
                    - error
                    - draft
                  default: active
                metadata:
                  type: object
                  additionalProperties: {}
              required:
                - name
                - type
                - sources
                - schedule
              additionalProperties: false
        required: true
      responses:
        "200":
          description: Default Response
    get:
      summary: Yedek görevleri listele
      tags:
        - backup-jobs
      parameters:
        - schema:
            type: string
            enum:
              - folder
              - database
              - logo
              - mikro
              - eta
              - netsis
              - imap
              - pst
              - system
              - vm
              - disk_image
          in: query
          name: type
          required: false
        - schema:
            type: string
            enum:
              - active
              - paused
              - error
              - draft
          in: query
          name: status
          required: false
        - schema:
            type: boolean
          in: query
          name: enabled
          required: false
        - schema:
            type: string
            maxLength: 40
          in: query
          name: tag
          required: false
        - schema:
            type: string
            maxLength: 200
          in: query
          name: search
          required: false
        - schema:
            type: integer
            exclusiveMinimum: true
            minimum: 0
            maximum: 200
          in: query
          name: limit
          required: false
        - schema:
            type: integer
            minimum: 0
          in: query
          name: offset
          required: false
      responses:
        "200":
          description: Default Response
  /v1/backup-jobs/account/runs:
    get:
      summary: Tüm görevlerin çalışma geçmişi (dashboard)
      tags:
        - backup-jobs
      parameters:
        - schema:
            type: string
            enum:
              - queued
              - running
              - success
              - warning
              - failed
              - cancelled
          in: query
          name: status
          required: false
        - schema:
            type: string
            format: date-time
          in: query
          name: from
          required: false
        - schema:
            type: string
            format: date-time
          in: query
          name: to
          required: false
        - schema:
            type: integer
            exclusiveMinimum: true
            minimum: 0
            maximum: 500
          in: query
          name: limit
          required: false
        - schema:
            type: integer
            minimum: 0
          in: query
          name: offset
          required: false
      responses:
        "200":
          description: Default Response
  /v1/backup-jobs/{id}:
    get:
      summary: Yedek görev detayı
      tags:
        - backup-jobs
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 64
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
    put:
      summary: Yedek görev güncelle
      tags:
        - backup-jobs
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  minLength: 1
                  maxLength: 200
                type:
                  type: string
                  enum:
                    - folder
                    - database
                    - logo
                    - mikro
                    - eta
                    - netsis
                    - imap
                    - pst
                    - system
                    - vm
                    - disk_image
                description:
                  type: string
                  maxLength: 2000
                sources:
                  type: array
                  items:
                    anyOf:
                      - type: object
                        properties:
                          kind:
                            type: string
                            enum:
                              - folder
                          path:
                            type: string
                            minLength: 1
                            maxLength: 4096
                        required:
                          - kind
                          - path
                        additionalProperties: false
                      - type: object
                        properties:
                          kind:
                            type: string
                            enum:
                              - postgres
                              - mysql
                              - mariadb
                              - mssql
                              - sqlite
                          host:
                            type: string
                            maxLength: 200
                          port:
                            type: integer
                            minimum: 1
                            maximum: 65535
                          database:
                            type: string
                            minLength: 1
                            maxLength: 200
                          username:
                            type: string
                            maxLength: 100
                          passwordRef:
                            type: string
                            maxLength: 200
                        required:
                          - kind
                          - database
                        additionalProperties: false
                      - type: object
                        properties:
                          kind:
                            type: string
                            enum:
                              - imap
                          host:
                            type: string
                            minLength: 1
                            maxLength: 200
                          port:
                            type: integer
                            minimum: 1
                            maximum: 65535
                            default: 993
                          username:
                            type: string
                            format: email
                          ssl:
                            type: boolean
                            default: true
                          passwordRef:
                            type: string
                            maxLength: 200
                        required:
                          - kind
                          - host
                          - username
                        additionalProperties: false
                      - type: object
                        properties:
                          kind:
                            type: string
                            enum:
                              - pst
                          path:
                            type: string
                            minLength: 1
                            maxLength: 4096
                        required:
                          - kind
                          - path
                        additionalProperties: false
                      - type: object
                        properties:
                          kind:
                            type: string
                            enum:
                              - logo_tiger
                              - logo_go
                              - mikro_run
                              - mikro_fly
                              - eta_v8
                              - netsis_3
                          installPath:
                            type: string
                            minLength: 1
                            maxLength: 4096
                          database:
                            type: string
                            minLength: 1
                            maxLength: 200
                        required:
                          - kind
                          - installPath
                          - database
                        additionalProperties: false
                  minItems: 1
                  maxItems: 50
                schedule:
                  type: object
                  properties:
                    cron:
                      type: string
                      minLength: 1
                      maxLength: 100
                    timezone:
                      type: string
                      minLength: 1
                      maxLength: 60
                      default: Europe/Istanbul
                    window:
                      type: object
                      properties:
                        from:
                          type: string
                          pattern: ^\d{2}:\d{2}$
                        to:
                          type: string
                          pattern: ^\d{2}:\d{2}$
                      required:
                        - from
                        - to
                      additionalProperties: false
                      nullable: true
                    missedPolicy:
                      type: string
                      enum:
                        - run_on_startup
                        - wait_next
                        - notify
                      default: run_on_startup
                  required:
                    - cron
                  additionalProperties: false
                retention:
                  type: object
                  properties:
                    keepLatest:
                      type: integer
                      minimum: 1
                      maximum: 1000
                    keepHourly:
                      type: integer
                      minimum: 0
                      maximum: 168
                    keepDaily:
                      type: integer
                      minimum: 0
                      maximum: 3650
                    keepWeekly:
                      type: integer
                      minimum: 0
                      maximum: 520
                    keepMonthly:
                      type: integer
                      minimum: 0
                      maximum: 120
                    keepAnnual:
                      type: integer
                      minimum: 0
                      maximum: 50
                  additionalProperties: false
                bandwidth:
                  type: object
                  properties:
                    officeMbps:
                      type: number
                      minimum: 0
                      maximum: 10000
                      default: 0
                    afterHoursMbps:
                      type: number
                      minimum: 0
                      maximum: 10000
                      default: 0
                  additionalProperties: false
                excludePatterns:
                  type: array
                  items:
                    type: string
                    maxLength: 500
                  maxItems: 200
                hooks:
                  type: object
                  properties:
                    pre:
                      type: string
                      maxLength: 4096
                      nullable: true
                    post:
                      type: string
                      maxLength: 4096
                      nullable: true
                  additionalProperties: false
                tags:
                  type: array
                  items:
                    type: string
                    maxLength: 40
                  maxItems: 20
                enabled:
                  type: boolean
                  default: true
                status:
                  type: string
                  enum:
                    - active
                    - paused
                    - error
                    - draft
                  default: active
                metadata:
                  type: object
                  additionalProperties: {}
              additionalProperties: false
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 64
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
    delete:
      summary: Yedek görev sil
      tags:
        - backup-jobs
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 64
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/backup-jobs/{id}/pause:
    post:
      summary: Görevi duraklat
      tags:
        - backup-jobs
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 64
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/backup-jobs/{id}/resume:
    post:
      summary: Görevi devam ettir
      tags:
        - backup-jobs
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 64
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/backup-jobs/{id}/run:
    post:
      summary: Görevi manuel veya kuru çalıştırma ile tetikle
      tags:
        - backup-jobs
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                triggeredBy:
                  type: string
                  enum:
                    - manual
                    - dry_run
                  default: manual
              additionalProperties: false
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 64
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/backup-jobs/{id}/runs:
    get:
      summary: Görev çalışma geçmişi
      tags:
        - backup-jobs
      parameters:
        - schema:
            type: string
            enum:
              - queued
              - running
              - success
              - warning
              - failed
              - cancelled
          in: query
          name: status
          required: false
        - schema:
            type: string
            format: date-time
          in: query
          name: from
          required: false
        - schema:
            type: string
            format: date-time
          in: query
          name: to
          required: false
        - schema:
            type: integer
            exclusiveMinimum: true
            minimum: 0
            maximum: 500
          in: query
          name: limit
          required: false
        - schema:
            type: integer
            minimum: 0
          in: query
          name: offset
          required: false
        - schema:
            type: string
            minLength: 1
            maxLength: 64
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/backup-jobs/{id}/runs/{runId}/heartbeat:
    post:
      summary: Çalışan run heartbeat
      tags:
        - backup-jobs
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                bytesProcessed:
                  type: string
                  pattern: ^\d+$
                bytesUploaded:
                  type: string
                  pattern: ^\d+$
                fileCount:
                  type: integer
                  minimum: 0
              additionalProperties: false
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 64
          in: path
          name: id
          required: true
        - schema:
            type: string
            minLength: 1
            maxLength: 64
          in: path
          name: runId
          required: true
      responses:
        "200":
          description: Default Response
  /v1/backup-jobs/{id}/backup-request:
    post:
      summary: Mobilden masaüstüne yedekleme isteği gönderir (24h TTL)
      tags:
        - backup-jobs
        - backup-requests
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                notes:
                  type: string
                  maxLength: 500
                  nullable: true
              additionalProperties: false
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 64
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/backup-jobs/{id}/runs/{runId}/complete:
    post:
      summary: Run tamamlandı bildirimi
      tags:
        - backup-jobs
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                status:
                  type: string
                  enum:
                    - success
                    - warning
                    - failed
                    - cancelled
                snapshotId:
                  type: string
                  pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
                durationSec:
                  type: integer
                  minimum: 0
                bytesProcessed:
                  type: string
                  pattern: ^\d+$
                bytesUploaded:
                  type: string
                  pattern: ^\d+$
                fileCount:
                  type: integer
                  minimum: 0
                errorCount:
                  type: integer
                  minimum: 0
                  default: 0
                warningCount:
                  type: integer
                  minimum: 0
                  default: 0
                errorCode:
                  type: string
                  maxLength: 50
                errorMessage:
                  type: string
                  maxLength: 4000
                logSummary:
                  type: string
                  maxLength: 20000
              required:
                - status
                - durationSec
              additionalProperties: false
        required: true
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 64
          in: path
          name: id
          required: true
        - schema:
            type: string
            minLength: 1
            maxLength: 64
          in: path
          name: runId
          required: true
      responses:
        "200":
          description: Default Response
  /v1/devices/push-token:
    post:
      summary: Mobil cihaz push token kayıt/yenileme (upsert)
      tags:
        - devices
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                device_id:
                  type: string
                  minLength: 8
                  maxLength: 64
                platform:
                  type: string
                  enum:
                    - ios
                    - android
                    - web
                push_token:
                  type: string
                  minLength: 1
                  maxLength: 500
                  nullable: true
                push_provider:
                  type: string
                  enum:
                    - expo
                    - fcm
                    - apns
                device_label:
                  type: string
                  maxLength: 120
                  nullable: true
                app_version:
                  type: string
                  maxLength: 40
                  nullable: true
                os_version:
                  type: string
                  maxLength: 40
                  nullable: true
              required:
                - device_id
                - platform
              additionalProperties: false
        required: true
      responses:
        "200":
          description: Default Response
  /v1/devices/me:
    get:
      summary: Hesabın aktif cihazları (UI yönetim ekranı) — push_token DÖNMEZ
      tags:
        - devices
      responses:
        "200":
          description: Default Response
  /v1/devices/{deviceId}/revoke:
    post:
      summary: Cihaz push token iptal (logout)
      tags:
        - devices
      parameters:
        - schema:
            type: string
            minLength: 8
            maxLength: 64
          in: path
          name: deviceId
          required: true
      responses:
        "200":
          description: Default Response
  /v1/restore-requests/:
    get:
      summary: Hesaba ait geri yükle isteklerini listeler
      tags:
        - restore-requests
      parameters:
        - schema:
            type: string
            enum:
              - pending
              - accepted
              - rejected
              - completed
              - expired
          in: query
          name: status
          required: false
        - schema:
            type: integer
            minimum: 1
            maximum: 200
          in: query
          name: limit
          required: false
        - schema:
            type: integer
            minimum: 0
          in: query
          name: offset
          required: false
      responses:
        "200":
          description: Default Response
  /v1/restore-requests/{id}:
    get:
      summary: Tek geri yükle isteği detayını getirir (mobile polling için)
      tags:
        - restore-requests
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 40
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/restore-requests/{id}/respond:
    post:
      summary: Masaüstü kullanıcısı isteği accept/reject ile yanıtlar
      tags:
        - restore-requests
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                status:
                  type: string
                  enum:
                    - accepted
                    - rejected
                notes:
                  type: string
                  maxLength: 500
                  nullable: true
              required:
                - status
              additionalProperties: false
        required: true
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 40
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/restore-requests/{id}/complete:
    post:
      summary: Masaüstü restore tamamlandığında istek state machine accepted → completed
      tags:
        - restore-requests
      requestBody:
        content:
          application/json:
            schema:
              anyOf:
                - not: {}
                - type: object
                  properties:
                    target_dir:
                      type: string
                      maxLength: 500
                      nullable: true
                    files_restored:
                      type: integer
                      minimum: 0
                      maximum: 10000000
                      nullable: true
                    bytes_restored:
                      type: integer
                      minimum: 0
                      nullable: true
                    duration_ms:
                      type: integer
                      minimum: 0
                      nullable: true
                  additionalProperties: false
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 40
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/backup-requests/:
    get:
      summary: Hesaba ait yedek isteklerini listeler
      tags:
        - backup-requests
      parameters:
        - schema:
            type: string
            enum:
              - pending
              - accepted
              - rejected
              - completed
              - expired
          in: query
          name: status
          required: false
        - schema:
            type: integer
            minimum: 1
            maximum: 200
          in: query
          name: limit
          required: false
        - schema:
            type: integer
            minimum: 0
          in: query
          name: offset
          required: false
      responses:
        "200":
          description: Default Response
  /v1/backup-requests/{id}:
    get:
      summary: Tek yedek isteği detayını getirir (mobile polling için)
      tags:
        - backup-requests
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 40
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/backup-requests/{id}/respond:
    post:
      summary: Masaüstü kullanıcısı isteği accept/reject ile yanıtlar
      tags:
        - backup-requests
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                status:
                  type: string
                  enum:
                    - accepted
                    - rejected
                notes:
                  type: string
                  maxLength: 500
                  nullable: true
              required:
                - status
              additionalProperties: false
        required: true
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 40
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/backup-requests/{id}/complete:
    post:
      summary: Masaüstü backup tamamlandığında istek state machine accepted → completed
      tags:
        - backup-requests
      requestBody:
        content:
          application/json:
            schema:
              anyOf:
                - not: {}
                - type: object
                  properties:
                    bytes_uploaded:
                      type: integer
                      minimum: 0
                      nullable: true
                    file_count:
                      type: integer
                      minimum: 0
                      maximum: 10000000
                      nullable: true
                    duration_ms:
                      type: integer
                      minimum: 0
                      nullable: true
                  additionalProperties: false
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 40
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/notifications/sse:
    get:
      responses:
        "200":
          description: Default Response
  /v1/notifications/:
    get:
      summary: Kullanıcının in-app bildirim feed'i
      tags:
        - notifications
      parameters:
        - schema:
            type: integer
            minimum: 1
            maximum: 200
          in: query
          name: limit
          required: false
        - schema:
            type: integer
            minimum: 0
          in: query
          name: offset
          required: false
        - schema:
            type: boolean
          in: query
          name: only_unread
          required: false
      responses:
        "200":
          description: Default Response
  /v1/notifications/{id}/read:
    post:
      summary: Bildirim okundu işaretle
      tags:
        - notifications
      parameters:
        - schema:
            type: string
            minLength: 8
            maxLength: 40
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/notifications/read-all:
    post:
      summary: Tüm okunmamış bildirimleri okundu işaretle
      tags:
        - notifications
      responses:
        "200":
          description: Default Response
  /v1/notifications/preferences:
    get:
      summary: Bildirim tercih matrisi (kind × channels)
      tags:
        - notifications
      responses:
        "200":
          description: Default Response
    patch:
      summary: Bildirim tercihi güncelle (SMS/WhatsApp/Push için KVKK § 5/2 consent
        zorunlu)
      tags:
        - notifications
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                kind:
                  type: string
                  enum:
                    - backup_success
                    - backup_fail
                    - quota_warning_80
                    - quota_critical_95
                    - payment_due
                    - payment_failed
                    - payment_success
                    - subscription_expiring
                    - kvkk_request_status
                    - audit_share_otp_used
                    - transfer_completed
                    - legal_text_updated
                    - system_maintenance
                    - security_login_new_device
                    - security_anomaly_new_ip
                    - security_anomaly_new_ua
                    - security_anomaly_failed_attempts
                    - security_anomaly_superadmin_login
                channels:
                  type: array
                  items:
                    type: string
                    enum:
                      - in_app
                      - email
                      - sms
                      - whatsapp
                      - push
                  minItems: 0
                  maxItems: 5
                quiet_hours_start:
                  type: string
                  pattern: ^\d{2}:\d{2}$
                  nullable: true
                quiet_hours_end:
                  type: string
                  pattern: ^\d{2}:\d{2}$
                  nullable: true
                kvkk_consent:
                  type: boolean
              required:
                - kind
                - channels
              additionalProperties: false
        required: true
      responses:
        "200":
          description: Default Response
  /v1/notifications/categories:
    get:
      summary: Kullanıcı kategori toggle listesi (system/promo)
      tags:
        - notifications
      responses:
        "200":
          description: Default Response
    patch:
      summary: Kullanıcı kategori toggle (system+promo); security+billing KVKK § 5/2-c
        gereği kapatılamaz
      tags:
        - notifications
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                categories_disabled:
                  type: array
                  items:
                    type: string
                    enum:
                      - system
                      - promo
                  maxItems: 2
              required:
                - categories_disabled
              additionalProperties: false
        required: true
      responses:
        "200":
          description: Default Response
  /v1/webhooks/whatsapp:
    get:
      responses:
        "200":
          description: Default Response
    post:
      responses:
        "200":
          description: Default Response
  /v1/mobile-backups/:
    post:
      summary: Yeni mobil yedek başlat (galeri/rehber/SMS)
      tags:
        - mobile-backups
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                kind:
                  type: string
                  enum:
                    - media
                    - contacts
                    - sms
                total_chunks:
                  type: integer
                  minimum: 1
                  maximum: 100000
                album_label:
                  type: string
                  maxLength: 500
                  nullable: true
              required:
                - kind
                - total_chunks
              additionalProperties: false
        required: true
      responses:
        "200":
          description: Default Response
    get:
      summary: Hesabın mobil yedeklerini listeler (en yeni önce)
      tags:
        - mobile-backups
      parameters:
        - schema:
            type: integer
            minimum: 1
            maximum: 200
          in: query
          name: limit
          required: false
        - schema:
            type: integer
            minimum: 0
          in: query
          name: offset
          required: false
      responses:
        "200":
          description: Default Response
  /v1/mobile-backups/{id}/chunks/{index}:
    put:
      summary: Sealed AES-256-GCM chunk yükle (binary; X-Chunk-SHA256 header zorunlu)
      tags:
        - mobile-backups
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 40
          in: path
          name: id
          required: true
        - schema:
            type: integer
            minimum: 0
            maximum: 99999
          in: path
          name: index
          required: true
      responses:
        "200":
          description: Default Response
  /v1/mobile-backups/{id}/finalize:
    post:
      summary: Tüm chunk'lar geldikten sonra yedek tamamla (status=done)
      tags:
        - mobile-backups
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 40
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/mobile-backups/{id}:
    get:
      summary: Tek mobil yedek detayı
      tags:
        - mobile-backups
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 40
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
    delete:
      summary: Mobil yedek sil (chunk dosyaları + DB satırları)
      tags:
        - mobile-backups
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 40
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/storage/fs/{backendId}/{*}:
    put:
      parameters:
        - schema:
            type: string
          in: path
          name: backendId
          required: true
        - schema:
            type: string
          in: path
          name: "*"
          required: true
      responses:
        "200":
          description: Default Response
    get:
      parameters:
        - schema:
            type: string
          in: path
          name: backendId
          required: true
        - schema:
            type: string
          in: path
          name: "*"
          required: true
      responses:
        "200":
          description: Default Response
  /v1/admin/storage-backends/:
    post:
      summary: Yeni Hosted storage backend ekler
      tags:
        - admin
        - storage-backends
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                provider_type:
                  type: string
                  enum:
                    - filesystem
                    - s3
                    - s3_partner
                    - minio
                    - s3_compat
                    - google_drive
                    - onedrive
                    - yandex
                    - dropbox
                    - webdav
                display_name:
                  type: string
                  minLength: 1
                  maxLength: 200
                config:
                  type: object
                  additionalProperties: {}
                credentials:
                  type: object
                  additionalProperties: {}
                capacity_bytes:
                  type: integer
                  format: int64
                  minimum: 0
                kvkk_jurisdiction:
                  type: string
                  minLength: 2
                  maxLength: 2
                status:
                  type: string
                  enum:
                    - active
                    - paused
                    - draining
                    - archived
                    - auth_expired
                    - quota_exceeded
                    - error
              required:
                - provider_type
                - display_name
                - config
                - credentials
                - kvkk_jurisdiction
              additionalProperties: false
        required: true
      responses:
        "200":
          description: Default Response
    get:
      summary: Admin-owned storage backend listesi
      tags:
        - admin
        - storage-backends
      responses:
        "200":
          description: Default Response
  /v1/admin/storage-backends/{id}:
    get:
      summary: Backend detayı (credentials maskeli)
      tags:
        - admin
        - storage-backends
      parameters:
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
    patch:
      summary: Backend günceller (display_name, status, capacity, config, credentials)
      tags:
        - admin
        - storage-backends
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                display_name:
                  type: string
                  minLength: 1
                  maxLength: 200
                status:
                  type: string
                  enum:
                    - active
                    - paused
                    - draining
                    - archived
                    - auth_expired
                    - quota_exceeded
                    - error
                capacity_bytes:
                  type: integer
                  format: int64
                  minimum: 0
                  nullable: true
                config:
                  type: object
                  additionalProperties: {}
                credentials:
                  type: object
                  additionalProperties: {}
              additionalProperties: false
      parameters:
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
    delete:
      summary: Backend siler (referans varsa archive)
      tags:
        - admin
        - storage-backends
      parameters:
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/admin/storage-backends/{id}/test-connection:
    post:
      summary: Backend bağlantı testi (write/read/unlink probe)
      tags:
        - admin
        - storage-backends
      parameters:
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/admin/storage-backends/{id}/assign:
    post:
      summary: Backend'i account'lara default olarak ata
      tags:
        - admin
        - storage-backends
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                account_ids:
                  type: array
                  items:
                    type: string
                    pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
                  minItems: 1
                  maxItems: 1000
                set_as_default:
                  type: boolean
              required:
                - account_ids
              additionalProperties: false
        required: true
      parameters:
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/admin/storage-backends/{id}/usage:
    get:
      summary: Backend kullanım toplamı (snapshot count, size totals, account count)
      tags:
        - admin
        - storage-backends
      parameters:
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/admin/branding/:
    get:
      tags:
        - admin
        - branding
      responses:
        "200":
          description: Default Response
  /v1/admin/branding/upload:
    post:
      summary: Logo/sembol/favicon yükle
      tags:
        - admin
        - branding
      responses:
        "200":
          description: Default Response
  /v1/admin/branding/reset/{kind}:
    post:
      tags:
        - admin
        - branding
      parameters:
        - schema:
            type: string
          in: path
          name: kind
          required: true
      responses:
        "200":
          description: Default Response
  /v1/musavirs/:
    get:
      summary: Hesaba bağlı mali müşavir(ler)i listeler
      tags:
        - musavirs
      responses:
        "200":
          description: Default Response
    post:
      summary: Mali müşavir kaydı oluşturur (account_type=accountant, hesap başına 1)
      tags:
        - musavirs
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  minLength: 1
                  maxLength: 200
                title:
                  type: string
                  enum:
                    - SMMM
                    - YMM
                    - serbest_muhasebeci
                registration_number:
                  type: string
                  maxLength: 50
                chamber:
                  type: string
                  maxLength: 100
                signature_seal_url:
                  type: string
                  format: uri
                  maxLength: 2048
                vekil_musavir_id:
                  type: string
                  pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
              required:
                - name
                - title
              additionalProperties: false
        required: true
      responses:
        "200":
          description: Default Response
  /v1/musavirs/{id}:
    get:
      summary: Mali müşavir detayı (RLS account isolation)
      tags:
        - musavirs
      parameters:
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
    patch:
      summary: Mali müşavir günceller
      tags:
        - musavirs
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  minLength: 1
                  maxLength: 200
                title:
                  type: string
                  enum:
                    - SMMM
                    - YMM
                    - serbest_muhasebeci
                registration_number:
                  type: string
                  maxLength: 50
                chamber:
                  type: string
                  maxLength: 100
                signature_seal_url:
                  type: string
                  format: uri
                  maxLength: 2048
                vekil_musavir_id:
                  type: string
                  pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
              additionalProperties: false
      parameters:
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/musavirs/{id}/mukellefs:
    get:
      summary: Müşaviri mükelleflerini listeler (cursor pagination + filter)
      tags:
        - musavirs
        - mukelleflar
      parameters:
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: query
          name: musavir_id
          required: false
        - schema:
            type: string
            enum:
              - gercek_kisi
              - sermaye_sirketi
              - sahis_sirketi
              - kollektif
              - komandit
              - kooperatif
              - dernek
              - vakif
          in: query
          name: mukellef_type
          required: false
        - schema:
            type: string
            enum:
              - "true"
              - "false"
          in: query
          name: active
          required: false
        - schema:
            type: integer
            exclusiveMinimum: true
            minimum: 0
            maximum: 100
          in: query
          name: limit
          required: false
        - schema:
            type: string
            minLength: 1
            maxLength: 512
          in: query
          name: cursor
          required: false
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
    post:
      summary: Müşaviri için yeni mükellef ekler (KVKK § 6.2 açık rıza beyanı zorunlu)
      tags:
        - musavirs
        - mukelleflar
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                tax_id:
                  type: string
                  pattern: ^[0-9]{10,11}$
                legal_name:
                  type: string
                  minLength: 1
                  maxLength: 200
                trade_name:
                  type: string
                  maxLength: 200
                mukellef_type:
                  type: string
                  enum:
                    - gercek_kisi
                    - sermaye_sirketi
                    - sahis_sirketi
                    - kollektif
                    - komandit
                    - kooperatif
                    - dernek
                    - vakif
                contact_email:
                  type: string
                  format: email
                  maxLength: 254
                contact_phone:
                  type: string
                  maxLength: 20
                address:
                  type: string
                  maxLength: 2000
                active_from:
                  type: string
                  format: date-time
                active_until:
                  type: string
                  format: date-time
                storage_backend_id:
                  type: string
                  pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
                kvkk_consent_acknowledged:
                  type: boolean
                  enum:
                    - true
                kvkk_consent_doc_url:
                  type: string
                  format: uri
                  maxLength: 2048
                metadata:
                  type: object
                  additionalProperties: {}
              required:
                - tax_id
                - legal_name
                - mukellef_type
                - active_from
                - kvkk_consent_acknowledged
              additionalProperties: false
        required: true
      parameters:
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/mukellefs/{id}:
    get:
      summary: Mükellef detayı (RLS account isolation)
      tags:
        - mukelleflar
      parameters:
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
    patch:
      summary: Mükellef günceller (tax_id ve KVKK consent immutable — zod .omit)
      tags:
        - mukelleflar
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                legal_name:
                  type: string
                  minLength: 1
                  maxLength: 200
                trade_name:
                  type: string
                  maxLength: 200
                mukellef_type:
                  type: string
                  enum:
                    - gercek_kisi
                    - sermaye_sirketi
                    - sahis_sirketi
                    - kollektif
                    - komandit
                    - kooperatif
                    - dernek
                    - vakif
                contact_email:
                  type: string
                  format: email
                  maxLength: 254
                contact_phone:
                  type: string
                  maxLength: 20
                address:
                  type: string
                  maxLength: 2000
                active_from:
                  type: string
                  format: date-time
                active_until:
                  type: string
                  format: date-time
                storage_backend_id:
                  type: string
                  pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
                kvkk_consent_doc_url:
                  type: string
                  format: uri
                  maxLength: 2048
                metadata:
                  type: object
                  additionalProperties: {}
              additionalProperties: false
      parameters:
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
    delete:
      summary: Mükellef silme — KVKK akışı zorunlu (önce /v1/kvkk/deletion-request);
        cooldown sonu worker siler
      tags:
        - mukelleflar
      parameters:
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/mukellefs/lookup-tax-id:
    post:
      summary: F6.S5 — VKN/TCKN Bien ön sorgu (mukellef yaratmadan)
      tags:
        - mukelleflar
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                tax_id:
                  type: string
                  pattern: ^\d{10}$|^\d{11}$
              required:
                - tax_id
              additionalProperties: false
        required: true
      responses:
        "200":
          description: Default Response
  /v1/mukellefs/{id}/verify-identity:
    post:
      summary: Mukellef VKN/TCKN icin Bien API sorgu tetikle (F6.S3)
      tags:
        - mukelleflar
      parameters:
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/mukellefs/{id}/transfer:
    post:
      summary: Mukellefin baska musavire devrini baslatir (Idempotency-Key zorunlu;
        KVKK § 6.2 yeniden onay)
      tags:
        - mukelleflar
        - transfers
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                target_musavir_email:
                  type: string
                  format: email
                  maxLength: 254
                document_year_range:
                  type: array
                  minItems: 2
                  maxItems: 2
                  items:
                    - type: integer
                      minimum: 1900
                      maximum: 2200
                    - type: integer
                      minimum: 1900
                      maximum: 2200
                acknowledgement:
                  type: boolean
                  enum:
                    - true
                note:
                  type: string
                  maxLength: 2000
                consent_proof_hash:
                  type: string
                  pattern: ^[a-f0-9]{64}$
                consent_proof_path:
                  type: string
                  minLength: 1
                  maxLength: 500
              required:
                - target_musavir_email
                - acknowledgement
              additionalProperties: false
        required: true
      parameters:
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/mukellefs/{id}/transfer-consent/upload:
    post:
      summary: F6.S9 — KVKK § 6.2 devir onay belgesi yükle (PDF veya JPEG; max 5 MB)
      tags:
        - mukelleflar
        - transfers
      parameters:
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/mukellefs/{id}/efatura/heatmap:
    get:
      summary: F6.S7 — mukellef e-Belge yedek manifesti (heatmap)
      tags:
        - mukelleflar
      parameters:
        - schema:
            type: integer
            minimum: 1
            maximum: 60
          in: query
          name: months_back
          required: false
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/audit-shares/:
    get:
      summary: Hesabın oluşturduğu vergi denetimi paylaşımları (RLS isolation)
      tags:
        - audit-shares
      parameters:
        - schema: {}
          in: query
          name: not
        - schema:
            type: string
          in: query
          name: active
          required: false
      responses:
        "200":
          description: Default Response
    post:
      summary: Vergi denetimi paylaşımı oluşturur (Idempotency-Key 24h replay)
      tags:
        - audit-shares
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mukellef_id:
                  type: string
                  pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
                period_start:
                  type: string
                  format: date-time
                period_end:
                  type: string
                  format: date-time
                document_types:
                  type: array
                  items:
                    type: string
                    minLength: 1
                    maxLength: 50
                  minItems: 1
                  maxItems: 20
                auditor_email:
                  type: string
                  format: email
                  maxLength: 254
                auditor_phone:
                  type: string
                  pattern: ^\+?[0-9]{10,15}$
                auditor_name:
                  type: string
                  minLength: 1
                  maxLength: 200
                valid_for_days:
                  type: integer
                  minimum: 1
                  maximum: 30
                include_audit_trail:
                  type: boolean
              required:
                - mukellef_id
                - period_start
                - period_end
                - document_types
                - auditor_email
                - auditor_phone
                - valid_for_days
              additionalProperties: false
        required: true
      responses:
        "200":
          description: Default Response
  /v1/audit-shares/{id}:
    get:
      summary: Paylaşım detayı (RLS isolation; share_token serialize edilmez)
      tags:
        - audit-shares
      parameters:
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/audit-shares/{id}/revoke:
    post:
      summary: Paylaşımı manuel iptal eder (idempotent)
      tags:
        - audit-shares
      parameters:
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/public/audit-shares/verify:
    post:
      summary: Denetçi share_token + SMS OTP doğrulaması; dosya listesi + presigned
        URL döner
      tags:
        - audit-shares
        - public
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                share_token:
                  type: string
                  minLength: 32
                  maxLength: 256
                sms_code:
                  type: string
                  pattern: ^\d{6}$
              required:
                - share_token
                - sms_code
              additionalProperties: false
        required: true
      responses:
        "200":
          description: Default Response
  /v1/kvkk/deletion-request:
    post:
      summary: KVKK m.11 silme talebi olusturur (Idempotency-Key zorunlu, 24h replay;
        30 gun cooldown)
      tags:
        - kvkk
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                request_type:
                  type: string
                  enum:
                    - deletion
                    - data_export
                    - rectification
                    - access
                scope:
                  type: object
                  properties:
                    target:
                      type: string
                      enum:
                        - account
                        - mukellefs
                        - period
                    mukellef_ids:
                      type: array
                      items:
                        type: string
                        pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
                      maxItems: 1000
                    period_start:
                      type: string
                      format: date-time
                    period_end:
                      type: string
                      format: date-time
                    document_types:
                      type: array
                      items:
                        type: string
                        minLength: 1
                        maxLength: 50
                  required:
                    - target
                  additionalProperties: false
                acknowledgement:
                  type: boolean
                  enum:
                    - true
                reason:
                  type: string
                  maxLength: 2000
              required:
                - request_type
                - scope
                - acknowledgement
              additionalProperties: false
        required: true
      responses:
        "200":
          description: Default Response
  /v1/kvkk/deletion-requests:
    get:
      summary: Hesabin KVKK taleplerini listeler (RLS isolation)
      tags:
        - kvkk
      responses:
        "200":
          description: Default Response
  /v1/kvkk/deletion-request/{id}:
    get:
      summary: KVKK talebi detay (RLS isolation)
      tags:
        - kvkk
      parameters:
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/kvkk/deletion-request/{id}/cancel:
    post:
      summary: Bekleyen KVKK silme talebini iptal eder (cooldown icinde)
      tags:
        - kvkk
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                reason:
                  type: string
                  maxLength: 2000
              additionalProperties: false
      parameters:
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/kvkk/deletion-certificate/{id}:
    get:
      summary: KVKK Silme Sertifikasi presigned download URL (sadece status=completed
        taleplerde)
      tags:
        - kvkk
      parameters:
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/kvkk/data-export-request:
    post:
      summary: "KVKK m.11 veri tasinabilirligi talebi (Faz 4 worker; bu Faz: kayit +
        status=pending)"
      tags:
        - kvkk
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                request_type:
                  type: string
                  enum:
                    - deletion
                    - data_export
                    - rectification
                    - access
                scope:
                  type: object
                  properties:
                    target:
                      type: string
                      enum:
                        - account
                        - mukellefs
                        - period
                    mukellef_ids:
                      type: array
                      items:
                        type: string
                        pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
                      maxItems: 1000
                    period_start:
                      type: string
                      format: date-time
                    period_end:
                      type: string
                      format: date-time
                    document_types:
                      type: array
                      items:
                        type: string
                        minLength: 1
                        maxLength: 50
                  required:
                    - target
                  additionalProperties: false
                acknowledgement:
                  type: boolean
                  enum:
                    - true
                reason:
                  type: string
                  maxLength: 2000
              required:
                - request_type
                - scope
                - acknowledgement
              additionalProperties: false
        required: true
      responses:
        "200":
          description: Default Response
  /v1/transfers/:
    get:
      summary: Hesabin source veya target oldugu devirler (RLS isolation)
      tags:
        - transfers
      parameters:
        - schema: {}
          in: query
          name: not
        - schema:
            type: string
            enum:
              - pending
              - accepted
              - in_progress
              - completed
              - rejected
              - cancelled
          in: query
          name: status
          required: false
      responses:
        "200":
          description: Default Response
  /v1/transfers/{id}:
    get:
      summary: Devir detayi (source veya target erisebilir)
      tags:
        - transfers
      parameters:
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/transfers/{id}/accept:
    post:
      summary: Target musavir devri kabul eder (KVKK § 6.2 yeniden onay)
      tags:
        - transfers
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                acknowledgement:
                  type: boolean
                  enum:
                    - true
                signature:
                  type: string
                  minLength: 1
                  maxLength: 512
              required:
                - acknowledgement
              additionalProperties: false
        required: true
      parameters:
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/transfers/{id}/reject:
    post:
      summary: Devri reddeder (source veya target)
      tags:
        - transfers
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                reason:
                  type: string
                  maxLength: 2000
              additionalProperties: false
      parameters:
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/transfers/{id}/cancel:
    post:
      summary: Devri iptal eder (sadece source musavir)
      tags:
        - transfers
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                reason:
                  type: string
                  maxLength: 2000
              additionalProperties: false
      parameters:
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/oauth/google-drive/authorize:
    post:
      summary: Google Drive OAuth flow başlatır — authorize URL döner
      tags:
        - oauth
        - google-drive
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                return_url:
                  type: string
                  format: uri
              additionalProperties: false
      responses:
        "200":
          description: Default Response
  /v1/oauth/google-drive/callback:
    get:
      summary: Google OAuth callback — code+state exchange + storage_backend create
      tags:
        - oauth
        - google-drive
      parameters:
        - schema:
            type: string
          in: query
          name: code
          required: false
        - schema:
            type: string
          in: query
          name: state
          required: false
        - schema:
            type: string
          in: query
          name: error
          required: false
        - schema:
            type: string
          in: query
          name: error_description
          required: false
      responses:
        "200":
          description: Default Response
  /v1/oauth/google-drive/revoke:
    post:
      summary: Google Drive bağlantısını kaldırır — token revoke + backend delete
      tags:
        - oauth
        - google-drive
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                backend_id:
                  type: string
                  pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
              required:
                - backend_id
              additionalProperties: false
        required: true
      responses:
        "200":
          description: Default Response
  /v1/oauth/onedrive/authorize:
    post:
      summary: OneDrive OAuth flow başlatır — authorize URL döner
      tags:
        - oauth
        - onedrive
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                return_url:
                  type: string
                  format: uri
              additionalProperties: false
      responses:
        "200":
          description: Default Response
  /v1/oauth/onedrive/callback:
    get:
      summary: Microsoft OAuth callback — code+state exchange + storage_backend create
      tags:
        - oauth
        - onedrive
      parameters:
        - schema:
            type: string
          in: query
          name: code
          required: false
        - schema:
            type: string
          in: query
          name: state
          required: false
        - schema:
            type: string
          in: query
          name: error
          required: false
        - schema:
            type: string
          in: query
          name: error_description
          required: false
      responses:
        "200":
          description: Default Response
  /v1/oauth/onedrive/revoke:
    post:
      summary: OneDrive bağlantısını kaldırır — token revoke + backend delete
      tags:
        - oauth
        - onedrive
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                backend_id:
                  type: string
                  pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
              required:
                - backend_id
              additionalProperties: false
        required: true
      responses:
        "200":
          description: Default Response
  /v1/storage-backends/:
    get:
      summary: Kullanıcının BYOS backend listesi
      tags:
        - storage-backends
      responses:
        "200":
          description: Default Response
  /v1/storage-backends/{id}:
    get:
      summary: BYOS backend detayı
      tags:
        - storage-backends
      parameters:
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
    patch:
      summary: Görünen adı düzenle
      tags:
        - storage-backends
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                display_name:
                  type: string
                  minLength: 1
                  maxLength: 200
              required:
                - display_name
              additionalProperties: false
        required: true
      parameters:
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
    delete:
      summary: Backend kaldır + OAuth token revoke
      tags:
        - storage-backends
      parameters:
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/storage-backends/{id}/set-default:
    post:
      summary: Bu backend'i hesap için varsayılan yap (paket kısıtı uygulanır)
      tags:
        - storage-backends
      parameters:
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/storage-backends/{id}/test-connection:
    post:
      summary: Backend bağlantı testi (about.get / read-write probe)
      tags:
        - storage-backends
      parameters:
        - schema:
            type: string
            pattern: ^[a-z]+_[0-9A-HJKMNP-TV-Z]{26}$
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/billing/plans:
    get:
      summary: Hesap türüne uygun plan listesi
      tags:
        - billing
      responses:
        "200":
          description: Default Response
  /v1/billing/subscription:
    get:
      summary: Mevcut abonelik
      tags:
        - billing
      responses:
        "200":
          description: Default Response
  /v1/billing/subscribe:
    post:
      summary: Abonelik ödeme akışı başlat
      tags:
        - billing
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                plan_code:
                  type: string
                  minLength: 1
                  maxLength: 40
                return_url:
                  type: string
                  format: uri
              required:
                - plan_code
              additionalProperties: false
        required: true
      responses:
        "200":
          description: Default Response
  /v1/billing/cancel:
    post:
      summary: Abonelik iptal işaretle
      tags:
        - billing
      responses:
        "200":
          description: Default Response
  /v1/billing/undo-cancel:
    post:
      summary: Abonelik iptal geri al
      tags:
        - billing
      responses:
        "200":
          description: Default Response
  /v1/billing/usage:
    get:
      summary: Hesap depolama kullanımı + quota
      tags:
        - billing
      responses:
        "200":
          description: Default Response
  /v1/billing/invoices:
    get:
      summary: Fatura listesi
      tags:
        - billing
      responses:
        "200":
          description: Default Response
  /v1/billing/callback/paynkolay:
    post:
      tags:
        - billing
      responses:
        "200":
          description: Default Response
  /v1/billing/callback/paytr:
    post:
      tags:
        - billing
      responses:
        "200":
          description: Default Response
  /v1/billing/callback/iyzico:
    post:
      tags:
        - billing
      responses:
        "200":
          description: Default Response
  /v1/applications:
    post:
      summary: Başvuru/kayıt formu — KVKK rıza + GSM OTP doğrulama zorunlu
      tags:
        - applications
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                type:
                  type: string
                  enum:
                    - musavir
                    - bireysel
                    - kurumsal
                    - pilot
                    - test-kullanici
                package_code:
                  type: string
                  maxLength: 40
                name:
                  type: string
                  minLength: 2
                  maxLength: 200
                email:
                  type: string
                  format: email
                  maxLength: 255
                phone:
                  type: string
                  minLength: 10
                  maxLength: 20
                company_name:
                  type: string
                  maxLength: 255
                vkn_tckn:
                  type: string
                  pattern: ^[0-9]{10,11}$
                musavir_license_no:
                  type: string
                  maxLength: 40
                mukellef_count_estimate:
                  type: integer
                  minimum: 0
                  maximum: 100000
                address:
                  type: string
                  maxLength: 2000
                city:
                  type: string
                  maxLength: 80
                message:
                  type: string
                  maxLength: 2000
                kvkk_consent:
                  type: boolean
                  enum:
                    - true
                marketing_consent:
                  type: boolean
                  default: false
                consents:
                  type: array
                  items:
                    type: object
                    properties:
                      slug:
                        type: string
                        minLength: 1
                        maxLength: 60
                      version:
                        type: string
                        minLength: 1
                        maxLength: 20
                      updated_at:
                        type: string
                        maxLength: 40
                      confirmed_at:
                        type: string
                        format: date-time
                      required:
                        type: boolean
                    required:
                      - slug
                      - version
                      - updated_at
                      - confirmed_at
                      - required
                    additionalProperties: false
                  maxItems: 20
                utm_source:
                  type: string
                  maxLength: 120
                utm_medium:
                  type: string
                  maxLength: 120
                utm_campaign:
                  type: string
                  maxLength: 120
              required:
                - type
                - name
                - email
                - phone
                - kvkk_consent
              additionalProperties: false
        required: true
      responses:
        "200":
          description: Default Response
  /v1/auth/sms-otp/request:
    post:
      summary: SMS doğrulama kodu iste (6 haneli, 5 dk TTL)
      tags:
        - auth
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                phone:
                  type: string
                  minLength: 10
                  maxLength: 20
                purpose:
                  type: string
                  enum:
                    - application
                    - login
                    - phone-change
                    - pilot:invite
                  default: application
              required:
                - phone
              additionalProperties: false
        required: true
      responses:
        "200":
          description: Default Response
  /v1/auth/sms-otp/verify:
    post:
      summary: SMS doğrulama kodunu doğrula
      tags:
        - auth
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                phone:
                  type: string
                  minLength: 10
                  maxLength: 20
                code:
                  type: string
                  minLength: 6
                  maxLength: 6
                purpose:
                  type: string
                  enum:
                    - application
                    - login
                    - phone-change
                    - pilot:invite
                  default: application
              required:
                - phone
                - code
              additionalProperties: false
        required: true
      responses:
        "200":
          description: Default Response
  /v1/admin/sms-providers:
    get:
      responses:
        "200":
          description: Default Response
  /v1/admin/sms-providers/{code}:
    patch:
      parameters:
        - schema:
            type: string
          in: path
          name: code
          required: true
      responses:
        "200":
          description: Default Response
  /v1/admin/sms-providers/{code}/set-default:
    post:
      parameters:
        - schema:
            type: string
          in: path
          name: code
          required: true
      responses:
        "200":
          description: Default Response
  /v1/test-user-feedback/:
    post:
      summary: Pilot 30g programı haftalık geri bildirim — KVKK rıza zorunlu
      tags:
        - pilot
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                pilot_code:
                  type: string
                  pattern: ^PIL-[A-Z0-9]{4}-[A-Z0-9]{4,8}$
                week_number:
                  type: integer
                  minimum: 1
                  maximum: 4
                nps_score:
                  type: integer
                  minimum: 0
                  maximum: 10
                usage_days:
                  type: integer
                  minimum: 0
                  maximum: 7
                most_used_flow:
                  type: string
                  enum:
                    - snapshot
                    - restore
                    - mukellef
                    - paylasim
                    - devir
                    - fatura
                    - byos
                    - diger
                had_blocking_bug:
                  type: boolean
                bug_description:
                  type: string
                  maxLength: 2000
                open_response_1:
                  type: string
                  maxLength: 2000
                open_response_2:
                  type: string
                  maxLength: 2000
                open_response_3:
                  type: string
                  maxLength: 2000
                berhan_note:
                  type: string
                  maxLength: 2000
                kvkk_consent:
                  type: boolean
                  enum:
                    - true
              required:
                - pilot_code
                - week_number
                - kvkk_consent
              additionalProperties: false
        required: true
      responses:
        "200":
          description: Default Response
  /v1/admin/test-user-feedback/:
    get:
      responses:
        "200":
          description: Default Response
  /v1/pilot-feedback/:
    post:
      summary: Pilot 30g programı haftalık geri bildirim — KVKK rıza zorunlu
      tags:
        - pilot
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                pilot_code:
                  type: string
                  pattern: ^PIL-[A-Z0-9]{4}-[A-Z0-9]{4,8}$
                week_number:
                  type: integer
                  minimum: 1
                  maximum: 4
                nps_score:
                  type: integer
                  minimum: 0
                  maximum: 10
                usage_days:
                  type: integer
                  minimum: 0
                  maximum: 7
                most_used_flow:
                  type: string
                  enum:
                    - snapshot
                    - restore
                    - mukellef
                    - paylasim
                    - devir
                    - fatura
                    - byos
                    - diger
                had_blocking_bug:
                  type: boolean
                bug_description:
                  type: string
                  maxLength: 2000
                open_response_1:
                  type: string
                  maxLength: 2000
                open_response_2:
                  type: string
                  maxLength: 2000
                open_response_3:
                  type: string
                  maxLength: 2000
                berhan_note:
                  type: string
                  maxLength: 2000
                kvkk_consent:
                  type: boolean
                  enum:
                    - true
              required:
                - pilot_code
                - week_number
                - kvkk_consent
              additionalProperties: false
        required: true
      responses:
        "200":
          description: Default Response
  /v1/admin/pilot-feedback/:
    get:
      responses:
        "200":
          description: Default Response
  /v1/admin/applications:
    get:
      responses:
        "200":
          description: Default Response
  /v1/admin/applications/{id}:
    get:
      parameters:
        - schema:
            type: string
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
    patch:
      parameters:
        - schema:
            type: string
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/admin/applications/{id}/invite:
    post:
      parameters:
        - schema:
            type: string
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/admin/applications/{id}/convert:
    post:
      parameters:
        - schema:
            type: string
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/admin/users:
    get:
      responses:
        "200":
          description: Default Response
  /v1/admin/users/{id}/phone:
    post:
      parameters:
        - schema:
            type: string
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
    delete:
      parameters:
        - schema:
            type: string
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/admin/users/{id}/2fa/reset:
    post:
      parameters:
        - schema:
            type: string
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/admin/users/invite:
    post:
      responses:
        "200":
          description: Default Response
  /v1/admin/accounts:
    get:
      responses:
        "200":
          description: Default Response
  /v1/admin/accounts/{id}:
    get:
      parameters:
        - schema:
            type: string
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/admin/accounts/{id}/suspend:
    post:
      parameters:
        - schema:
            type: string
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/admin/accounts/{id}/unsuspend:
    post:
      parameters:
        - schema:
            type: string
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/admin/accounts/{id}/reset-password:
    post:
      parameters:
        - schema:
            type: string
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/admin/accounts/{id}/integrations/bien-token:
    put:
      parameters:
        - schema:
            type: string
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/admin/announcements/kvkk-section-10:
    post:
      responses:
        "200":
          description: Default Response
  /v1/admin/audit:
    get:
      responses:
        "200":
          description: Default Response
  /v1/admin/audit/users-resolve:
    post:
      responses:
        "200":
          description: Default Response
  /v1/admin/audit/export.csv:
    get:
      responses:
        "200":
          description: Default Response
  /v1/admin/test-users/:
    get:
      responses:
        "200":
          description: Default Response
  /v1/admin/test-users/stats:
    get:
      responses:
        "200":
          description: Default Response
  /v1/admin/test-users/{id}:
    get:
      parameters:
        - schema:
            type: string
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/admin/test-users/generate:
    post:
      responses:
        "200":
          description: Default Response
  /v1/admin/test-users/{id}/issue:
    post:
      parameters:
        - schema:
            type: string
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/admin/test-users/{id}/revoke:
    post:
      parameters:
        - schema:
            type: string
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/admin/pilots/:
    get:
      responses:
        "200":
          description: Default Response
  /v1/admin/pilots/stats:
    get:
      responses:
        "200":
          description: Default Response
  /v1/admin/pilots/{id}:
    get:
      parameters:
        - schema:
            type: string
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/admin/pilots/generate:
    post:
      responses:
        "200":
          description: Default Response
  /v1/admin/pilots/{id}/issue:
    post:
      parameters:
        - schema:
            type: string
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/admin/pilots/{id}/revoke:
    post:
      parameters:
        - schema:
            type: string
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/admin/health:
    get:
      summary: Sistem sağlık panosu — admin only (component + KPI)
      tags:
        - admin
      responses:
        "200":
          description: Default Response
  /v1/admin/queue-stats:
    get:
      summary: BullMQ queue durum panosu (14 queue paralel)
      tags:
        - admin
      responses:
        "200":
          description: Default Response
  /v1/admin/accounts/{id}/integrations/efatura:
    put:
      parameters:
        - schema:
            type: string
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
    get:
      parameters:
        - schema:
            type: string
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/admin/efatura/run-once:
    post:
      responses:
        "200":
          description: Default Response
  /v1/admin/efatura/snapshots/{id}:
    delete:
      parameters:
        - schema:
            type: string
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/admin/backup-wizards:
    get:
      responses:
        "200":
          description: Default Response
    post:
      responses:
        "200":
          description: Default Response
  /v1/admin/backup-wizards/{id}:
    get:
      parameters:
        - schema:
            type: string
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
    put:
      parameters:
        - schema:
            type: string
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
    delete:
      parameters:
        - schema:
            type: string
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/admin/backup-wizards/{id}/test:
    post:
      parameters:
        - schema:
            type: string
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/admin/backup-wizards/{id}/run-once:
    post:
      parameters:
        - schema:
            type: string
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/admin/security/alerts:
    get:
      responses:
        "200":
          description: Default Response
  /v1/admin/security/locks:
    get:
      responses:
        "200":
          description: Default Response
  /v1/admin/security/locks/{id}/release:
    post:
      parameters:
        - schema:
            type: string
          in: path
          name: id
          required: true
      responses:
        "200":
          description: Default Response
  /v1/admin/security/admins/promote:
    post:
      responses:
        "200":
          description: Default Response
  /v1/admin/security/admins/demote:
    post:
      responses:
        "200":
          description: Default Response
  /v1/admin/security/sweep-run-once:
    post:
      responses:
        "200":
          description: Default Response
  /v1/admin/notification-policy:
    get:
      summary: Tenant bildirim politikası (account-level override)
      tags:
        - admin
        - notifications
      responses:
        "200":
          description: Default Response
    put:
      summary: Tenant policy güncelle (owner veya SuperAdmin)
      tags:
        - admin
        - notifications
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                force_off_channels:
                  type: array
                  items:
                    type: string
                    enum:
                      - in_app
                      - email
                      - sms
                      - whatsapp
                      - push
                  maxItems: 5
                force_on_kinds:
                  type: array
                  items:
                    type: string
                    enum:
                      - backup_success
                      - backup_fail
                      - quota_warning_80
                      - quota_critical_95
                      - payment_due
                      - payment_failed
                      - payment_success
                      - subscription_expiring
                      - kvkk_request_status
                      - audit_share_otp_used
                      - transfer_completed
                      - legal_text_updated
                      - system_maintenance
                      - security_login_new_device
                      - security_anomaly_new_ip
                      - security_anomaly_new_ua
                      - security_anomaly_failed_attempts
                      - security_anomaly_superadmin_login
                  maxItems: 20
                categories_disabled:
                  type: array
                  items:
                    type: string
                    enum:
                      - security
                      - billing
                      - system
                      - promo
                  maxItems: 4
                max_email_per_hour:
                  type: integer
                  minimum: 0
                  maximum: 10000
                max_sms_per_hour:
                  type: integer
                  minimum: 0
                  maximum: 1000
                max_whatsapp_per_hour:
                  type: integer
                  minimum: 0
                  maximum: 1000
                max_push_per_hour:
                  type: integer
                  minimum: 0
                  maximum: 10000
              required:
                - force_off_channels
                - force_on_kinds
                - categories_disabled
                - max_email_per_hour
                - max_sms_per_hour
                - max_whatsapp_per_hour
                - max_push_per_hour
              additionalProperties: false
        required: true
      responses:
        "200":
          description: Default Response
  /v1/admin/whatsapp/status:
    get:
      responses:
        "200":
          description: Default Response
  /v1/admin/whatsapp/qr:
    get:
      responses:
        "200":
          description: Default Response
  /v1/admin/whatsapp/test-send:
    post:
      responses:
        "200":
          description: Default Response
  /v1/admin/whatsapp/disconnect:
    post:
      responses:
        "200":
          description: Default Response
  /v1/admin/whatsapp/restart:
    post:
      responses:
        "200":
          description: Default Response
servers:
  - url: https://api.pratikyedek.com
    description: production
