openapi: 3.0.3
info:
  title: Spot gateway
  description: API request/response types and OpenAI-compatible shapes
  license:
    name: MIT
  version: 1.0.0
paths:
  /v1/chat/completions:
    post:
      tags:
      - crate
      operationId: chat_completions
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ChatCompletionRequest'
        required: true
      responses:
        '200':
          description: OpenAI-compatible completion
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChatCompletionResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorBody'
      security:
      - bearer_buyer: []
  /v1/sellers/{id}/asks:
    post:
      tags:
      - crate
      operationId: submit_ask
      parameters:
      - name: id
        in: path
        description: Seller id
        required: true
        schema:
          type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubmitAskRequest'
        required: true
      responses:
        '200':
          description: Resting ask
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubmitAskResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorBody'
      security:
      - x_seller_api_key: []
  /v1/sellers/{id}/capacity:
    post:
      tags:
      - crate
      operationId: report_capacity
      parameters:
      - name: id
        in: path
        description: Seller id
        required: true
        schema:
          type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ReportCapacityRequest'
        required: true
      responses:
        '200':
          description: Capacity snapshot
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReportCapacityResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorBody'
      security:
      - x_seller_api_key: []
components:
  schemas:
    ChatChoice:
      type: object
      description: One choice in a chat completion response.
      required:
      - index
      - message
      properties:
        finish_reason:
          type: string
          description: Why generation stopped (for example `"stop"`).
          nullable: true
        index:
          type: integer
          format: int32
          description: Zero-based index among choices.
          minimum: 0
        message:
          $ref: '#/components/schemas/ChatMessage'
    ChatCompletionRequest:
      type: object
      description: OpenAI-compatible chat completion request body.
      required:
      - model
      - messages
      properties:
        max_price:
          type: string
          description: Maximum price per 1,000 tokens the buyer will pay, if any.
          nullable: true
        messages:
          type: array
          items:
            $ref: '#/components/schemas/ChatMessage'
          description: Conversation so far.
        model:
          type: string
          description: Model identifier.
        stream:
          type: boolean
          description: When `true`, the server should stream tokens. Streaming itself is later work.
          nullable: true
    ChatCompletionResponse:
      type: object
      description: OpenAI-compatible chat completion response body.
      required:
      - id
      - object
      - created
      - model
      - choices
      properties:
        choices:
          type: array
          items:
            $ref: '#/components/schemas/ChatChoice'
          description: Generated choices.
        created:
          type: integer
          format: int64
          description: Unix timestamp (seconds).
        id:
          type: string
          description: Completion identifier.
        model:
          type: string
          description: Model that produced the completion.
        object:
          type: string
          description: Object type, typically `"chat.completion"`.
        usage:
          allOf:
          - $ref: '#/components/schemas/Usage'
          nullable: true
    ChatMessage:
      type: object
      description: A single message in a chat completion.
      required:
      - role
      - content
      properties:
        content:
          type: string
          description: Message text.
        role:
          $ref: '#/components/schemas/ChatRole'
    ChatRole:
      type: string
      description: Role of a chat message, matching OpenAI's public names.
      enum:
      - system
      - user
      - assistant
    ErrorBody:
      type: object
      required:
      - code
      - message
      properties:
        code:
          type: string
          description: Wire error code.
        message:
          type: string
          description: Human-readable detail.
    ReportCapacityRequest:
      type: object
      description: |-
        Body of `POST /v1/sellers/{id}/capacity`.

        Informational only — updates the seller's capacity profile for the
        dashboard. It never creates asks or touches the order book. Token counts are
        `u64`, so non-negativity is enforced by the type and zero is a valid report.
      required:
      - model_id
      - available_tokens
      - queued_tokens
      properties:
        available_tokens:
          type: integer
          format: int64
          description: Tokens the seller can serve right now.
          minimum: 0
        model_id:
          type: string
          description: Model / instrument the capacity applies to.
        queued_tokens:
          type: integer
          format: int64
          description: Tokens currently queued / committed.
          minimum: 0
    ReportCapacityResponse:
      type: object
      description: Response for `POST /v1/sellers/{id}/capacity`.
      required:
      - seller_id
      - model_id
      - available_tokens
      - queued_tokens
      - reported_at
      properties:
        available_tokens:
          type: integer
          format: int64
          description: Tokens the seller can serve right now (echoed).
          minimum: 0
        model_id:
          type: string
          description: Model / instrument the capacity applies to.
        queued_tokens:
          type: integer
          format: int64
          description: Tokens currently queued / committed (echoed).
          minimum: 0
        reported_at:
          type: string
          description: When the profile was recorded.
        seller_id:
          type: string
          description: Seller the profile belongs to.
    SubmitAskRequest:
      type: object
      description: Body of `POST /v1/sellers/{id}/asks`.
      required:
      - model_id
      - price
      - capacity
      properties:
        capacity:
          type: integer
          format: int64
          description: Token capacity offered. Must be strictly positive.
          minimum: 0
        model_id:
          type: string
          description: Model / instrument this ask offers. Must be in the seller's models.
        price:
          type: string
          description: Ask limit price per 1000 tokens. Must be strictly positive.
        ttl_seconds:
          type: integer
          format: int64
          description: Time-to-live in seconds. Defaults to 300 (5 minutes) when omitted.
          nullable: true
          minimum: 0
    SubmitAskResponse:
      type: object
      description: Response for `POST /v1/sellers/{id}/asks`.
      required:
      - ask_id
      - seller_id
      - model_id
      - price
      - capacity
      - remaining
      - created_at
      - expires_at
      properties:
        ask_id:
          type: string
          description: Newly created ask identifier.
        capacity:
          type: integer
          format: int64
          description: Token capacity offered.
          minimum: 0
        created_at:
          type: string
          description: When the ask was accepted.
        expires_at:
          type: string
          description: When the ask will expire if not refreshed or cancelled.
        model_id:
          type: string
          description: Model / instrument offered.
        price:
          type: string
          description: Ask limit price per 1000 tokens.
        remaining:
          type: integer
          format: int64
          description: Unfilled token quantity (equals `capacity` at creation).
          minimum: 0
        seller_id:
          type: string
          description: Seller that owns the ask.
    Usage:
      type: object
      description: Token accounting on an OpenAI-compatible completion.
      required:
      - prompt_tokens
      - completion_tokens
      - total_tokens
      properties:
        completion_tokens:
          type: integer
          format: int32
          description: Tokens generated in the completion.
          minimum: 0
        prompt_tokens:
          type: integer
          format: int32
          description: Tokens consumed from the prompt.
          minimum: 0
        total_tokens:
          type: integer
          format: int32
          description: '`prompt_tokens + completion_tokens`.'
          minimum: 0
  securitySchemes:
    bearer_buyer:
      type: http
      scheme: bearer
    x_seller_api_key:
      type: apiKey
      in: header
      name: X-Seller-API-Key
