{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/cnvs-app/json-schema/cnvs-app-add-image-request-schema.json",
  "title": "AddImageRequest",
  "x-generated": "2026-11-04",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/cnvs-app-openapi.yml#/components/schemas/AddImageRequest",
  "type": "object",
  "required": [
    "x",
    "y",
    "width",
    "height",
    "dataUrl"
  ],
  "properties": {
    "id": {
      "type": "string"
    },
    "x": {
      "type": "number"
    },
    "y": {
      "type": "number"
    },
    "width": {
      "type": "number",
      "description": "Displayed width in board px."
    },
    "height": {
      "type": "number",
      "description": "Displayed height in board px."
    },
    "dataUrl": {
      "type": "string",
      "description": "Data URL: `data:image/(png|jpeg|gif|webp|svg+xml);base64,<payload>`. Max ~900 kB total. Hosted URLs NOT accepted — fetch + base64-encode first. Only image payloads are accepted: the decoded header bytes are sniffed (PNG/JPEG/GIF/WebP magic bytes or an `<svg>` root), so ordinary PDFs, archives and other files relabeled as images are rejected with 400 (a header check, not a full image decode).",
      "pattern": "^data:image/(png|jpeg|gif|webp|svg\\+xml);base64,"
    },
    "thumbDataUrl": {
      "type": [
        "string",
        "null"
      ],
      "description": "Optional tiny thumbnail (≤8 kB JPEG/PNG/WebP, ~64 px on long edge). Embedded into SVG previews so other AI viewers see the image instead of a placeholder."
    },
    "author": {
      "$ref": "#/$defs/AuthorTag"
    }
  },
  "$defs": {
    "AuthorTag": {
      "type": "string",
      "description": "Author tag, charset `[A-Za-z0-9:_\\-.]`, max 80 chars. Defaults to `ai:rest` for REST mutations. Use `ai:<your-label>` (e.g. `ai:claude`, `ai:mybot`) so humans can tell AI edits apart.",
      "pattern": "^[A-Za-z0-9:_\\-.]{1,80}$"
    }
  }
}