openapi: 3.0.3
info:
  title: PicShapes API
  description: |
    API for AI image generation powered by a distributed network of GPU workers.

    ## Authentication

    Authenticated endpoints require a User API Key passed as a Bearer token:
    ```
    Authorization: Bearer uk_your_api_key_here
    ```

    Create your API key at https://picshapes.com/dashboard/keys

    ## Rate Limits

    - **Per-minute limit**: 60 requests
    - **Daily limit**: 1,000 requests

    When rate limited, you'll receive a 429 response with `retry_after` indicating seconds to wait.
  version: 1.0.0
  contact:
    name: PicShapes
    url: https://picshapes.com

servers:
  - url: https://api.picshapes.com
    description: Production server

components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: User API Key (starts with uk_)

  schemas:
    CreateJobRequest:
      type: object
      required:
        - prompt
      properties:
        prompt:
          type: string
          description: Text description of the image to generate
          example: a beautiful sunset over mountains, digital art
        negative_prompt:
          type: string
          description: What to avoid in the image
          example: blurry, low quality
        model:
          type: string
          enum: [z-image-turbo, flux-schnell]
          default: z-image-turbo
          description: |
            AI model to use for generation:
            - **z-image-turbo** (default): Fast, high-quality images with 8 inference steps
            - **flux-schnell**: Ultra-fast generation from Black Forest Labs with 4 inference steps
        tier:
          type: string
          enum: [basic, pro, premium]
          default: basic
          description: Quality tier (affects resolution and credits)
        width:
          type: integer
          description: Image width in pixels (max depends on tier and model)
          example: 1024
        height:
          type: integer
          description: Image height in pixels (max depends on tier and model)
          example: 1024
        seed:
          type: integer
          description: Random seed for reproducibility
          example: 42

    Job:
      type: object
      properties:
        id:
          type: string
          format: uuid
          example: 8ed8f84c-c9b8-43f4-a8cd-90dec79ada7d
        status:
          type: string
          enum: [pending, claimed, processing, completed, failed]
          description: Current job status
        prompt:
          type: string
        negative_prompt:
          type: string
        model:
          type: string
          enum: [z-image-turbo, flux-schnell]
          description: AI model used for this generation
        tier:
          type: string
          enum: [basic, pro, premium]
        width:
          type: integer
        height:
          type: integer
        steps:
          type: integer
        seed:
          type: integer
        result_url:
          type: string
          format: uri
          description: URL to download the generated image (only when completed)
        error_msg:
          type: string
          description: Error message (only when failed)
        created_at:
          type: string
          format: date-time
        started_at:
          type: string
          format: date-time
        completed_at:
          type: string
          format: date-time

    UserProfile:
      type: object
      properties:
        id:
          type: string
          format: uuid
        email:
          type: string
          format: email
        display_name:
          type: string
        photo_url:
          type: string
          format: uri
        credits:
          type: integer
          description: Current credit balance
        role:
          type: string
          enum: [user, admin]
        created_at:
          type: string
          format: date-time
        last_login_at:
          type: string
          format: date-time

    CreditsResponse:
      type: object
      properties:
        credits:
          type: integer
          description: Current credit balance
          example: 86
        user_id:
          type: string
          format: uuid

    TierConfig:
      type: object
      properties:
        name:
          type: string
        description:
          type: string
        max_width:
          type: integer
        max_height:
          type: integer
        max_steps:
          type: integer
        default_width:
          type: integer
        default_height:
          type: integer
        default_steps:
          type: integer
        credits:
          type: integer
          description: Credits required for this tier
        min_vram:
          type: integer
          description: Minimum GPU VRAM required

    TiersResponse:
      type: object
      properties:
        tiers:
          type: object
          properties:
            basic:
              $ref: '#/components/schemas/TierConfig'
            pro:
              $ref: '#/components/schemas/TierConfig'
            premium:
              $ref: '#/components/schemas/TierConfig'

    Error:
      type: object
      properties:
        error:
          type: string
          description: Human-readable error message
        code:
          type: string
          description: Machine-readable error code
        credits:
          type: integer
          description: Current credit balance (for credit-related errors)
        credits_needed:
          type: integer
          description: Credits needed for the operation

    ModelInfo:
      type: object
      properties:
        id:
          type: string
          description: Model identifier
          example: flux-schnell
        name:
          type: string
          description: Human-readable model name
          example: FLUX.1 Schnell
        description:
          type: string
          description: Brief description of the model
          example: Ultra-fast, excellent prompts (4 steps)
        optimal_steps:
          type: integer
          description: Optimal number of inference steps for this model
          example: 4
        is_default:
          type: boolean
          description: Whether this is the default model
        tier_configs:
          type: object
          description: Tier-specific configurations for this model
          additionalProperties:
            $ref: '#/components/schemas/TierConfig'
        available:
          type: boolean
          description: Whether workers are currently available for this model
        worker_count:
          type: integer
          description: Number of online workers supporting this model
        tiers:
          type: object
          description: Per-tier availability information
          additionalProperties:
            type: object
            properties:
              available:
                type: boolean
              worker_count:
                type: integer

    ModelsResponse:
      type: object
      properties:
        models:
          type: object
          description: Map of model ID to model information
          additionalProperties:
            $ref: '#/components/schemas/ModelInfo'
        default_model:
          type: string
          description: The default model ID
          example: z-image-turbo

paths:
  /api/v1/users/me:
    get:
      summary: Get user profile
      description: Returns the authenticated user's profile including credit balance
      tags:
        - Users
      security:
        - BearerAuth: []
      responses:
        '200':
          description: User profile
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserProfile'
        '401':
          description: Unauthorized - Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /api/v1/users/me/credits:
    get:
      summary: Get credit balance
      description: Returns just the user's current credit balance
      tags:
        - Users
      security:
        - BearerAuth: []
      responses:
        '200':
          description: Credit balance
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreditsResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /api/v1/tiers:
    get:
      summary: Get tier configurations
      description: Returns available quality tiers with their limits and pricing
      tags:
        - Tiers
      responses:
        '200':
          description: Tier configurations
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TiersResponse'

  /api/v1/models:
    get:
      summary: Get available models
      description: |
        Returns available AI image generation models with their configurations and real-time availability.

        **Available Models:**
        - **z-image-turbo**: Fast, high-quality generation (8 steps optimal)
        - **flux-schnell**: Ultra-fast generation from Black Forest Labs (4 steps optimal)

        Each model has different tier limits. For example, FLUX Pro tier maxes at 1280px while Z-Image Pro tier maxes at 1440px.
      tags:
        - Models
      responses:
        '200':
          description: Model configurations and availability
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ModelsResponse'
              example:
                models:
                  z-image-turbo:
                    id: z-image-turbo
                    name: Z-Image Turbo
                    description: Fast, high-quality (8 steps)
                    optimal_steps: 8
                    is_default: true
                    available: true
                    worker_count: 3
                  flux-schnell:
                    id: flux-schnell
                    name: FLUX.1 Schnell
                    description: Ultra-fast, excellent prompts (4 steps)
                    optimal_steps: 4
                    is_default: false
                    available: true
                    worker_count: 2
                default_model: z-image-turbo

  /api/v1/jobs:
    post:
      summary: Create image generation job
      description: |
        Creates a new image generation job. Credits are deducted immediately based on the tier.

        **Model Selection:**
        - `z-image-turbo` (default): 8 inference steps, high-quality output
        - `flux-schnell`: 4 inference steps, ultra-fast from Black Forest Labs

        **Tier Pricing (same for both models):**
        - **basic**: 1 credit
        - **pro**: 3 credits
        - **premium**: 5 credits

        **Resolution Limits by Model and Tier:**
        | Tier | Z-Image Turbo | FLUX.1 Schnell |
        |------|---------------|----------------|
        | basic | 1024px | 1024px |
        | pro | 1440px | 1280px |
        | premium | 1536px | 1536px |
      tags:
        - Jobs
      security:
        - BearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateJobRequest'
      responses:
        '201':
          description: Job created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Job'
        '400':
          description: Invalid request (bad tier, exceeds limits, etc.)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                invalidTier:
                  value:
                    error: Invalid tier
                    code: INVALID_TIER
                limitExceeded:
                  value:
                    error: Width exceeds tier maximum
                    code: TIER_LIMIT_EXCEEDED
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '402':
          description: Insufficient credits
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Insufficient credits
                code: INSUFFICIENT_CREDITS
                credits: 0
                credits_needed: 1
        '429':
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  code:
                    type: string
                  retry_after:
                    type: integer
                    description: Seconds to wait before retrying

  /api/v1/jobs/{id}:
    get:
      summary: Get job status
      description: |
        Returns the current status of a job. Poll this endpoint to check for completion.
        No authentication required - job IDs are unguessable UUIDs.
      tags:
        - Jobs
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
          description: Job ID
      responses:
        '200':
          description: Job details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Job'
        '404':
          description: Job not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /api/v1/jobs/{id}/result:
    get:
      summary: Get job result
      description: |
        Returns just the result URL. Useful for simple polling.
        Returns 202 Accepted if the job is not yet complete.
      tags:
        - Jobs
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
          description: Job ID
      responses:
        '200':
          description: Job completed, result available
          content:
            application/json:
              schema:
                type: object
                properties:
                  result_url:
                    type: string
                    format: uri
        '202':
          description: Job not yet complete
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                    example: Job is not completed yet
        '404':
          description: Job not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

tags:
  - name: Users
    description: User profile and credits
  - name: Jobs
    description: Image generation jobs
  - name: Tiers
    description: Quality tier configurations
  - name: Models
    description: Available AI image generation models
