---
openapi: 3.1.0
components:
  schemas:
    GenerateImageRequest:
      description: Request to generate an image from a template with variable substitution
      type: object
      required:
      - variables
      properties:
        variables:
          type: object
          additionalProperties:
            type: string
          description: Map of variable names to values
          examples:
          - customer_name: John Doe
            discount_code: SAVE20
        format:
          type: string
          description: Output image format
          examples:
          - png
          enum:
          - png
          - jpeg
          - webp
          - pdf
          pattern: ^(png|jpeg|webp|pdf)$
        options:
          $ref: "#/components/schemas/RenderOptions"
        formatOrDefault:
          type: string
    OffsetDateTime:
      type: string
      format: date-time
      examples:
      - 2022-03-10T12:15:50-04:00
    OutputDpi:
      type: integer
      format: int32
      enum:
      - 96
      - 150
      - 300
    ProjectListItem:
      type: object
      properties:
        id:
          $ref: "#/components/schemas/UUID"
        name:
          type: string
        description:
          type: string
        templateCount:
          type: integer
          format: int32
        visibility:
          type: string
        updatedAt:
          $ref: "#/components/schemas/OffsetDateTime"
    RenderOptions:
      description: "Options controlling output quality, resolution, and appearance.\
        \ Specify EITHER outputDpi (print DPI tiers) OR scale (screen pixel multiplication),\
        \ not both; when both are provided, outputDpi takes priority. When neither\
        \ is provided, renders default to the design's stored export DPI for print-intent\
        \ designs, to 300 DPI for PDF output, and to 1x for screen designs otherwise."
      type: object
      properties:
        outputDpi:
          description: "DPI tier for output image (SCREEN=96, DRAFT=150, PRINT=300).\
            \ Takes priority over scale when both are set."
          type: string
          $ref: "#/components/schemas/OutputDpi"
        scale:
          type: integer
          format: int32
          maximum: 4
          minimum: 1
          description: Integer scale multiplier for output image
        quality:
          type: integer
          format: int32
          maximum: 100
          minimum: 1
          description: Quality for JPEG/WebP output
        backgroundColor:
          type: string
          description: Background color override in hex format
    TemplateDetailResponse:
      description: Template detail with metadata and variable definitions
      type: object
      properties:
        id:
          description: Unique template identifier
          type: string
          examples:
          - 019463b8-1234-7890-abcd-ef1234567890
          $ref: "#/components/schemas/UUID"
        name:
          type: string
          description: Template name
          examples:
          - Summer Sale Coupon
        description:
          type: string
          description: Optional template description
          examples:
          - 20% off coupon for summer sale campaign
        projectId:
          description: Project ID this template belongs to
          type: string
          examples:
          - 019463b8-abcd-7890-1234-ef1234567890
          $ref: "#/components/schemas/UUID"
        viewport:
          $ref: "#/components/schemas/ViewportInfo"
        viewportUnit:
          type: string
          description: Viewport dimension unit
          examples:
          - px
        viewportExportDpi:
          type: integer
          format: int32
          description: Export DPI for raster output
          examples:
          - 96
        viewportOutputIntent:
          type: string
          description: Output intent for PDF/print workflows
          examples:
          - screen
        visibility:
          type: string
          description: Template visibility
          examples:
          - SHARED
          enum:
          - PRIVATE
          - SHARED
        createdAt:
          $ref: "#/components/schemas/OffsetDateTime"
        updatedAt:
          $ref: "#/components/schemas/OffsetDateTime"
        variables:
          type: array
          items:
            $ref: "#/components/schemas/VariableInfo"
    TemplateListItem:
      type: object
      properties:
        id:
          $ref: "#/components/schemas/UUID"
        name:
          type: string
        description:
          type: string
        projectId:
          $ref: "#/components/schemas/UUID"
        updatedAt:
          $ref: "#/components/schemas/OffsetDateTime"
        visibility:
          type: string
    UUID:
      type: string
      format: uuid
      pattern: "[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}"
    VariableInfo:
      type: object
      description: Variable definition for template substitution
      properties:
        name:
          type: string
          description: Variable name (use as key in variables map)
          examples:
          - customer_name
        type:
          type: string
          description: Variable type
          examples:
          - text
          enum:
          - text
          - number
          - email
          - url
          - phone
          - date
          - qrcode
          - barcode
          - image
        label:
          type: string
          description: Human-readable label
          examples:
          - Customer Name
        required:
          type: boolean
          description: Whether this variable is required
          examples:
          - true
        defaultValue:
          type: string
          description: Default value if not provided
          examples:
          - John Doe
        validation:
          $ref: "#/components/schemas/VariableValidationInfo"
    VariableValidationInfo:
      type: object
      properties:
        minLength:
          type: integer
          format: int32
        maxLength:
          type: integer
          format: int32
        pattern:
          type: string
        min:
          type: number
          format: double
        max:
          type: number
          format: double
        options:
          type: array
          items:
            type: string
    ViewportInfo:
      type: object
      properties:
        width:
          type: integer
          format: int32
        height:
          type: integer
          format: int32
  securitySchemes:
    apiKey:
      type: apiKey
      description: API key for authentication. Contact admin for access.
      name: X-Api-Key
      in: header
paths:
  /api/v1/projects:
    get:
      summary: List projects
      description: "Returns a paginated list of projects visible to the API key owner:\
        \ own projects (PRIVATE or SHARED) plus projects shared by other org members.\
        \ Each item includes a visibility field indicating PRIVATE or SHARED."
      tags:
      - Public API
      parameters:
      - description: Number of items per page (max 100)
        example: 20
        name: limit
        in: query
        schema:
          type: integer
          format: int32
          default: 20
      - description: Page number (0-based)
        example: 0
        name: page
        in: query
        schema:
          type: integer
          format: int32
          default: 0
      responses:
        "200":
          description: Project list retrieved successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProjectListItem"
        "401":
          description: Missing or invalid API key
          content:
            application/json: {}
      security:
      - apiKey: []
  /api/v1/projects/{projectId}/templates:
    get:
      summary: List templates in a project
      description: "Returns a paginated list of templates in the given project that\
        \ are visible to the API key owner: own templates (PRIVATE or SHARED) plus\
        \ templates shared by other org members. Does not include full canvas data."
      tags:
      - Public API
      parameters:
      - description: Project ID
        required: true
        name: projectId
        in: path
        schema:
          $ref: "#/components/schemas/UUID"
      - description: Number of items per page (max 100)
        example: 20
        name: limit
        in: query
        schema:
          type: integer
          format: int32
          default: 20
      - description: Page number (0-based)
        example: 0
        name: page
        in: query
        schema:
          type: integer
          format: int32
          default: 0
      responses:
        "200":
          description: Template list retrieved successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TemplateListItem"
        "401":
          description: Missing or invalid API key
          content:
            application/json: {}
      security:
      - apiKey: []
  /api/v1/templates/{templateId}:
    get:
      summary: Get template detail
      description: "Returns full template metadata including name, description, project,\
        \ viewport dimensions, and all available variables with their types, labels,\
        \ default values, and validation rules. The template owner can access PRIVATE\
        \ templates; other org members can only access SHARED ones. Use this endpoint\
        \ to discover what variables can be substituted when generating images."
      tags:
      - Public API
      parameters:
      - description: Template ID
        required: true
        name: templateId
        in: path
        schema:
          $ref: "#/components/schemas/UUID"
      responses:
        "200":
          description: Template detail retrieved successfully
          headers:
            ETag:
              description: Entity tag for conditional requests (based on updatedAt)
            Cache-Control:
              description: "private, max-age=60"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TemplateDetailResponse"
        "401":
          description: Missing or invalid API key
          content:
            application/json: {}
        "404":
          description: Template not found or not accessible
          content:
            application/json: {}
      security:
      - apiKey: []
  /api/v1/templates/{templateId}/generate:
    post:
      summary: Generate image from template
      description: "Generates an image from a template with variable substitution.\
        \ Provide variable values as a key-value map. Variable names must match those\
        \ returned by the GET /{templateId} endpoint. Returns binary image data. Resolution\
        \ defaults: when options contain neither outputDpi nor scale, templates with\
        \ outputIntent 'print' render at their stored export DPI (viewportExportDpi\
        \ from the GET /{templateId} endpoint), PDF output defaults to 300 DPI, and\
        \ 'screen' templates render at 1x (96 DPI) otherwise. Set outputDpi or scale\
        \ explicitly to override; if both are provided, outputDpi wins."
      tags:
      - Public API
      parameters:
      - description: Template ID
        required: true
        name: templateId
        in: path
        schema:
          $ref: "#/components/schemas/UUID"
      requestBody:
        description: Generation request with variables and optional render settings
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/GenerateImageRequest"
        required: true
      responses:
        "200":
          description: Image generated successfully
          headers:
            X-Request-Id:
              description: Unique identifier for this request
            X-Template-Id:
              description: Template ID used for rendering
            X-Quota-Limit:
              description: Monthly API quota ceiling for the organisation
            X-Quota-Remaining:
              description: Remaining renders this billing period
            X-Quota-Reset:
              description: ISO 8601 UTC datetime when the quota resets
          content:
            image/png: {}
            image/jpeg: {}
            image/webp: {}
            application/pdf: {}
        "400":
          description: Variable validation error — missing required variables or validation
            rules failed
          content:
            application/json: {}
        "401":
          description: Missing or invalid API key
          content:
            application/json: {}
        "404":
          description: Template not found
          content:
            application/json: {}
        "429":
          description: Monthly quota exceeded — retry after the indicated seconds
          headers:
            Retry-After:
              description: Seconds until quota resets at start of next month
            X-RateLimit-Remaining:
              description: Always 0 when quota is exceeded
          content:
            application/problem+json: {}
        "502":
          description: Image generator service error
          content:
            application/json: {}
        "503":
          description: Image generator service unavailable
          content:
            application/json: {}
      security:
      - apiKey: []
tags:
- name: Public API
  description: Public API for template description and image generation (requires
    API key)
info:
  title: Zandovi API
  version: 1.0.0
  description: API for template management and image rendering
  contact:
    name: Zandovi Team
servers:
- url: https://app.zandovi.com
  description: Zandovi public API
