openapi: 3.0.3
info:
  title: Make-QR Public API
  version: 1.0.0
  description: |
    Stable endpoint for QR generation. Optimized for LLM / tool use.
servers:
  - url: https://make-qr.com/api
  - url: /api

tags:
  - name: qr
    description: QR code generation endpoints

paths:
  /qr:
    get:
      operationId: generateQr
      tags: [qr]
      summary: Generate a QR code
      description: |
        Returns a QR image (SVG or PNG) for the provided payload.
        - `size`: target output image size in **pixels** (internally mapped to module `scale`).
        - `margin`: quiet zone in **modules**, not pixels.
      parameters:
        - in: query
          name: data
          required: true
          schema: { type: string }
          description: Payload encoded in the QR (URL, text, etc.)
          examples:
            url: { summary: URL payload, value: https://make-qr.com }
            text: { summary: Text payload, value: Hello world }
        - in: query
          name: format
          required: false
          schema:
            type: string
            enum: [svg, png]
            default: svg
          description: Output image format.
          examples:
            svg: { value: svg }
            png: { value: png }
        - in: query
          name: size
          required: false
          schema:
            type: integer
            minimum: 128
            maximum: 4096
            default: 1024
          description: Target image size (px). Internally converted to module `scale`.
          examples:
            hd: { value: 1024 }
            small: { value: 256 }
        - in: query
          name: ec
          required: false
          schema:
            type: string
            enum: [L, M, Q, H]
            default: Q
          description: Error correction level.
          examples:
            default: { value: Q }
            max: { value: H }
        - in: query
          name: margin
          required: false
          schema:
            type: integer
            minimum: 0
            maximum: 10
            default: 2
          description: Quiet zone size **in modules** (not pixels).
          examples:
            default: { value: 2 }
            none: { value: 0 }
        - in: query
          name: fg
          required: false
          schema:
            type: string
            pattern: "^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$"
            default: "#000000"
          description: Foreground color (hex).
          examples:
            black: { value: "#000" }
            navy: { value: "#001f3f" }
        - in: query
          name: bg
          required: false
          schema:
            type: string
            pattern: "^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$"
            default: "#ffffff"
          description: Background color (hex).
          examples:
            white: { value: "#fff" }
            cream: { value: "#f9f7f1" }
      responses:
        "200":
          description: QR image
          headers:
            Cache-Control:
              $ref: "#/components/headers/CacheControlPublic"
            X-MQ-Warning:
              $ref: "#/components/headers/XMQWarning"
            Content-Disposition:
              $ref: "#/components/headers/ContentDispositionInline"
            X-Content-Type-Options:
              $ref: "#/components/headers/XContentTypeOptions"
          content:
            image/svg+xml:
              schema:
                type: string
              examples:
                sample:
                  summary: Example SVG
                  externalValue: https://make-qr.com/api/qr?data=Hello&format=svg&size=512
            image/png:
              schema:
                type: string
                format: binary
              examples:
                sample:
                  summary: Example PNG
                  externalValue: https://make-qr.com/api/qr?data=Hello&format=png&size=512
        "400":
          description: Missing or invalid parameters
          headers:
            Cache-Control:
              $ref: "#/components/headers/CacheControlNoStore"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              examples:
                missingData:
                  summary: Missing data
                  value:
                    code: INVALID_ARGUMENT
                    message: "Missing ?data"
        "413":
          description: Payload too large
          headers:
            Cache-Control:
              $ref: "#/components/headers/CacheControlNoStore"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              examples:
                tooLarge:
                  value:
                    code: PAYLOAD_TOO_LARGE
                    message: "Payload too large"
        "415":
          description: Requested output format not supported on this host
          headers:
            Cache-Control:
              $ref: "#/components/headers/CacheControlNoStore"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              examples:
                pngUnsupported:
                  summary: PNG not available (GD missing)
                  value:
                    code: UNSUPPORTED_MEDIA_TYPE
                    message: "PNG output is not supported on this host (GD extension missing). Use format=svg."
        "429":
          description: Too many requests
          headers:
            Cache-Control:
              $ref: "#/components/headers/CacheControlNoStore"
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
                minimum: 1
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              examples:
                rateLimited:
                  value:
                    code: RATE_LIMITED
                    message: "Too many requests. Please retry later."
        "500":
          description: Server error
          headers:
            Cache-Control:
              $ref: "#/components/headers/CacheControlNoStore"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              examples:
                serverError:
                  value:
                    code: INTERNAL
                    message: "QR generation error"
        "501":
          description: (Deprecated) Legacy response when PNG not supported on host
          headers:
            Cache-Control:
              $ref: "#/components/headers/CacheControlNoStore"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              examples:
                deprecatedPngUnsupported:
                  value:
                    code: NOT_IMPLEMENTED
                    message: "PNG output is not supported on this host (GD extension missing). Use format=svg."

components:
  headers:
    CacheControlPublic:
      description: Public, long-term cache for success responses.
      schema:
        type: string
        example: "public, max-age=31536000, immutable"
    CacheControlNoStore:
      description: Do not cache error responses.
      schema:
        type: string
        example: "no-store"
    XMQWarning:
      description: Optional warning header (e.g., low-contrast).
      schema:
        type: string
        example: "low-contrast"
    ContentDispositionInline:
      description: Suggested filename for inline rendering.
      schema:
        type: string
        example: 'inline; filename="qr.svg"'
    XContentTypeOptions:
      description: Security header.
      schema:
        type: string
        example: "nosniff"
  schemas:
    ErrorResponse:
      type: object
      required: [code, message]
      properties:
        code:
          type: string
          description: Stable, machine-readable error code.
          examples:
            - INVALID_ARGUMENT
            - PAYLOAD_TOO_LARGE
            - UNSUPPORTED_MEDIA_TYPE
            - RATE_LIMITED
            - INTERNAL
            - NOT_IMPLEMENTED
        message:
          type: string
          description: Human-readable error message.
        details:
          description: Optional extra info (e.g., which parameter failed validation).
          oneOf:
            - type: object
            - type: array
            - type: string
