openapi: "3.1.0"
info:
  title: Qpher Tenant API
  description: Tenant management — create tenants and manage API keys.
  version: "1.1.0"
  contact:
    name: Qpher Support
    url: https://qpher.ai/support
    email: support@qpher.ai

servers:
  - url: https://api.qpher.ai
    description: Production

security:
  - apiKey: []

paths:
  /api/v1/tenants:
    post:
      operationId: createTenant
      summary: Create a new tenant
      description: |
        Create a new tenant with the specified name and plan.
        Returns the tenant details including the API key (shown only once).
      tags: [Tenants]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [name, plan]
              properties:
                name:
                  type: string
                  minLength: 1
                  maxLength: 255
                  description: Tenant display name
                  example: Acme Corp
                plan:
                  type: string
                  enum: [free, starter, growth, pro, enterprise]
                  description: Pricing plan tier
                  example: starter
      responses:
        "201":
          description: Tenant created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TenantCreateResponse"
        "400":
          $ref: "#/components/responses/BadRequest"
        "409":
          $ref: "#/components/responses/Conflict"

  /api/v1/tenants/{id}:
    get:
      operationId: getTenant
      summary: Get tenant details
      description: Returns tenant details. Does not include the API key.
      tags: [Tenants]
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
          description: Tenant ID
          example: 550e8400-e29b-41d4-a716-446655440000
      responses:
        "200":
          description: Tenant details
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TenantResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"

  /api/v1/tenants/{id}/api-keys/rotate:
    post:
      operationId: rotateApiKey
      summary: Rotate tenant API key
      description: |
        Create a new API key and revoke the old one.
        The new key is shown only once in the response.
        There is a brief concurrent window where both keys work.
      tags: [Tenants]
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
          description: Tenant ID
          example: 550e8400-e29b-41d4-a716-446655440000
      responses:
        "200":
          description: API key rotated
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiKeyRotateResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/RateLimited"

components:
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: X-API-Key

  schemas:
    TenantCreateResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            id:
              type: string
              format: uuid
              example: 550e8400-e29b-41d4-a716-446655440000
            name:
              type: string
              example: Acme Corp
            plan:
              type: string
              example: starter
            status:
              type: string
              example: active
            api_key:
              type: string
              description: API key (shown ONCE — store securely)
              example: qph_live_abc123def456ghi789
            created_at:
              type: string
              format: date-time
              example: "2026-01-15T10:30:00.000Z"
        request_id:
          type: string
          format: uuid
          example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
        timestamp:
          type: string
          format: date-time
          example: "2026-01-15T10:30:00.000Z"

    TenantResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            id:
              type: string
              format: uuid
              example: 550e8400-e29b-41d4-a716-446655440000
            name:
              type: string
              example: Acme Corp
            plan:
              type: string
              example: starter
            status:
              type: string
              example: active
            created_at:
              type: string
              format: date-time
              example: "2026-01-15T10:30:00.000Z"
            updated_at:
              type: string
              format: date-time
              example: "2026-01-15T10:30:00.000Z"
        request_id:
          type: string
          format: uuid
          example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
        timestamp:
          type: string
          format: date-time
          example: "2026-01-15T10:30:00.000Z"

    ApiKeyRotateResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            api_key:
              type: string
              description: New API key (shown ONCE)
              example: qph_live_xyz789abc012def345
            version:
              type: integer
              description: New key version number
              example: 2
            previous_version_revoked:
              type: boolean
              example: true
        request_id:
          type: string
          format: uuid
          example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
        timestamp:
          type: string
          format: date-time
          example: "2026-01-15T10:30:00.000Z"

    ErrorResponse:
      type: object
      properties:
        error:
          type: object
          properties:
            error_code:
              type: string
              pattern: "^ERR_[A-Z_]+_\\d{3}$"
              example: ERR_AUTH_001
            message:
              type: string
              example: Missing or invalid API key
        request_id:
          type: string
          format: uuid
          example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
        timestamp:
          type: string
          format: date-time
          example: "2026-01-15T10:30:00.000Z"

  responses:
    BadRequest:
      description: Invalid request
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    Unauthorized:
      description: Missing or invalid API key
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    Conflict:
      description: Resource already exists
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    RateLimited:
      description: Rate limit exceeded
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
