openapi: "3.1.0"
info:
  title: Cocoon Platform API
  version: "0.1.0"
  description: |
    Paid API proxy for the Cocoon decentralized AI network on TON blockchain.
    Provides OpenAI-compatible chat completions with per-token billing and TON cryptocurrency payments.

    ## Authentication
    Most endpoints require a Bearer token (API key) in the Authorization header.
    API keys use the `ck_` prefix. Create one via POST /v1/keys or POST /api/register.

    ## Billing
    Usage is billed per-token with separate rates for prompt, completion, reasoning, and cached tokens.
    A 1.5x markup is applied over Cocoon network costs. Balance is prepaid via TON deposits.

    ## Quick Start
    1. Create an API key: `POST /api/register`
    2. Deposit TON to the provided wallet with your deposit code as memo
    3. Query AI models: `POST /v1/chat/completions` with your API key
  contact:
    name: Cocoon Platform
    url: https://cocoon.knyazevai.work
  license:
    name: Proprietary

servers:
  - url: https://cocoon.knyazevai.work
    description: Production server

paths:
  /v1/chat/completions:
    post:
      operationId: createChatCompletion
      summary: Create a chat completion
      description: |
        Send messages to an AI model and receive a response. Supports streaming and non-streaming modes.
        Use when you need to query AI models (e.g., Qwen/Qwen3-32B) through the Cocoon network.
        Requires a funded API key. Cost is deducted from balance after completion based on token usage.
      tags: [AI Inference]
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [model, messages]
              properties:
                model:
                  type: string
                  description: "Model ID to use. Get available models from GET /v1/models."
                  example: "Qwen/Qwen3-32B"
                messages:
                  type: array
                  description: "Conversation messages in OpenAI chat format."
                  items:
                    type: object
                    required: [role, content]
                    properties:
                      role:
                        type: string
                        enum: [system, user, assistant]
                        description: "Message role."
                      content:
                        type: string
                        description: "Message text content."
                  example:
                    - role: user
                      content: "What is the TON blockchain?"
                stream:
                  type: boolean
                  default: false
                  description: "If true, response is streamed as server-sent events."
                max_tokens:
                  type: integer
                  description: "Maximum tokens to generate. Capped at 128000."
                  maximum: 128000
                temperature:
                  type: number
                  description: "Sampling temperature (0-2). Higher = more creative."
                  minimum: 0
                  maximum: 2
            example:
              model: "Qwen/Qwen3-32B"
              messages:
                - role: user
                  content: "Explain smart contracts in one paragraph."
              stream: false
              max_tokens: 1000
      responses:
        "200":
          description: Chat completion response
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                  object:
                    type: string
                    enum: [chat.completion]
                  model:
                    type: string
                  choices:
                    type: array
                    items:
                      type: object
                      properties:
                        index:
                          type: integer
                        message:
                          type: object
                          properties:
                            role:
                              type: string
                            content:
                              type: string
                        finish_reason:
                          type: string
                  usage:
                    $ref: "#/components/schemas/Usage"
              example:
                id: "chatcmpl-abc123"
                object: "chat.completion"
                model: "Qwen/Qwen3-32B"
                choices:
                  - index: 0
                    message:
                      role: assistant
                      content: "Smart contracts are self-executing programs..."
                    finish_reason: stop
                usage:
                  prompt_tokens: 12
                  completion_tokens: 45
                  total_tokens: 57
        "400":
          description: Invalid request (missing model or messages)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              example:
                error:
                  message: "model and messages are required"
                  type: invalid_request_error
                  param: null
                  code: null
        "401":
          description: Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              example:
                error:
                  message: "Invalid API key"
                  type: invalid_auth
                  param: null
                  code: invalid_api_key
        "402":
          description: Insufficient balance
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              example:
                error:
                  message: "Insufficient balance: 0.0000 TON. Minimum: 0.01 TON. Top up via /v1/deposit."
                  type: insufficient_balance
                  param: null
                  code: insufficient_balance
        "422":
          description: Validation error (malformed request body)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ValidationError"
              example:
                detail:
                  - loc: [body, model]
                    msg: "Field required"
                    type: "missing"

  /v1/completions:
    post:
      operationId: createCompletion
      summary: Create a text completion
      description: |
        Send a text prompt to an AI model and receive a text completion. Use for models without chat templates,
        such as ByteDance-Seed/Seed-X-PPO-7B (translation model, 50+ languages).
        For Seed-X-PPO-7B, use prompt format: "Translate the following [source] sentence into [target]: [text] <lang_code>"
        where lang_code is e.g. <zh>, <en>, <de>, <fr>, <es>, <ja>, <ko>, <ru>.
        Requires a funded API key. Cost is deducted from balance after completion based on token usage.
      tags: [AI Inference]
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [model, prompt]
              properties:
                model:
                  type: string
                  description: "Model ID to use. Get available models from GET /v1/models."
                  example: "ByteDance-Seed/Seed-X-PPO-7B"
                prompt:
                  type: string
                  description: "Text prompt to complete."
                  example: "Translate the following English sentence into Chinese: Hello, how are you? <zh>"
                stream:
                  type: boolean
                  default: false
                  description: "If true, response is streamed as server-sent events."
                max_tokens:
                  type: integer
                  description: "Maximum tokens to generate. Capped at 128000."
                  maximum: 128000
                temperature:
                  type: number
                  description: "Sampling temperature (0-2)."
                  minimum: 0
                  maximum: 2
            example:
              model: "ByteDance-Seed/Seed-X-PPO-7B"
              prompt: "Translate the following English sentence into Chinese: Hello, how are you? <zh>"
              max_tokens: 100
      responses:
        "200":
          description: Text completion response
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                  object:
                    type: string
                    enum: [text_completion]
                  model:
                    type: string
                  choices:
                    type: array
                    items:
                      type: object
                      properties:
                        index:
                          type: integer
                        text:
                          type: string
                        finish_reason:
                          type: string
                  usage:
                    $ref: "#/components/schemas/Usage"
              example:
                id: "cmpl-abc123"
                object: "text_completion"
                model: "ByteDance-Seed/Seed-X-PPO-7B"
                choices:
                  - index: 0
                    text: "你好，你好吗？"
                    finish_reason: stop
                usage:
                  prompt_tokens: 14
                  completion_tokens: 5
                  total_tokens: 19
        "400":
          description: Invalid request (missing model or prompt)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "402":
          description: Insufficient balance
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /v1/models:
    get:
      operationId: listModels
      summary: List available AI models
      description: |
        Returns all AI models currently available on the Cocoon network with worker counts and load information.
        Use to discover which models can be queried via /v1/chat/completions or /v1/completions. No authentication required.
      tags: [AI Inference]
      responses:
        "200":
          description: List of available models
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                          description: "Model identifier to use in completions."
                        owned_by:
                          type: string
                          description: "Organization that created the model."
                        endpoint:
                          type: string
                          description: "API endpoint to use for this model (/v1/chat/completions or /v1/completions)."
                        type:
                          type: string
                          enum: [chat, translation]
                          description: "Model type: 'chat' for conversational models, 'translation' for translation models."
                        context_window:
                          type: integer
                          nullable: true
                          description: "Maximum context window in tokens."
                        workers:
                          type: array
                          description: "Worker nodes serving this model."
                          items:
                            type: object
                            properties:
                              running_requests:
                                type: integer
                              max_running_requests:
                                type: integer
              example:
                data:
                  - id: "Qwen/Qwen3-32B"
                    owned_by: "Alibaba"
                    endpoint: "/v1/chat/completions"
                    type: "chat"
                    context_window: 131072
                    workers:
                      - running_requests: 2
                        max_running_requests: 8
                  - id: "ByteDance-Seed/Seed-X-PPO-7B"
                    owned_by: "ByteDance"
                    endpoint: "/v1/completions"
                    type: "translation"
                    context_window: 8192
                    workers:
                      - running_requests: 5
                        max_running_requests: 60

  /v1/keys:
    post:
      operationId: createApiKey
      summary: Create a new API key
      description: |
        Creates a new user account with an API key and deposit code. Returns the plaintext API key (shown only once).
        Use when programmatically provisioning access. Requires admin token if COCOON_ADMIN_TOKEN is set.
      tags: [Authentication]
      security:
        - bearerAuth: []
      responses:
        "201":
          description: API key created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiKeyResponse"
              example:
                api_key: "ck_a1b2c3d4e5f6..."
                deposit_code: "xK9mN2pQ"
                balance_ton: 0.0
                created_at: "2026-03-23T10:00:00Z"
        "403":
          description: Admin token required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /v1/balance:
    get:
      operationId: getBalance
      summary: Check account balance
      description: |
        Returns the current TON balance for the authenticated user.
        Use to check if you have sufficient funds before making AI queries.
      tags: [Billing]
      security:
        - bearerAuth: []
      responses:
        "200":
          description: Current balance
          content:
            application/json:
              schema:
                type: object
                properties:
                  balance_ton:
                    type: number
                    description: "Balance in TON (1 TON = 1e9 nanoton)."
                  balance_nanoton:
                    type: integer
                    description: "Balance in nanotons (smallest unit)."
                  balance_usd:
                    type: number
                    nullable: true
                    description: "Balance in USD (based on current TON/USD rate)."
                  ton_usd_rate:
                    type: number
                    nullable: true
                    description: "Current TON/USD exchange rate used for conversion."
              example:
                balance_ton: 1.5
                balance_nanoton: 1500000000
                balance_usd: 1.95
                ton_usd_rate: 1.302
        "401":
          $ref: "#/components/responses/Unauthorized"

  /v1/deposit:
    get:
      operationId: getDepositInfo
      summary: Get deposit instructions
      description: |
        Returns the TON wallet address and unique memo code for depositing funds.
        Send TON to the wallet with the memo/comment to credit your account. Deposits are detected within ~30 seconds.
      tags: [Billing]
      security:
        - bearerAuth: []
      responses:
        "200":
          description: Deposit instructions
          content:
            application/json:
              schema:
                type: object
                properties:
                  wallet:
                    type: string
                    description: "TON wallet address to send funds to."
                  memo:
                    type: string
                    description: "Unique memo/comment to include with your TON transfer."
                  instructions:
                    type: string
                    description: "Human-readable deposit instructions."
              example:
                wallet: "EQAv6GynfX6rrRlbNjYHpa5Mz1UDE61s5VPg-TN8sBFeR9Sp"
                memo: "xK9mN2pQ"
                instructions: "Send TON to EQAv6GynfX6rrRlbNjYHpa5Mz1UDE61s5VPg-TN8sBFeR9Sp with the comment/memo: xK9mN2pQ. Your balance will be credited automatically within ~30 seconds."
        "401":
          $ref: "#/components/responses/Unauthorized"

  /api/register:
    post:
      operationId: registerUser
      summary: Register a new user
      description: |
        Creates a new user account and returns API key, deposit code, and deposit wallet address.
        Use for self-service registration. The API key is shown only once — store it securely.
      tags: [Authentication]
      responses:
        "200":
          description: Registration successful
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/ApiKeyResponse"
                  - type: object
                    properties:
                      deposit_wallet:
                        type: string
                        description: "TON wallet address for deposits."

  /api/login:
    post:
      operationId: loginUser
      summary: Verify API key and get user info
      description: |
        Validates an API key and returns the associated user balance, deposit code, and deposit wallet.
        Use to check if an API key is valid and retrieve account details.
      tags: [Authentication]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [api_key]
              properties:
                api_key:
                  type: string
                  description: "API key to verify (with ck_ prefix)."
            example:
              api_key: "ck_a1b2c3d4e5f6..."
      responses:
        "200":
          description: Valid API key
          content:
            application/json:
              schema:
                type: object
                properties:
                  balance_ton:
                    type: number
                  deposit_code:
                    type: string
                  deposit_wallet:
                    type: string
        "401":
          description: Invalid API key
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/stats:
    get:
      operationId: getNetworkStats
      summary: Get live network statistics
      description: |
        Returns real-time Cocoon network statistics including available models, worker counts, and load.
        Uses caching — returns last known state if upstream is temporarily offline. No authentication required.
      tags: [Network]
      responses:
        "200":
          description: Network stats
          content:
            application/json:
              schema:
                type: object
                properties:
                  models:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        workers:
                          type: integer
                        running:
                          type: integer
                        capacity:
                          type: integer
                        load_pct:
                          type: number
                  status:
                    type: string
                    enum: [online, cached, offline]
                    description: "'online' = fresh data, 'cached' = stale but last known, 'offline' = no data."
                  cached_at:
                    type: string
                    format: date-time
                    nullable: true
              example:
                models:
                  - id: "Qwen/Qwen3-32B"
                    workers: 3
                    running: 5
                    capacity: 24
                    load_pct: 20.8
                status: "online"
                cached_at: "2026-03-23T10:00:00Z"

  /v1/pricing:
    get:
      operationId: getPricing
      summary: Get pricing information
      description: |
        Returns machine-readable pricing details including per-token rates for all token types, markup multiplier, and minimum balance requirements.
        Use to estimate costs before making AI queries. No authentication required.
      tags: [Billing]
      responses:
        "200":
          description: Pricing information
          content:
            application/json:
              schema:
                type: object
                properties:
                  currency:
                    type: string
                    enum: [TON]
                  unit:
                    type: string
                    enum: [nanoton]
                  nanoton_per_ton:
                    type: integer
                    example: 1000000000
                  markup_multiplier:
                    type: number
                    example: 1.5
                  rates:
                    type: object
                    properties:
                      prompt_token:
                        $ref: "#/components/schemas/TokenRate"
                      completion_token:
                        $ref: "#/components/schemas/TokenRate"
                      reasoning_token:
                        $ref: "#/components/schemas/TokenRate"
                      cached_prompt_token:
                        $ref: "#/components/schemas/TokenRate"
                  minimum_balance_ton:
                    type: number
                    example: 0.01
                  maximum_overdraft_ton:
                    type: number
                    example: 0.05
                  payment_method:
                    type: string

  /health:
    get:
      operationId: healthCheck
      summary: Health check
      description: |
        Returns service health status. Use for monitoring and uptime checks. Always returns 200 if the service is running.
      tags: [System]
      responses:
        "200":
          description: Service is healthy
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    enum: [ok]
                  version:
                    type: string
                  service:
                    type: string
              example:
                status: "ok"
                version: "0.1.0"
                service: "cocoon-platform"

components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: "API key with `ck_` prefix. Obtain via POST /api/register or POST /v1/keys."

  schemas:
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            message:
              type: string
              description: "Human-readable error description."
            type:
              type: string
              description: "Error category."
              enum: [invalid_request_error, invalid_auth, insufficient_balance, auth_error, server_error]
            param:
              type: string
              nullable: true
              description: "Parameter that caused the error, if applicable."
            code:
              type: string
              nullable: true
              description: "Machine-readable error code."
              enum: [invalid_api_key, insufficient_balance, forbidden, internal_error]

    ValidationError:
      type: object
      description: "FastAPI validation error response (422)."
      properties:
        detail:
          type: array
          items:
            type: object
            properties:
              loc:
                type: array
                items:
                  oneOf:
                    - type: string
                    - type: integer
                description: "Path to the field that caused the error."
              msg:
                type: string
                description: "Human-readable error message."
              type:
                type: string
                description: "Error type identifier."

    Usage:
      type: object
      description: "Token usage statistics for billing."
      properties:
        prompt_tokens:
          type: integer
          description: "Number of tokens in the prompt."
        completion_tokens:
          type: integer
          description: "Number of tokens in the completion."
        total_tokens:
          type: integer
          description: "Total tokens (prompt + completion)."

    TokenRate:
      type: object
      properties:
        base_nanoton:
          type: integer
          description: "Base price per token in nanoton before multiplier."
        multiplier:
          type: number
          description: "Token type multiplier."
        effective_nanoton:
          type: integer
          description: "Final price per token in nanoton (base * multiplier * markup)."

    ApiKeyResponse:
      type: object
      properties:
        api_key:
          type: string
          description: "Plaintext API key (shown only once). Starts with 'ck_'."
        deposit_code:
          type: string
          description: "Unique code to include as memo in TON deposits."
        balance_ton:
          type: number
          description: "Current balance in TON."
        created_at:
          type: string
          format: date-time
          description: "Account creation timestamp."

  responses:
    Unauthorized:
      description: Invalid or missing API key
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          example:
            error:
              message: "Invalid API key"
              type: invalid_auth
              param: null
              code: invalid_api_key

tags:
  - name: AI Inference
    description: "Query AI models on the Cocoon decentralized network."
  - name: Authentication
    description: "Create and manage API keys."
  - name: Billing
    description: "Check balance and deposit TON for usage."
  - name: Network
    description: "Cocoon network status and statistics."
  - name: System
    description: "Platform health and operational endpoints."
