openapi: 3.1.0
info:
  title: LayerBack Conversion API
  version: "1.0"
  description: |
    Convert diagram images (PNG, JPEG, WebP) into fully editable
    Visio (VSDX), PowerPoint (PPTX), draw.io, and SVG files.
    Every shape, connector, and label is rebuilt as a native object —
    not an image embedded in a file container.

    Get an API key at https://layerback.com/settings/apikeys.
    One conversion costs 10 credits and includes all output formats.
  contact:
    url: https://layerback.com/docs/api
servers:
  - url: https://layerback.com/api/v1
security:
  - apiKey: []
paths:
  /convert:
    post:
      summary: Start a conversion
      description: |
        Send raw image bytes as the request body for images under 4 MB
        (request bodies are capped at about 4.5 MB). For images up to
        20 MB, upload through `POST /uploads` first and send
        `{"key": "..."}` as JSON. Poll the job endpoint, or pass
        `callback_url` to receive a completion webhook.
      operationId: startConversion
      parameters:
        - name: callback_url
          in: query
          required: false
          description: |
            Public https URL that receives a POST when the job finishes
            (both success and failure):
            `{"job_id", "status", "total_seconds", "error", "error_code", "input_kind", "formats"}`.
          schema:
            type: string
            format: uri
      requestBody:
        required: true
        content:
          application/octet-stream:
            schema:
              type: string
              format: binary
          application/json:
            schema:
              type: object
              required: [key]
              properties:
                key:
                  type: string
                  description: The `key` returned by `POST /uploads`, after the image was PUT to `upload_url`.
      responses:
        "202":
          description: Conversion started
          content:
            application/json:
              schema:
                type: object
                properties:
                  job_id: { type: string, format: uuid }
        "400": { description: Empty body, invalid upload key, or invalid callback_url }
        "401": { description: Invalid API key }
        "402": { description: Insufficient credits }
        "404": { description: Upload key has no uploaded image }
        "413": { description: Image exceeds 20 MB, or request body over about 4.5 MB (use /uploads) }
        "415": { description: Body is not PNG, JPEG, or WebP }
        "429": { description: Rate limit exceeded }
        "503": { description: Conversion service unavailable (credits refunded) }
  /uploads:
    post:
      summary: Get an upload URL for a large image
      description: |
        Free. Returns a presigned URL valid for 15 minutes. PUT the image
        bytes to `upload_url` with the same Content-Type, then call
        `POST /convert` with `{"key": "<key>"}`. Images up to 20 MB.
      operationId: createUpload
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [content_type]
              properties:
                content_type:
                  type: string
                  enum: [image/png, image/jpeg, image/webp]
      responses:
        "200":
          description: Upload URL created
          content:
            application/json:
              schema:
                type: object
                properties:
                  key: { type: string }
                  upload_url: { type: string, format: uri }
                  method: { type: string, enum: [PUT] }
                  headers: { type: object, additionalProperties: { type: string } }
                  expires_in: { type: integer, description: Seconds }
        "401": { description: Invalid API key }
        "415": { description: Unsupported content_type }
        "429": { description: Rate limit exceeded }
  /jobs/{jobId}:
    get:
      summary: Get job status
      operationId: getJob
      parameters:
        - name: jobId
          in: path
          required: true
          schema: { type: string, format: uuid }
      responses:
        "200":
          description: Current job state
          content:
            application/json:
              schema:
                type: object
                properties:
                  job_id: { type: string, format: uuid }
                  status:
                    type: string
                    enum: [queued, running, succeeded, failed]
                  total_seconds: { type: number }
                  formats:
                    type: array
                    items: { type: string }
                    description: Available once succeeded (vsdx, pptx, drawio, svg, ir, preview)
                  input_kind:
                    type: string
                    enum: [diagram, infographic, photo, document, id_document, screenshot, table_receipt, blank]
                    description: |
                      How the upload was classified. diagram / infographic are rebuilt as
                      editable shapes; document / table_receipt / screenshot keep the image
                      with its text replaced by editable text; photo / id_document are
                      embedded as an image.
                  error_code:
                    type: string
                    description: Present on failure when the cause is known, e.g. blank_input (refunded).
        "401": { description: Invalid API key }
        "404": { description: Unknown job }
  /jobs/{jobId}/download:
    get:
      summary: Download an artifact
      description: |
        Responds with a 302 redirect to a short-lived download URL —
        follow redirects (`curl -L`). Downloads are free and repeatable.
      operationId: downloadArtifact
      parameters:
        - name: jobId
          in: path
          required: true
          schema: { type: string, format: uuid }
        - name: format
          in: query
          required: false
          schema:
            type: string
            enum: [vsdx, pptx, drawio, svg, ir, preview]
            default: vsdx
      responses:
        "302": { description: Redirect to the artifact }
        "200":
          description: Artifact bytes (fallback path)
          content:
            application/octet-stream:
              schema: { type: string, format: binary }
        "401": { description: Invalid API key }
        "404": { description: Unknown job or artifact not ready }
components:
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: x-api-key
