openapi: 3.0.0
info:
  title: Screenshot API
  version: 1.0.0
  description: |
    A high-performance API for capturing website screenshots with advanced features.

    ## Features
    - Full-page screenshots
    - Multiple output formats (PNG, JPEG, WebP)
    - Custom viewport dimensions
    - Cookie banner dismissal
    - Batch processing
    - Webhook notifications
    - Analytics and usage tracking

    ## Authentication
    All endpoints (except registration and authentication) require either:
    - Session-based authentication (for web interface)
    - API Key authentication (for programmatic access)

    Include your API key in the `Authorization` header as a Bearer token:
    ```
    Authorization: Bearer YOUR_API_KEY
    ```
  license:
    name: MIT

servers:
  - url: https://screenshot-api-gamma.vercel.app/api
    description: Production Server

components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API_KEY
      description: API Key for programmatic access

    SessionAuth:
      type: apiKey
      in: cookie
      name: next-auth.session-token
      description: Session cookie for web interface

  schemas:
    Error:
      type: object
      properties:
        error:
          type: string
          description: Error message
        message:
          type: string
          description: Detailed error description
      required:
        - error

    User:
      type: object
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
        email:
          type: string
          format: email
        apiKey:
          type: string
        apiUsage:
          type: integer
        apiLimit:
          type: integer
        rateLimit:
          type: integer
          description: Requests per hour limit
        planType:
          type: string
          enum: [free, pro, enterprise]
        createdAt:
          type: string
          format: date-time

    WebhookEvent:
      type: string
      description: Available webhook events.
      enum:
        - screenshot.failed
        - usage.limit_reached
        - usage.limit_warning

paths:
  /auth/register:
    post:
      summary: Register a new user
      description: Create a new account with email and password. Automatically generates an API key.
      tags:
        - Authentication
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  example: "John Doe"
                email:
                  type: string
                  format: email
                  example: "john@example.com"
                password:
                  type: string
                  format: password
                  example: "SecurePassword123!"
              required:
                - name
                - email
                - password
      responses:
        "200":
          description: User successfully registered
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  user:
                    $ref: "#/components/schemas/User"
        "400":
          description: Bad Request - Missing fields or user already exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /screenshot:
    post:
      summary: Capture a website screenshot
      description: |
        Generates a screenshot of the specified URL with customizable options.

        ## Features
        - Supports PNG, JPEG, WebP, and PDF formats
        - Screenshot websites from URLs or render custom HTML content
        - Custom viewport dimensions (320-3840 width, 240-2160 height)
        - Full-page capture option
        - Automatic cookie banner dismissal
        - Rate limiting: 30 requests per minute per IP, 120 per hour per user (free plan)
      tags:
        - Screenshots
      security:
        - BearerAuth: []
        - SessionAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                url:
                  type: string
                  format: uri
                  description: The website URL to capture (required if html not provided)
                  example: "https://github.com"
                html:
                  type: string
                  description: HTML content to render (required if url not provided)
                  example: "<h1>Hello World</h1><p>This is rendered from HTML</p>"
                css:
                  type: string
                  description: CSS to apply to HTML content (optional, only used with html parameter)
                  example: "body { background: #f0f0f0; font-family: Arial; }"
                width:
                  type: integer
                  minimum: 320
                  maximum: 3840
                  default: 1920
                  description: Viewport width in pixels
                height:
                  type: integer
                  minimum: 240
                  maximum: 2160
                  default: 1080
                  description: Viewport height in pixels
                fullPage:
                  type: boolean
                  default: false
                  description: Capture the entire page height
                format:
                  type: string
                  enum: [png, jpeg, webp, pdf]
                  default: png
                  description: Output image format
                dismissCookieBanners:
                  type: boolean
                  default: false
                  description: Attempt to dismiss cookie consent banners (only applies to URL mode)
                stealth:
                  type: boolean
                  default: false
                  description: Enable stealth mode to evade bot detection systems (recommended for protected websites)
                name:
                  type: string
                  description: Optional name for the screenshot
                scroll:
                  type: boolean
                  default: false
                  description: Enable scrolling to trigger lazy-loaded content before capture
                scrollMode:
                  type: string
                  enum: [auto, stitch]
                  default: auto
                  description: |
                    Scroll mode:
                    - auto: Scrolls page to trigger lazy content, then captures screenshot
                    - stitch: Captures multiple viewport screenshots while scrolling and stitches together
                scrollStep:
                  type: integer
                  minimum: 100
                  maximum: 2000
                  default: 800
                  description: Pixels to scroll in each step
                scrollDelay:
                  type: integer
                  minimum: 50
                  maximum: 2000
                  default: 250
                  description: Delay between scroll steps in milliseconds
                maxScrolls:
                  type: integer
                  minimum: 1
                  maximum: 100
                  default: 50
                  description: Maximum number of scroll iterations
                lazyLoadWait:
                  type: integer
                  minimum: 100
                  maximum: 5000
                  default: 500
                  description: Wait time after reaching page bottom in milliseconds
                noCache:
                  type: boolean
                  default: false
                  description: Skip cache lookup and do not store result in cache
                cacheMaxAge:
                  type: integer
                  minimum: 0
                  maximum: 3600
                  default: 300
                  description: Cache duration in seconds (0 disables caching for this request)
              oneOf:
                - required: [url]
                - required: [html]
            examples:
              basic:
                summary: Basic screenshot
                value:
                  url: "https://github.com"
              fullPage:
                summary: Full page screenshot
                value:
                  url: "https://github.com"
                  fullPage: true
                  format: "png"
              custom:
                summary: Custom dimensions
                value:
                  url: "https://github.com"
                  width: 1280
                  height: 720
                  format: "jpeg"
                  dismissCookieBanners: true
              pdf:
                summary: PDF generation
                value:
                  url: "https://github.com"
                  format: "pdf"
              stealth:
                summary: Stealth mode for bot detection evasion
                value:
                  url: "https://example.com/protected-page"
                  stealth: true
                  format: "png"
              htmlRendering:
                summary: HTML rendering
                value:
                  html: "<h1>Hello World</h1><p>This is rendered from HTML</p>"
                  css: "body { background: #f0f0f0; font-family: Arial, sans-serif; }"
                  width: 800
                  height: 600
                  format: "png"
              scrolling:
                summary: Scrolling screenshot for lazy content
                value:
                  url: "https://example.com/long-page"
                  scroll: true
                  scrollMode: "auto"
                  scrollStep: 800
                  scrollDelay: 250
                  maxScrolls: 50
                  fullPage: true
                  format: "png"
              stitching:
                summary: Stitch mode for very long pages
                value:
                  url: "https://example.com/infinite-scroll"
                  scroll: true
                  scrollMode: "stitch"
                  maxScrolls: 20
                  format: "png"
      responses:
        "200":
          description: Screenshot captured successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  screenshot:
                    type: string
                    description: Base64-encoded image data
                  metadata:
                    type: object
                    properties:
                      url:
                        type: string
                      width:
                        type: integer
                      height:
                        type: integer
                      format:
                        type: string
                      fullPage:
                        type: boolean
                      size:
                        type: integer
                      timestamp:
                        type: string
                        format: date-time
                      scroll:
                        type: boolean
                        description: Whether scrolling was enabled
                      scrollMode:
                        type: string
                        enum: [auto, stitch]
                        description: Scroll mode used (only present if scroll was enabled)
                      scrollSteps:
                        type: integer
                        description: Number of scroll steps taken
                      totalScrollHeight:
                        type: integer
                        description: Total pixels scrolled
                      scrollDuration:
                        type: integer
                        description: Time spent scrolling in milliseconds
                      cached:
                        type: boolean
                        description: Whether response was served from cache
                      cacheAge:
                        type: integer
                        description: Seconds since cached response was generated (only present on cache hit)
                      cacheKey:
                        type: string
                        description: Unique cache key for this request
                  remainingRequests:
                    type: integer
                    description: API requests remaining this hour
        "400":
          description: Bad Request - Invalid URL or parameters
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: Unauthorized - Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: Forbidden - Blocked URL or feature not allowed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "429":
          description: Too Many Requests - Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "500":
          description: Internal Server Error - Screenshot capture failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /batch:
    post:
      summary: Submit a batch screenshot job
      description: |
        Process multiple screenshot requests in a single batch job.
        Maximum 50 URLs per batch. Jobs are processed asynchronously with 3 concurrent screenshots.
      tags:
        - Screenshots
      security:
        - BearerAuth: []
        - SessionAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                requests:
                  type: array
                  maxItems: 50
                  items:
                    type: object
                    properties:
                      url:
                        type: string
                        format: uri
                      width:
                        type: integer
                        minimum: 320
                        maximum: 3840
                      height:
                        type: integer
                        minimum: 240
                        maximum: 2160
                      fullPage:
                        type: boolean
                      format:
                        type: string
                        enum: [png, jpeg, webp]
                      dismissCookieBanners:
                        type: boolean
                    required:
                      - url
              required:
                - requests
            example:
              requests:
                - url: "https://github.com"
                  format: "png"
                - url: "https://example.com"
                  fullPage: true
      responses:
        "200":
          description: Batch job submitted successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  job:
                    type: object
                    properties:
                      id:
                        type: string
                        format: uuid
                      status:
                        type: string
                        enum: [pending, processing]
                      totalRequests:
                        type: integer
                      completedRequests:
                        type: integer
                      failedRequests:
                        type: integer
                      createdAt:
                        type: string
                        format: date-time
        "400":
          description: Bad Request - Invalid requests array or URL format
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: User not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "429":
          description: Insufficient quota for batch
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  message:
                    type: string
                    description: Details about remaining quota

    get:
      summary: Get batch job status
      description: Retrieve the status and results of a batch job
      tags:
        - Screenshots
      security:
        - BearerAuth: []
        - SessionAuth: []
      parameters:
        - name: id
          in: query
          required: true
          schema:
            type: string
            format: uuid
          description: The batch job ID
      responses:
        "200":
          description: Batch job details
          content:
            application/json:
              schema:
                type: object
                properties:
                  job:
                    type: object
                    properties:
                      id:
                        type: string
                        format: uuid
                      status:
                        type: string
                        enum: [pending, processing, completed, failed]
                      totalRequests:
                        type: integer
                      completedRequests:
                        type: integer
                      failedRequests:
                        type: integer
                      results:
                        type: array
                        items:
                          type: object
                          properties:
                            index:
                              type: integer
                            success:
                              type: boolean
                            screenshot:
                              type: string
                              description: Base64-encoded image (only if success)
                            metadata:
                              type: object
                              description: Screenshot metadata (only if success)
                            error:
                              type: string
                              description: Error message (only if failed)
                      createdAt:
                        type: string
                        format: date-time
                      updatedAt:
                        type: string
                        format: date-time
                      completedAt:
                        type: string
                        format: date-time
                        description: Only present when status is completed
        "400":
          description: Job ID is required
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: Access denied - Job belongs to another user
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: Job not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /user/profile:
    get:
      summary: Get user profile
      description: Retrieve the authenticated user's profile information
      tags:
        - User
      security:
        - BearerAuth: []
        - SessionAuth: []
      responses:
        "200":
          description: User profile
          content:
            application/json:
              schema:
                type: object
                properties:
                  user:
                    $ref: "#/components/schemas/User"
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: User not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /user/regenerate-api-key:
    post:
      summary: Regenerate API key
      description: Generate a new API key for the authenticated user. The old key will be invalidated.
      tags:
        - User
      security:
        - SessionAuth: []
      responses:
        "200":
          description: New API key generated
          content:
            application/json:
              schema:
                type: object
                properties:
                  apiKey:
                    type: string
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /analytics:
    get:
      summary: Get usage analytics
      description: |
        Retrieve usage statistics for the authenticated user.

        **Note:** Analytics show usage counters only.
        Screenshot history (format distribution, top domains, etc.) is not stored.
      tags:
        - Analytics
      security:
        - BearerAuth: []
        - SessionAuth: []
      responses:
        "200":
          description: Analytics data
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  analytics:
                    type: object
                    properties:
                      totalRequests:
                        type: integer
                        description: Total API requests made
                      limit:
                        type: integer
                        description: Monthly request limit
                      remaining:
                        type: integer
                        description: Remaining requests this month
                      usagePercentage:
                        type: integer
                        description: Percentage of limit used (0-100)
                      planType:
                        type: string
                        enum: [free, pro, enterprise]
                      rateLimit:
                        type: integer
                        description: Rate limit (requests per hour)
                      memberSince:
                        type: string
                        format: date-time
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: User not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /analytics/advanced:
    get:
      summary: Get advanced usage analytics
      description: |
        Retrieve detailed usage analytics including account age and average usage metrics.
      tags:
        - Analytics
      security:
        - BearerAuth: []
        - SessionAuth: []
      parameters:
        - name: period
          in: query
          schema:
            type: integer
            enum: [7, 30, 90]
            default: 30
          description: Analysis period in days (for reference only)
      responses:
        "200":
          description: Advanced analytics data
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  analytics:
                    type: object
                    properties:
                      period:
                        type: integer
                        description: Requested period in days
                      accountAge:
                        type: integer
                        description: Account age in days
                      totalRequests:
                        type: integer
                        description: Total API requests made
                      avgRequestsPerDay:
                        type: number
                        description: Average requests per day since account creation
                      limit:
                        type: integer
                        description: Monthly request limit
                      remaining:
                        type: integer
                        description: Remaining requests this month
                      usagePercentage:
                        type: integer
                        description: Percentage of limit used (0-100)
                      planUtilization:
                        type: object
                        properties:
                          planType:
                            type: string
                            enum: [free, pro, enterprise]
                          currentUsage:
                            type: integer
                          rateLimit:
                            type: integer
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: User not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /webhooks:
    post:
      summary: Create or update webhook
      description: |
        Configure a webhook endpoint to receive event notifications.
        Only one webhook per user is supported - creating a new one will update the existing configuration.
      tags:
        - Webhooks
      security:
        - BearerAuth: []
        - SessionAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                url:
                  type: string
                  format: uri
                  description: Your webhook endpoint URL (must be a valid URL)
                events:
                  type: array
                  items:
                    $ref: "#/components/schemas/WebhookEvent"
                  description: Events to subscribe to
                secret:
                  type: string
                  description: Optional secret for webhook signature verification
              required:
                - url
                - events
            example:
              url: "https://your-server.com/webhook"
              events: ["screenshot.failed", "usage.limit_warning"]
              secret: "your-secret-key"
      responses:
        "200":
          description: Webhook configured successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  webhook:
                    type: object
                    properties:
                      id:
                        type: string
                        format: uuid
                      url:
                        type: string
                      events:
                        type: array
                        items:
                          type: string
                      secret:
                        type: string
                        description: Returns "***hidden***" if set, null otherwise
                      isActive:
                        type: boolean
                      createdAt:
                        type: string
                        format: date-time
        "400":
          description: Invalid URL or events array
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: User not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

    get:
      summary: Get webhook configuration
      description: Retrieve the current webhook configuration and recent delivery history
      tags:
        - Webhooks
      security:
        - BearerAuth: []
        - SessionAuth: []
      responses:
        "200":
          description: Webhook configuration (returns null if not configured)
          content:
            application/json:
              schema:
                type: object
                properties:
                  webhook:
                    type: object
                    nullable: true
                    properties:
                      id:
                        type: string
                        format: uuid
                      url:
                        type: string
                      events:
                        type: array
                        items:
                          type: string
                      secret:
                        type: string
                        description: Returns "***hidden***" if set, null otherwise
                      isActive:
                        type: boolean
                      createdAt:
                        type: string
                        format: date-time
                      lastDelivery:
                        type: string
                        format: date-time
                        nullable: true
                  deliveries:
                    type: array
                    description: Last 10 webhook deliveries
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                          format: uuid
                        event:
                          type: string
                        success:
                          type: boolean
                        statusCode:
                          type: integer
                          nullable: true
                        attempts:
                          type: integer
                        createdAt:
                          type: string
                          format: date-time
                        nextRetry:
                          type: string
                          format: date-time
                          nullable: true
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: User not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

    delete:
      summary: Delete webhook
      description: Remove the webhook configuration
      tags:
        - Webhooks
      security:
        - BearerAuth: []
        - SessionAuth: []
      responses:
        "200":
          description: Webhook deleted successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: User not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /contact:
    post:
      x-internal: true
      summary: Submit contact form
      description: |
        Send a message through the contact form. No authentication required.

        ## Rate Limiting
        - 3 requests per hour per IP address
        - Includes honeypot spam protection

        ## Validation
        - Name: Required, max 100 characters
        - Email: Required, valid email format
        - Message: Required, 10-5000 characters
      tags:
        - Contact
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  maxLength: 100
                  description: Sender's name
                  example: "John Doe"
                email:
                  type: string
                  format: email
                  description: Sender's email address
                  example: "john@example.com"
                message:
                  type: string
                  minLength: 10
                  maxLength: 5000
                  description: Message content
                  example: "I'd like to learn more about your API pricing plans."
                website:
                  type: string
                  description: Honeypot field - leave empty (used for spam detection)
              required:
                - name
                - email
                - message
      responses:
        "200":
          description: Message sent successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  message:
                    type: string
                    example: "Thank you for your message. We'll get back to you soon!"
        "400":
          description: Validation error
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: false
                  error:
                    type: string
                    example: "Email is required"
        "429":
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: false
                  error:
                    type: string
                    example: "Too many requests. Please try again later."
        "500":
          description: Failed to send message
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: false
                  error:
                    type: string
                    example: "Failed to send message. Please try again later."

tags:
  - name: Authentication
    description: User registration and authentication
  - name: Screenshots
    description: Screenshot capture and batch processing
  - name: User
    description: User profile and settings management
  - name: Analytics
    description: Usage statistics and analytics
  - name: Webhooks
    description: Webhook configuration and event notifications
  - name: Contact
    description: Contact form submission
