openapi: 3.1.0
info:
  title: altinapps API
  version: "1.0.0"
  summary: Türk altın ve döviz için REST API.
  description: |
    `altinapps` platformu iki paralel ürün sunar:

    - **data-api** (`/data-api/v1/*`) — dev'ler için Bearer API key auth, çoklu sembol REST.
      Public docs: <https://www.altinapps.com/docs/api>
    - **woo-gold** (`/woo-gold/v1/*`) — WooCommerce eklentisi için lisans + domain whitelist auth.
      Doğrudan REST entegrasyonu hedeflenmez; eklenti kullanılır.

    57 normalize sembol (altın çeşitleri + döviz pariteleri).

    ## Hızlı başlangıç

    1. <https://www.altinapps.com/giris> magic-link ile kayıt
    2. <https://www.altinapps.com/panel/data-api> Free key oluştur (1.000 istek/ay, 10 popüler sembol)
    3. `curl https://api.altinapps.com/data-api/v1/prices -H "Authorization: Bearer ala_..."`

    ## Auth modelleri
    Her endpoint kendi auth şemasını belirtir; bir Bearer key sadece kendi ürün
    namespace'inde çalışır (data-api key woo-gold endpoint'ine erişemez ve tersi).

    ## Rate limit
    Her yanıtta `X-RateLimit-Limit` ve `X-RateLimit-Remaining` header'ları döner.
    Aşıldığında `429` + `Retry-After` saniye.
  contact:
    name: altinapps destek
    email: info@altinapps.com
    url: https://www.altinapps.com
  license:
    name: Ticari
    url: https://www.altinapps.com
  termsOfService: https://www.altinapps.com

servers:
  - url: https://api.altinapps.com
    description: Üretim

tags:
  - name: data-api
    description: |
      Bearer API key auth (veya RapidAPI marketplace proxy). Self-service Free
      key panel üzerinden anında üretilir. Per-customer N key
      (production/staging/dev environment ayrımı).
  - name: woo-gold
    description: |
      Lisans (Bearer) + domain whitelist auth. WordPress eklentisi tarafından
      kullanılır; direct REST entegrasyonu önerilmez.
  - name: public
    description: Auth gerektirmeyen sistem endpoint'leri.

paths:
  # ---------------- public ----------------
  /health:
    get:
      tags: [public]
      summary: Sağlık kontrolü
      security: []
      responses:
        "200":
          description: Servis ayakta
          content:
            application/json:
              schema:
                type: object
                properties:
                  status: { type: string, example: ok }

  /public/stats:
    get:
      tags: [public]
      summary: Public stats — uptime, son tick, sembol sayıları, paket limitleri
      description: |
        Status sayfasının canlı feed'i. Auth gerekmez; 15 saniye edge cache.
      security: []
      responses:
        "200":
          description: Stats
          headers:
            Cache-Control:
              schema: { type: string, example: "public, max-age=15, s-maxage=15, stale-while-revalidate=60" }
          content:
            application/json:
              schema: { $ref: "#/components/schemas/PublicStats" }

  /public/products:
    get:
      tags: [public]
      summary: Aktif ürünler + paketler (pricing sayfası feed)
      description: Multi-currency (TRY/USD). DB'den okur — pricing sayfası dinamik.
      security: []
      responses:
        "200":
          description: Ürün katalog
          content:
            application/json:
              schema:
                type: object
                properties:
                  products:
                    type: array
                    items: { $ref: "#/components/schemas/ProductCatalog" }

  # ---------------- data-api ----------------
  /data-api/v1/prices:
    get:
      tags: [data-api]
      summary: Tüm aktif sembollerin anlık fiyatı
      description: |
        Paketinize göre filtreli sembol listesi:
        - **Free**: 10 popüler sembol (ALTIN, AYAR22, AYAR14, CEYREK_YENI, KULCEALTIN, USDTRY, EURTRY, GBPTRY, XAUUSD, EURUSD)
        - **Pro / Kurumsal**: 43 sembol (altın, sarrafiye, döviz, metaller)

        Sembolün cevapta yer almama nedenleri: paket erişim sınırı, veya
        symbol henüz ilk tick gelmedi (yeni ingestor restart sonrası birkaç saniye).
      security:
        - apiKey: []
      responses:
        "200":
          description: Fiyat listesi
          headers:
            X-RateLimit-Limit:
              schema: { type: integer }
              description: Dakikalık istek limiti (paket bazlı)
            X-RateLimit-Remaining:
              schema: { type: integer }
              description: Bu dakikada kalan istek hakkı
          content:
            application/json:
              schema:
                type: object
                properties:
                  prices:
                    type: array
                    items: { $ref: "#/components/schemas/Price" }
        "401": { $ref: "#/components/responses/Unauthorized" }
        "403": { $ref: "#/components/responses/Forbidden" }
        "429": { $ref: "#/components/responses/RateLimited" }
        "503": { $ref: "#/components/responses/Unavailable" }

  /data-api/v1/prices/{symbol}:
    get:
      tags: [data-api]
      summary: Tek sembolün anlık fiyatı
      security:
        - apiKey: []
      parameters:
        - name: symbol
          in: path
          required: true
          description: Sembol kodu. Tam liste için `GET /data-api/v1/symbols`.
          schema:
            type: string
            examples: [ALTIN, XAUUSD, USDTRY, EURUSD, GUMTRY]
      responses:
        "200":
          description: Sembol fiyatı
          headers:
            X-RateLimit-Limit:
              schema: { type: integer }
            X-RateLimit-Remaining:
              schema: { type: integer }
          content:
            application/json:
              schema: { $ref: "#/components/schemas/Price" }
        "401": { $ref: "#/components/responses/Unauthorized" }
        "403":
          description: |
            Sembol paketinizde değil (Free → 10 popüler sembol).
          content:
            application/json:
              schema: { $ref: "#/components/schemas/Error" }
        "404": { $ref: "#/components/responses/NotFound" }
        "429": { $ref: "#/components/responses/RateLimited" }
        "503": { $ref: "#/components/responses/Unavailable" }

  /data-api/v1/symbols:
    get:
      tags: [data-api]
      summary: Paketinize göre erişilebilir sembol listesi
      description: |
        Currency interpret edilmez; dev sembol adından çıkarsar (TRY altın çeşitleri, USD döviz
        pareleri, EUR XAUEUR vb.). Fiyatlar her zaman sembolün kendi para
        birimindedir; conversion yapılmaz.
      security:
        - apiKey: []
      responses:
        "200":
          description: Sembol listesi
          content:
            application/json:
              schema:
                type: object
                properties:
                  symbols:
                    type: array
                    items: { $ref: "#/components/schemas/SymbolInfo" }
        "401": { $ref: "#/components/responses/Unauthorized" }
        "429": { $ref: "#/components/responses/RateLimited" }

  # ---------------- woo-gold (sadece referans) ----------------
  /woo-gold/v1/prices:
    get:
      tags: [woo-gold]
      summary: Lisanslı eklenti için fiyat (paket tazeliğinde)
      description: |
        WordPress eklentisi tarafından çağrılır. Direct entegrasyon önerilmez;
        data-api tercih edin.
      security:
        - licenseKey: []
      parameters:
        - $ref: "#/components/parameters/siteURL"
      responses:
        "200":
          description: Fiyat (paket tazelik granülaritesi uygulanır)
          content:
            application/json:
              schema: { $ref: "#/components/schemas/PriceWooGold" }
        "401": { $ref: "#/components/responses/Unauthorized" }
        "403": { $ref: "#/components/responses/Forbidden" }
        "429": { $ref: "#/components/responses/RateLimited" }
        "503": { $ref: "#/components/responses/Unavailable" }

  /woo-gold/v1/sites/activate:
    post:
      tags: [woo-gold]
      summary: Domain'i lisansa aktive et (whitelist kurulumu)
      security:
        - licenseKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [site_url]
              properties:
                site_url:
                  type: string
                  example: https://magaza.example.com
      responses:
        "200":
          description: Aktive edildi
          content:
            application/json:
              schema:
                type: object
                properties:
                  activated: { type: boolean }
                  site: { type: string }
                  max_domains: { type: integer }
        "400": { $ref: "#/components/responses/BadRequest" }
        "401": { $ref: "#/components/responses/Unauthorized" }
        "403":
          description: Domain limiti dolu veya lisans uygun değil
          content:
            application/json:
              schema: { $ref: "#/components/schemas/Error" }

components:
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      bearerFormat: ala_*
      description: |
        data-api Bearer key. Panel'den oluşturulur (`/panel/data-api`).
        Format: `ala_<43 karakter>`. SHA-256 hash DB'de saklanır; plain key
        yalnızca oluşturulduğu anda gösterilir.

        ```
        Authorization: Bearer ala_AbCdEfGhIjKlMnOpQrStUvWxYz0123456789...
        ```

        ## Marketplace proxy (RapidAPI)
        Eğer altinapps'i RapidAPI üzerinden tüketiyorsanız RapidAPI proxy
        Bearer header'ı yerine `X-RapidAPI-Proxy-Secret` ile imzalanır;
        kullanıcı doğrulamasını RapidAPI yapar. Sizden hiçbir header
        beklenmez — RapidAPI normal "Connect" akışı çalışır.

        > CORS: data-api endpoint'leri `Access-Control-Allow-Origin: *` ile
        > yayında — RapidAPI playground / browser test araçları çalışır.

    licenseKey:
      type: http
      scheme: bearer
      bearerFormat: ala_*
      description: |
        woo-gold lisans anahtarı. WooCommerce eklenti ayarlarından girilir.
        Aynı format ile data-api key, fakat ürün-namespace bağlı: bir key
        sadece kendi ürün path'ine erişebilir.

  parameters:
    siteURL:
      name: X-Site-URL
      in: header
      required: true
      description: |
        İsteğin geldiği WordPress site adresi. Lisansa aktive edilmiş domain ile
        eşleşmelidir; bilinmeyen domain paket limiti uygunsa otomatik aktive edilir.
      schema:
        type: string
        example: https://magaza.example.com

  schemas:
    Price:
      type: object
      description: |
        data-api Price — anlık tick, paket tazeliği uygulanmaz.
        Currency interpret edilmez; dev sembol adından çıkarsar
        (XAUUSD → USD; ALTIN → TL standart konvansiyon).
      properties:
        symbol:
          type: string
          example: ALTIN
        alis:
          type: number
          example: 6676.90
          description: Alış fiyatı (sembolün birimi).
        satis:
          type: number
          example: 6809.08
          description: Satış fiyatı.
        as_of:
          type: string
          format: date-time
          example: "2026-05-31T10:14:23.512Z"
          description: Tick'in altinapps sistemine ulaştığı an (UTC).
      required: [symbol, alis, satis, as_of]

    PriceWooGold:
      type: object
      description: woo-gold endpoint yanıtı — eklenti tazelik + reverse-trial bilgisi içerir.
      allOf:
        - $ref: "#/components/schemas/Price"
        - type: object
          properties:
            market_status:
              type: string
              enum: [live, closed, stale, unknown]
              description: live=canlı; closed=piyasa kapalı; stale=akış arızası.
            effective_package:
              type: string
              enum: [free, pro, kurumsal]
              description: Reverse-trial sırasında Free lisans 'pro' olarak görünür.
          required: [market_status, effective_package]

    SymbolInfo:
      type: object
      properties:
        symbol:
          type: string
          example: ALTIN
      required: [symbol]

    PackageSummary:
      type: object
      properties:
        code: { type: string, enum: [free, pro, kurumsal] }
        monthly_cap:
          type: integer
          description: Aylık istek limiti (0 = sınırsız/adil kullanım)
        rate_limit_rpm:
          type: integer
          description: Dakikalık istek limiti (RPM)
        symbols:
          type: integer
          description: Erişilebilir sembol sayısı
      required: [code, monthly_cap, rate_limit_rpm, symbols]

    PublicStats:
      type: object
      properties:
        uptime_sec: { type: integer, example: 86400 }
        started_at: { type: string, format: date-time }
        market_status: { type: string, enum: [live, closed, stale, unknown] }
        last_tick_at: { type: string, format: date-time }
        last_tick_age_sec:
          type: integer
          description: Son tick'in kaç saniye önce alındığı (negatifse 0'a sıkıştırılır).
        symbols_active:
          type: integer
          description: Toplam allowlist boyutu (Pro/Kurumsal'a açık)
        symbols_live_now:
          type: integer
          description: Şu an Redis'te price'ı olan sembol sayısı
        packages:
          type: array
          items: { $ref: "#/components/schemas/PackageSummary" }
      required: [uptime_sec, started_at, market_status, last_tick_age_sec, symbols_active, symbols_live_now]

    ProductCatalog:
      type: object
      properties:
        code: { type: string, examples: [woo-gold, data-api] }
        name: { type: string }
        status: { type: string, example: active }
        packages:
          type: array
          items:
            type: object
            properties:
              code: { type: string, enum: [free, pro, kurumsal] }
              freshness_sec: { type: integer }
              rate_limit_rpm: { type: integer }
              max_domains: { type: integer }
              monthly_cap: { type: integer }
              currency: { type: string, enum: [TRY, USD] }
              price_try: { type: number }
              price_usd: { type: number }
      required: [code, name, status, packages]

    Error:
      type: object
      properties:
        error:
          type: string
          example: "geçersiz API key"
      required: [error]

  responses:
    BadRequest:
      description: Geçersiz istek
      content:
        application/json:
          schema: { $ref: "#/components/schemas/Error" }
    Unauthorized:
      description: API key eksik veya geçersiz
      content:
        application/json:
          schema: { $ref: "#/components/schemas/Error" }
    Forbidden:
      description: |
        Erişim reddedildi. Olası nedenler:
        - Key bu ürün için değil (woo-gold key → data-api endpoint)
        - Key revoke edildi
        - Sembol paketinizde değil (Free → 10 popüler sembol)
        - Domain whitelist uyuşmazlığı (woo-gold)
      content:
        application/json:
          schema: { $ref: "#/components/schemas/Error" }
    NotFound:
      description: Bilinmeyen sembol veya kaynak
      content:
        application/json:
          schema: { $ref: "#/components/schemas/Error" }
    RateLimited:
      description: İstek limiti aşıldı (dakikalık veya aylık)
      headers:
        Retry-After:
          schema: { type: integer }
          description: Tekrar denemeden önce beklenecek saniye
      content:
        application/json:
          schema: { $ref: "#/components/schemas/Error" }
    Unavailable:
      description: |
        Fiyat verisi geçici olarak yok. Olası nedenler:
        - Upstream veri akışı geçici kesintide (otomatik recover ≤30sn)
        - Servisin restart anı (semboller dakikalar içinde dolar)
        - Sembol henüz hiç tick almadı (ingestor cold start)
      content:
        application/json:
          schema: { $ref: "#/components/schemas/Error" }
