openapi: 3.1.0
info:
  title: Garlic Private Inference API
  version: 1.0.0
  description: |
    OpenAI-compatible private inference. Use a base model name for standard
    JSON or prefix it with `tee-` for an explicit confidential-compute
    contract. Paid API E2EE is disabled until Garlic can authenticate all
    provider-visible billing metadata. Signed-in browser chat remains E2EE.
  contact:
    name: Garlic
    url: https://garlic.ai/api
servers:
  - url: https://garlic.ai
    description: Garlic API
security:
  - bearerAuth: []
tags:
  - name: Models
  - name: Text
paths:
  /v1/models:
    get:
      operationId: listModels
      tags: [Models]
      summary: List models available to paid API clients
      responses:
        "200":
          description: Executable standard and TEE model aliases
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ModelList"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "429":
          $ref: "#/components/responses/RateLimited"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
  /v1/models/{model}:
    get:
      operationId: retrieveModel
      tags: [Models]
      summary: Retrieve an available paid model alias
      parameters:
        - in: path
          name: model
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Model
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Model"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/UnsupportedEndpoint"
        "429":
          $ref: "#/components/responses/RateLimited"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
  /v1/chat/completions:
    post:
      operationId: createChatCompletion
      tags: [Text]
      summary: Create an OpenAI-compatible chat completion
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ChatCompletionRequest"
      responses:
        "200":
          description: Completion or server-sent event stream
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
            text/event-stream:
              schema:
                type: string
        "400":
          description: Invalid or unsupported request metadata.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "402":
          $ref: "#/components/responses/BillingRequired"
        "413":
          description: The JSON request exceeded Garlic's application limit.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "422":
          description: Paid E2EE is not available.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "429":
          $ref: "#/components/responses/RateLimited"
        "502":
          $ref: "#/components/responses/UpstreamUnavailable"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: A revocable Garlic personal key or WorkOS organization key.
  responses:
    Unauthorized:
      description: The Garlic API key is missing, invalid, or revoked.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    BillingRequired:
      description: The selected owner lacks enough prepaid balance for the request ceiling.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    UnsupportedEndpoint:
      description: The path, method, or model is not in the paid API surface.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    RateLimited:
      description: The request rate limit was exceeded.
      headers:
        Retry-After:
          schema:
            type: integer
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    UpstreamUnavailable:
      description: The private inference backend was unavailable.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    ServiceUnavailable:
      description: Billing, identity, or another fail-closed dependency was unavailable.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
  schemas:
    ChatCompletionRequest:
      type: object
      additionalProperties: true
      required: [model, messages]
      properties:
        model:
          type: string
          description: A base or `tee-` model alias returned by GET /v1/models.
          examples: [gpt-oss-120b, tee-gpt-oss-120b]
        messages:
          type: array
          items:
            type: object
            required: [role, content]
            properties:
              role:
                type: string
                enum: [system, developer, user, assistant, tool]
              content: {}
            additionalProperties: true
        max_completion_tokens:
          type: integer
          minimum: 1
        max_tokens:
          type: integer
          minimum: 1
        n:
          type: integer
          minimum: 1
          maximum: 8
        stream:
          type: boolean
        tools:
          type: array
          items:
            type: object
            additionalProperties: true
    Model:
      type: object
      required: [id, object, owned_by, garlic]
      properties:
        id:
          type: string
        object:
          type: string
          const: model
        owned_by:
          type: string
          const: garlic
        garlic:
          type: object
          additionalProperties: true
    ModelList:
      type: object
      required: [data, object]
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/Model"
        object:
          type: string
          const: list
    Error:
      type: object
      required: [error]
      properties:
        error:
          type: object
          required: [code, message, type]
          properties:
            code:
              type: string
            message:
              type: string
            type:
              type: string
