openapi: 3.1.0
info:
  title: Kyro API
  version: 1.0.0
  description: Language-agnostic API platform for file storage and management.
  contact:
    name: Kyro Support
    url: https://kyro.io
  license:
    name: Proprietary
servers:
  - url: http://localhost:3000/api/v1
    description: Development
  - url: https://api.kyro.io/api/v1
    description: Production
tags:
  - name: Authentication
    description: User registration and login
  - name: Organisation
    description: Workspace management
  - name: API Keys
    description: API key lifecycle management
  - name: Files
    description: File upload, download, and management
  - name: Usage
    description: Usage analytics and reporting
  - name: Health
    description: Health check endpoints
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
    apiKey:
      type: apiKey
      in: header
      name: X-API-Key
  schemas:
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            message:
              type: string
            code:
              type: string
            details:
              type: array
              items:
                type: object
    User:
      type: object
      properties:
        id:
          type: string
          format: uuid
        email:
          type: string
          format: email
        role:
          type: string
          enum:
            - owner
            - admin
            - member
        orgId:
          type: string
          format: uuid
    Organisation:
      type: object
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
        slug:
          type: string
        plan:
          type: string
          enum:
            - free
            - pro
            - enterprise
        createdAt:
          type: string
          format: date-time
    ApiKey:
      type: object
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
        key_prefix:
          type: string
        scopes:
          type: array
          items:
            type: string
        last_used_at:
          type: string
          format: date-time
          nullable: true
        revoked_at:
          type: string
          format: date-time
          nullable: true
        created_at:
          type: string
          format: date-time
    File:
      type: object
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
        mimeType:
          type: string
        sizeBytes:
          type: integer
        createdAt:
          type: string
          format: date-time
    UsageStats:
      type: object
      properties:
        total_requests:
          type: integer
        total_bytes_in:
          type: integer
        total_bytes_out:
          type: integer
        total_storage:
          type: integer
        active_api_keys:
          type: integer
    Member:
      type: object
      properties:
        id:
          type: string
          format: uuid
        email:
          type: string
          format: email
        role:
          type: string
          enum:
            - owner
            - admin
            - member
        createdAt:
          type: string
          format: date-time
  responses:
    BadRequest:
      description: Invalid request body
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    Unauthorized:
      description: Authentication required
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    Forbidden:
      description: Insufficient permissions
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    Conflict:
      description: Resource already exists
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    PayloadTooLarge:
      description: File too large
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    TooManyRequests:
      description: Rate limit exceeded
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: object
                properties:
                  message:
                    type: string
                  retryAfter:
                    type: number
paths:
  /auth/register:
    post:
      tags:
        - Authentication
      summary: Register new user and organisation
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - email
                - password
                - orgName
              properties:
                email:
                  type: string
                  format: email
                  description: User email address
                password:
                  type: string
                  format: password
                  minLength: 8
                  description: User password (min 8 characters)
                orgName:
                  type: string
                  minLength: 1
                  maxLength: 255
                  description: Organisation name
      responses:
        "201":
          description: User registered successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  token:
                    type: string
                    description: JWT authentication token
                  user:
                    $ref: "#/components/schemas/User"
        "400":
          $ref: "#/components/responses/BadRequest"
        "409":
          $ref: "#/components/responses/Conflict"
  /auth/login:
    post:
      tags:
        - Authentication
      summary: Login user
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - email
                - password
              properties:
                email:
                  type: string
                  format: email
                password:
                  type: string
                  format: password
      responses:
        "200":
          description: Login successful
          content:
            application/json:
              schema:
                type: object
                properties:
                  token:
                    type: string
                  user:
                    $ref: "#/components/schemas/User"
        "401":
          $ref: "#/components/responses/Unauthorized"
  /auth/me:
    get:
      tags:
        - Authentication
      summary: Get current user
      security:
        - bearerAuth: []
      responses:
        "200":
          description: Current user details
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/User"
        "401":
          $ref: "#/components/responses/Unauthorized"
  /files:
    get:
      tags:
        - Files
      summary: List files
      security:
        - apiKey: []
      parameters:
        - name: limit
          in: query
          schema:
            type: integer
            default: 100
            maximum: 100
        - name: cursor
          in: query
          schema:
            type: string
      responses:
        "200":
          description: List of files
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
    post:
      tags:
        - Files
      summary: Upload file
      security:
        - apiKey: []
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - file
              properties:
                file:
                  type: string
                  format: binary
                  description: File to upload
      responses:
        "201":
          description: File uploaded
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "413":
          $ref: "#/components/responses/PayloadTooLarge"
  /files/{id}:
    get:
      tags:
        - Files
      summary: Download file
      security:
        - apiKey: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: File content
          content:
            application/octet-stream:
              schema:
                type: string
                format: binary
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
    delete:
      tags:
        - Files
      summary: Delete file
      security:
        - apiKey: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
          description: File UUID
      responses:
        "200":
          description: File deleted
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
  /keys:
    get:
      tags:
        - API Keys
      summary: List API keys
      security:
        - bearerAuth: []
      responses:
        "200":
          description: List of API keys
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/ApiKey"
        "401":
          $ref: "#/components/responses/Unauthorized"
    post:
      tags:
        - API Keys
      summary: Create API key
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - name
              properties:
                name:
                  type: string
                  minLength: 1
                  maxLength: 255
                  description: Key name
                scopes:
                  type: array
                  items:
                    type: string
                    enum:
                      - read
                      - write
                      - admin
                  default:
                    - read
                  description: Key permissions
      responses:
        "201":
          description: API key created
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
  /keys/{id}:
    delete:
      tags:
        - API Keys
      summary: Revoke API key
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: Key revoked
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
  /org:
    get:
      tags:
        - Organisation
      summary: Get current organisation
      security:
        - bearerAuth: []
      responses:
        "200":
          description: Organisation details
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Organisation"
        "401":
          $ref: "#/components/responses/Unauthorized"
  /org/members:
    get:
      tags:
        - Organisation
      summary: List organisation members
      security:
        - bearerAuth: []
      responses:
        "200":
          description: List of members
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Member"
        "401":
          $ref: "#/components/responses/Unauthorized"
    post:
      tags:
        - Organisation
      summary: Invite new member
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - email
                - password
              properties:
                email:
                  type: string
                  format: email
                password:
                  type: string
                  format: password
                role:
                  type: string
                  enum:
                    - owner
                    - admin
                    - member
                  default: member
      responses:
        "201":
          description: Member invited
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Member"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
  /org/members/{id}:
    delete:
      tags:
        - Organisation
      summary: Remove member
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "204":
          description: Member removed
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
  /usage:
    get:
      tags:
        - Usage
      summary: Get usage statistics
      security:
        - bearerAuth: []
      parameters:
        - name: start_date
          in: query
          schema:
            type: string
            format: date
          description: Start date (YYYY-MM-DD)
        - name: end_date
          in: query
          schema:
            type: string
            format: date
          description: End date (YYYY-MM-DD)
      responses:
        "200":
          description: Usage statistics
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UsageStats"
        "401":
          $ref: "#/components/responses/Unauthorized"
  /usage/daily:
    get:
      tags:
        - Usage
      summary: Get daily usage breakdown
      security:
        - bearerAuth: []
      parameters:
        - name: start_date
          in: query
          schema:
            type: string
            format: date
        - name: end_date
          in: query
          schema:
            type: string
            format: date
      responses:
        "200":
          description: Daily usage data
        "401":
          $ref: "#/components/responses/Unauthorized"
