openapi: 3.0.3
info:
  title: vfrog.ai Computer Vision API
  version: 1.0.0
  description: |
    vfrog.ai provides powerful computer vision capabilities through a simple REST API.

    ## Authentication
    All requests require an API key passed in the `x-api-key` header.

    ## Endpoints
    - **Sync** (`/v1/cv/requests/sync`): Process a single image and get results immediately
    - **Batch** (`/v1/cv/requests/batch`): Process multiple images (up to 10) in parallel
    - **Feedback** (`/v1/cv/feedback`): Submit rating feedback for a request

    ## Getting Started
    1. Sign up at [console.vfrog.ai](https://console.vfrog.ai)
    2. Create an API key
    3. Make your first request

    For detailed documentation, visit [docs.vfrog.ai](https://docs.vfrog.ai)

    ## Download API Resources

    - **Postman Collection**: [Download](https://docs.vfrog.ai/vfrog-rest-api.postman_collection.json)
    - **OpenAPI Spec**: [Download](https://docs.vfrog.ai/openapi/cv-api.yaml)

    The Postman collection includes pre-configured requests for all endpoints. The OpenAPI specification can be imported into API testing tools, code generators, and documentation platforms.
  contact:
    name: vfrog.ai Support
    email: contact@vfrog.ai
    url: https://vfrog.ai
  license:
    name: Proprietary
    url: https://vfrog.ai/terms
servers:
  - url: https://api.vfrog.ai
    description: Production server
tags:
  - name: Computer Vision
    description: Computer vision processing endpoints for image analysis
paths:
  /v1/cv/requests/{id}:
    get:
      summary: Get CV request status and results
      description: |
        Retrieve the status and results of a previously submitted request.
        The request_id is returned when you submit a sync request.
      operationId: getRequest
      tags:
        - Computer Vision
      security:
        - x-api-key: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
          description: Request ID returned from sync submission
      responses:
        '200':
          description: Request found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CVResult'
              examples:
                success:
                  summary: Successful request
                  value:
                    success: true
                    request_id: '550e8400-e29b-41d4-a716-446655440000'
                    external_id: 'async-scan-001'
                    status: DONE
                    image_url: 'https://cdn.vfrog.ai/cv-requests/2025-10-22/api-key-id/uuid.jpg'
                    results:
                      - label: 'product'
                        external_id: 'product-01'
                        bounding_box:
                          x: 100
                          y: 200
                          width: 300
                          height: 400
                processing:
                  summary: Request still processing
                  value:
                    success: false
                    request_id: '550e8400-e29b-41d4-a716-446655440000'
                    external_id: 'async-scan-001'
                    status: PROCESSING
                    image_url: 'https://example.com/image.jpg'
                    results: []
                error:
                  summary: Request failed
                  value:
                    success: false
                    request_id: '550e8400-e29b-41d4-a716-446655440000'
                    external_id: 'async-scan-001'
                    status: ERROR
                    image_url: 'https://example.com/image.jpg'
                    error: 'Image processing failed'
                    results: []
        '400':
          description: Invalid request ID
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                invalid_id:
                  summary: Invalid UUID format
                  value:
                    error: 'missing_request_id'
        '403':
          description: Not authorized to view this request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                unauthorized:
                  summary: Request belongs to different API key
                  value:
                    error: 'unauthorized'
        '404':
          description: Request not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                not_found:
                  summary: Request does not exist
                  value:
                    error: 'request_not_found'
  /v1/cv/feedback:
    post:
      summary: Submit feedback for a CV request
      description: |
        Submit a rating for a previously processed CV request. This helps improve the service quality.

        **Rating values:**
        - `-1`: Bad - The results were incorrect or unsatisfactory
        - `0`: Neutral - The results were acceptable but not exceptional
        - `1`: Good - The results were accurate and helpful

        The rating is stored in the `cv_request` table and can be used for analytics and service improvement.
      operationId: submitFeedback
      tags:
        - Computer Vision
      security:
        - x-api-key: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - request_id
                - rating
              properties:
                request_id:
                  type: string
                  format: uuid
                  description: The CV request ID from a previously submitted request
                  example: '550e8400-e29b-41d4-a716-446655440000'
                rating:
                  type: integer
                  enum: [-1, 0, 1]
                  description: |
                    Rating value:
                    - `-1`: Bad
                    - `0`: Neutral
                    - `1`: Good
                  example: 1
            examples:
              good_rating:
                summary: Good rating
                value:
                  request_id: '550e8400-e29b-41d4-a716-446655440000'
                  rating: 1
              neutral_rating:
                summary: Neutral rating
                value:
                  request_id: '550e8400-e29b-41d4-a716-446655440000'
                  rating: 0
              bad_rating:
                summary: Bad rating
                value:
                  request_id: '550e8400-e29b-41d4-a716-446655440000'
                  rating: -1
      responses:
        '200':
          description: Feedback submitted successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: 'success'
                    description: Status of the operation
                  message:
                    type: string
                    example: 'Feedback submitted successfully'
                    description: Success message
                  request_id:
                    type: string
                    format: uuid
                    example: '550e8400-e29b-41d4-a716-446655440000'
                    description: The CV request ID that was rated
                  rating:
                    type: integer
                    enum: [-1, 0, 1]
                    example: 1
                    description: The rating that was submitted
              examples:
                success:
                  summary: Feedback submitted
                  value:
                    status: 'success'
                    message: 'Feedback submitted successfully'
                    request_id: '550e8400-e29b-41d4-a716-446655440000'
                    rating: 1
        '400':
          description: Invalid rating value
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                invalid_rating:
                  summary: Invalid rating
                  value:
                    error: 'invalid_rating'
                    message: 'Rating must be -1 (bad), 0 (neutral), or 1 (good)'
                    error_code: 'INVALID_RATING'
        '401':
          description: Missing or invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                missing_api_key:
                  summary: Missing API key
                  value:
                    error: 'unauthorized'
                    message: 'Missing x-api-key header'
                    error_code: 'MISSING_API_KEY'
        '404':
          description: CV request not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                not_found:
                  summary: Request not found
                  value:
                    error: 'request_not_found'
                    message: "CV request with ID '550e8400-e29b-41d4-a716-446655440000' not found"
                    error_code: 'REQUEST_NOT_FOUND'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /v1/cv/requests/sync:
    post:
      summary: Submit a synchronous CV processing request
      description: |
        Process a computer vision request synchronously and return results immediately.
        Maximum processing time: 300 seconds (5 minutes). If processing exceeds this limit, a 408 timeout is returned.

        **Use this endpoint for:**
        - Real-time user-facing features
        - Interactive applications
        - Single image processing with immediate feedback

        **Rate limit:** 10 requests/minute
      operationId: createSyncCvRequest
      tags:
        - Computer Vision
      security:
        - x-api-key: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - external_id
              properties:
                image_url:
                  type: string
                  format: uri
                  description: Public URL of the image to process (required if image_base64 is not provided)
                  example: 'https://example.com/image.jpg'
                image_base64:
                  type: string
                  format: byte
                  description: |
                    Base64-encoded image data (required if image_url is not provided).
                    Supports JPEG, PNG, WebP, and GIF formats.
                    Maximum size: 10MB (encoded).
                    Can be provided with or without data URI prefix (e.g., "data:image/jpeg;base64,").
                  example: 'data:image/jpeg;base64,/9j/4AAQSkZJRg...'
                external_id:
                  type: string
                  description: Client-provided idempotency identifier
                  example: 'sync-scan-001'
              oneOf:
                - required: [image_url]
                - required: [image_base64]
            examples:
              product_scan_url:
                summary: Product recognition with URL
                value:
                  external_id: 'product-scan-123'
                  image_url: 'https://example.com/image.jpg'
              product_scan_base64:
                summary: Product recognition with base64 image
                value:
                  external_id: 'product-scan-123'
                  image_base64: 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD...'
      responses:
        '200':
          description: Processing completed successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CVResult'
              examples:
                success:
                  summary: Successful detection
                  value:
                    success: true
                    request_id: 'cv-req-abc123'
                    external_id: 'scan-001'
                    status: DONE
                    image_url: 'https://cdn.vfrog.ai/cv-requests/2025-10-22/api-key-id/uuid.jpg'
                    results:
                      - label: 'Product'
                        external_id: 'product-01'
                        bounding_box:
                          x: 100
                          y: 150
                          width: 200
                          height: 250
        '400':
          description: Invalid payload
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Missing API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: Invalid API key or no classes mapped
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '408':
          description: Request timeout (exceeded 29 seconds)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /v1/cv/requests/batch:
    post:
      summary: Submit a batch CV processing request
      description: |
        Process multiple images in parallel and return results for each image.
        Maximum of 10 images per request. Images are processed concurrently for faster throughput.

        **Use this endpoint for:**
        - Batch processing of multiple images
        - High-throughput scenarios
        - Processing image collections efficiently

        **Rate limit:** 10 requests/minute
      operationId: createBatchCvRequest
      tags:
        - Computer Vision
      security:
        - x-api-key: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - image_urls
              properties:
                image_urls:
                  type: array
                  items:
                    type: string
                    format: uri
                  minItems: 1
                  maxItems: 10
                  description: Array of public image URLs to process (1-10 images)
                  example: ['https://example.com/image1.jpg', 'https://example.com/image2.jpg']
                external_id:
                  type: string
                  description: Client-provided batch identifier for tracking
                  example: 'batch-001'
            examples:
              batch_scan:
                summary: Batch product recognition
                value:
                  image_urls:
                    - 'https://example.com/image1.jpg'
                    - 'https://example.com/image2.jpg'
                    - 'https://example.com/image3.jpg'
                  external_id: 'batch-scan-123'
      responses:
        '200':
          description: Batch processing completed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BatchCVResult'
              examples:
                success:
                  summary: Successful batch detection
                  value:
                    success: true
                    batch_id: 'batch-scan-123'
                    total_images: 3
                    results:
                      - image_url: 'https://example.com/image1.jpg'
                        request_id: 'cv-req-abc123'
                        status: 'DONE'
                        success: true
                        results:
                          - label: 'Product A'
                            external_id: 'product-01'
                            bounding_box:
                              x: 100
                              y: 150
                              width: 200
                              height: 250
                      - image_url: 'https://example.com/image2.jpg'
                        request_id: 'cv-req-def456'
                        status: 'DONE'
                        success: true
                        results:
                          - label: 'Product B'
                            external_id: 'product-02'
                            bounding_box:
                              x: 50
                              y: 75
                              width: 150
                              height: 200
                      - image_url: 'https://example.com/image3.jpg'
                        request_id: null
                        status: 'FAILED'
                        success: false
                        error: 'Image download failed'
                        results: []
        '400':
          description: Invalid payload (empty array, too many images, etc.)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                too_many_images:
                  summary: Too many images
                  value:
                    error: 'invalid_request'
                    message: 'Too many images. Maximum 10 images allowed, received 15'
                    error_code: 'TOO_MANY_IMAGES'
                empty_array:
                  summary: Empty image array
                  value:
                    error: 'invalid_request'
                    message: 'Missing required field: image_urls (must be a non-empty array)'
                    error_code: 'MISSING_IMAGE_URLS'
        '401':
          description: Missing or invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '402':
          description: Insufficient API calls balance
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                insufficient_balance:
                  summary: Insufficient balance
                  value:
                    error: 'payment_required'
                    message: 'Insufficient API calls balance'
                    error_code: 'INSUFFICIENT_BALANCE'
        '403':
          description: Invalid API key or no classes mapped
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  securitySchemes:
    x-api-key:
      type: apiKey
      in: header
      name: x-api-key
      description: API key from console.vfrog.ai
  schemas:
    Error:
      type: object
      properties:
        error:
          type: string
          description: Error type
        message:
          type: string
          description: Human-readable error message
        error_code:
          type: string
          description: Machine-readable error code
    CVResult:
      type: object
      properties:
        success:
          type: boolean
          description: Whether the request was successful
        request_id:
          type: string
          format: uuid
          description: Unique identifier for this request
        external_id:
          type: string
          description: Client-provided identifier
        status:
          type: string
          enum: [QUEUED, PROCESSING, DONE, ERROR]
          description: Current status of the request
        image_url:
          type: string
          format: uri
          description: URL of the processed image
        results:
          type: array
          items:
            $ref: '#/components/schemas/Detection'
          description: Detection results (empty if not done)
        error:
          type: string
          description: Error message if success is false
        response_code:
          type: integer
          description: HTTP response code from the CV service (if applicable)
    Detection:
      type: object
      properties:
        label:
          type: string
          description: Detected product label
        external_id:
          type: string
          description: External ID for the detected product
        bounding_box:
          $ref: '#/components/schemas/BoundingBox'
    BoundingBox:
      type: object
      properties:
        x:
          type: integer
          description: X coordinate of top-left corner
        y:
          type: integer
          description: Y coordinate of top-left corner
        width:
          type: integer
          description: Width of bounding box
        height:
          type: integer
          description: Height of bounding box
    BatchCVResult:
      type: object
      properties:
        success:
          type: boolean
          description: Whether the batch request was processed (individual images may still fail)
        batch_id:
          type: string
          description: Client-provided batch identifier (from external_id)
        total_images:
          type: integer
          description: Total number of images in the batch
        results:
          type: array
          items:
            $ref: '#/components/schemas/BatchImageResult'
          description: Results for each image in the batch
    BatchImageResult:
      type: object
      properties:
        image_url:
          type: string
          format: uri
          description: URL of the processed image
        request_id:
          type: string
          format: uuid
          nullable: true
          description: Unique identifier for this image's request (null if failed before processing)
        status:
          type: string
          enum: [DONE, FAILED]
          description: Processing status for this image
        success:
          type: boolean
          description: Whether this image was processed successfully
        error:
          type: string
          nullable: true
          description: Error message if processing failed
        results:
          type: array
          items:
            $ref: '#/components/schemas/Detection'
          description: Detection results (empty if failed)
        response_code:
          type: integer
          nullable: true
          description: HTTP response code from the CV service (if applicable)
