{"openapi":"3.1.0","info":{"title":"Layerre API Documentation","description":"Backend API for the Layerre platform","version":"0.1.0"},"paths":{"/v1/template":{"post":{"tags":["Templates"],"summary":"Create Template","description":"Create a template from a Canva URL.\n\nThis endpoint processes a Canva URL and extracts template information\nincluding layers, dimensions, and other metadata.","operationId":"create_template_v1_template_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateCreateRequest"}}},"required":true},"responses":{"201":{"description":"Template created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateResponse"}}}},"403":{"description":"Plan limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Canva URL not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"400":{"description":"Invalid or inaccessible Canva URL (format, sharing, or no design content returned—e.g. Brand Template without access).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Design type is not supported","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"504":{"description":"Import timeout — retry the same request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/template/{template_id}":{"get":{"tags":["Templates"],"summary":"Get Template","description":"Get a template by ID with all its layers. Refreshes signed URLs for all image layers.","operationId":"get_template_v1_template__template_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"responses":{"200":{"description":"Template retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateResponse"}}}},"404":{"description":"Template not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["Templates"],"summary":"Update Template","description":"Update a template (name, width, height, backgrounds) and/or layers.","operationId":"update_template_v1_template__template_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateUpdateRequest"}}}},"responses":{"200":{"description":"Template updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateResponse"}}}},"404":{"description":"Template not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Templates"],"summary":"Delete Template","description":"Soft delete a template.","operationId":"delete_template_v1_template__template_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"responses":{"204":{"description":"Template deleted successfully"},"404":{"description":"Template not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/templates/tags":{"get":{"tags":["Templates"],"summary":"List Template Tags","description":"List all unique tags for the current user's templates with their counts.\nSorted by count descending, then alphabetically.","operationId":"list_template_tags_v1_templates_tags_get","responses":{"200":{"description":"List of tags with counts retrieved successfully","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/TagCountResponse"},"type":"array","title":"Response List Template Tags V1 Templates Tags Get"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/templates":{"get":{"tags":["Templates"],"summary":"List Templates","description":"List all templates for the current user, sorted by last modified. Includes variant counts.","operationId":"list_templates_v1_templates_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Number of templates to skip","default":0,"title":"Skip"},"description":"Number of templates to skip"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"description":"Maximum number of templates to return","default":100,"title":"Limit"},"description":"Maximum number of templates to return"},{"name":"include_layers","in":"query","required":false,"schema":{"type":"boolean","description":"Whether to include layers in the response (slower for large templates)","default":false,"title":"Include Layers"},"description":"Whether to include layers in the response (slower for large templates)"},{"name":"tag","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter templates to those that have this tag. Case-insensitive.","title":"Tag"},"description":"Filter templates to those that have this tag. Case-insensitive."},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"description":"Search templates by name (case-insensitive substring).","title":"Q"},"description":"Search templates by name (case-insensitive substring)."}],"responses":{"200":{"description":"List of templates retrieved successfully","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TemplateResponse"},"title":"Response List Templates V1 Templates Get"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/template/{template_id}/layer":{"post":{"tags":["Layers"],"summary":"Create Layer","description":"Create a new layer for a template.\n\nAccepts either img_url or text to create image or text layers respectively.","operationId":"create_layer_v1_template__template_id__layer_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LayerCreateRequest"}}}},"responses":{"201":{"description":"Layer created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LayerResponse"}}}},"400":{"description":"Bad request - invalid input or missing required properties","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Template not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/template/{template_id}/layer/{layer_id}":{"get":{"tags":["Layers"],"summary":"Get Layer","description":"Get a specific layer by ID. Refreshes signed URL if expired.","operationId":"get_layer_v1_template__template_id__layer__layer_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}},{"name":"layer_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Layer Id"}}],"responses":{"200":{"description":"Layer retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LayerResponse"}}}},"404":{"description":"Layer or template not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["Layers"],"summary":"Update Layer","description":"Update a layer.\n\nSupports updating text content, img_url, or any other layer\nproperties.","operationId":"update_layer_v1_template__template_id__layer__layer_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}},{"name":"layer_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Layer Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LayerUpdateRequest"}}}},"responses":{"200":{"description":"Layer updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LayerResponse"}}}},"404":{"description":"Layer or template not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Layers"],"summary":"Delete Layer","description":"Soft delete a layer.","operationId":"delete_layer_v1_template__template_id__layer__layer_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}},{"name":"layer_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Layer Id"}}],"responses":{"204":{"description":"Layer deleted successfully"},"404":{"description":"Layer or template not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/template/{template_id}/variant":{"post":{"tags":["Variants"],"summary":"Create Variant","description":"Render one variant per request from a template, optionally overriding layers.\n\nOverrides is an array of objects with layer_id (from GET /v1/template/{template_id})\nand optional properties; layers you omit keep template defaults.","operationId":"create_variant_v1_template__template_id__variant_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VariantCreateUpdateRequest"}}}},"responses":{"201":{"description":"Variant created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VariantResponse"}}}},"400":{"description":"Bad request - invalid input or no valid layers found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Plan limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Template not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"504":{"description":"Render timeout — retry the same request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/template/{template_id}/variant/bulk":{"post":{"tags":["Variants"],"summary":"Create Variants Bulk","description":"Create multiple variants in one request (single export_type per batch).\n\nWhen combine_pdf=true (Plus+ only, PDF export), renders all items into one\nmulti-page PDF via a single Chromium print pass instead of per-item files.","operationId":"create_variants_bulk_v1_template__template_id__variant_bulk_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VariantBulkCreateRequest"}}}},"responses":{"200":{"description":"Bulk variant creation completed (may be partial)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VariantBulkCreateResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Plan limit or feature gate","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Template not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"504":{"description":"Render timeout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/template/{template_id}/variant/{variant_id}":{"get":{"tags":["Variants"],"summary":"Get Variant","description":"Get a variant by ID. Refreshes signed URL if expired.","operationId":"get_variant_v1_template__template_id__variant__variant_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}},{"name":"variant_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Variant Id"}}],"responses":{"200":{"description":"Variant retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VariantResponse"}}}},"404":{"description":"Variant or template not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Variants"],"summary":"Delete Variant","description":"Soft delete a variant.","operationId":"delete_variant_v1_template__template_id__variant__variant_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}},{"name":"variant_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Variant Id"}}],"responses":{"204":{"description":"Variant deleted successfully"},"404":{"description":"Variant or template not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/template/{template_id}/variants":{"get":{"tags":["Variants"],"summary":"List Template Variants","description":"List all variants for a template. Refreshes signed URLs for all variants.","operationId":"list_template_variants_v1_template__template_id__variants_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}},{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Number of variants to skip","default":0,"title":"Skip"},"description":"Number of variants to skip"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"description":"Maximum number of variants to return","default":100,"title":"Limit"},"description":"Maximum number of variants to return"}],"responses":{"200":{"description":"List of variants retrieved successfully","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/VariantResponse"},"title":"Response List Template Variants V1 Template  Template Id  Variants Get"}}}},"404":{"description":"Template not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/analyze/canva-design":{"post":{"tags":["Analyze"],"summary":"Analyze Canva design","description":"Extract colors, fonts, and images from a public Canva share URL.","operationId":"analyze_canva_design_v1_analyze_canva_design_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyzeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyzeResponse"}}}},"400":{"description":"Invalid Canva URL"},"429":{"description":"Rate limit exceeded"},"500":{"description":"Internal server error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AnalyzeRequest":{"properties":{"canva_url":{"type":"string","maxLength":2083,"minLength":1,"format":"uri","title":"Canva Url"}},"type":"object","required":["canva_url"],"title":"AnalyzeRequest"},"AnalyzeResponse":{"properties":{"colors":{"items":{"type":"string"},"type":"array","title":"Colors"},"fonts":{"items":{"$ref":"#/components/schemas/FontInfo"},"type":"array","title":"Fonts"},"images":{"items":{"$ref":"#/components/schemas/ImageInfo"},"type":"array","title":"Images"},"dimensions":{"additionalProperties":{"type":"integer"},"type":"object","title":"Dimensions"},"backgroundColor":{"type":"string","title":"Backgroundcolor"}},"type":"object","required":["colors","fonts","images","dimensions","backgroundColor"],"title":"AnalyzeResponse"},"CombinedPdfResult":{"properties":{"url":{"type":"string","title":"Url","description":"Signed URL of the combined multi-page PDF"},"signed_url_expiry":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Signed Url Expiry","description":"When the combined PDF signed URL expires"},"variant":{"anyOf":[{"$ref":"#/components/schemas/VariantResponse"},{"type":"null"}],"description":"Persisted variant record for the combined PDF (if saved)"}},"type":"object","required":["url"],"title":"CombinedPdfResult"},"ErrorResponse":{"properties":{"detail":{"type":"string","title":"Detail","description":"Error message describing what went wrong"}},"type":"object","required":["detail"],"title":"ErrorResponse","description":"Standard error response schema"},"ExportType":{"type":"string","enum":["png","pdf","jpeg","webp"],"title":"ExportType","description":"Export format options for variants"},"FlexibleLayerProperties":{"properties":{"width":{"anyOf":[{"type":"number","maximum":10000.0,"minimum":1.0},{"type":"null"}],"title":"Width","description":"Layer width in pixels","example":100},"height":{"anyOf":[{"type":"number","maximum":10000.0,"minimum":1.0},{"type":"null"}],"title":"Height","description":"Layer height in pixels","example":100},"color":{"anyOf":[{"type":"string","maxLength":7},{"type":"null"}],"title":"Color","description":"Color in hex format (#RRGGBB)","example":"#FF0000"},"rotation":{"anyOf":[{"type":"number","maximum":360.0,"minimum":-360.0},{"type":"null"}],"title":"Rotation","description":"Rotation angle in degrees","example":0},"text":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}],"title":"Text","description":"Text content","example":"Hello World"},"font_size":{"anyOf":[{"type":"number","maximum":2000.0,"minimum":1.0},{"type":"null"}],"title":"Font Size","description":"Font size in pixels","example":16},"font_name":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Font Name","description":"Font family name","example":"Arial"},"font_style":{"anyOf":[{"$ref":"#/components/schemas/FontStyle"},{"type":"null"}]},"text_align":{"anyOf":[{"$ref":"#/components/schemas/TextAlign"},{"type":"null"}]},"text_direction":{"anyOf":[{"type":"string","const":"rtl"},{"type":"null"}],"title":"Text Direction","description":"Text direction; only set for right-to-left text (Arabic, Hebrew, etc.). Absent/null means LTR.","example":"rtl"},"letter_spacing":{"anyOf":[{"type":"number","maximum":800.0,"minimum":-200.0},{"type":"null"}],"title":"Letter Spacing","description":"Letter spacing in pixels","example":0},"line_spacing":{"anyOf":[{"type":"number","maximum":2500.0,"minimum":500.0},{"type":"null"}],"title":"Line Spacing","description":"Line spacing in pixels","example":1000},"vertical_align":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vertical Align","description":"Vertical alignment for text (e.g. 'middle')","example":"middle"},"img_url":{"anyOf":[{"type":"string","maxLength":512000},{"type":"null"}],"title":"Img Url","description":"Image URL for image layers: public HTTPS, data URI, or Google Drive link shared for viewing.","example":"https://example.com/image.png"},"image_fit":{"anyOf":[{"$ref":"#/components/schemas/ImageFitValue"},{"type":"null"}],"description":"How raster images fit within the image layer bounds: 'cover' fills the box and may crop, while 'contain' keeps the full image visible and may leave empty space.","example":"contain"},"image_position":{"anyOf":[{"$ref":"#/components/schemas/ImagePositionValue"},{"type":"null"}],"description":"Crop anchor for image-in-frame layers (e.g. circles). Controls which part of the image stays in frame when using 'cover' fit, or where the image is anchored when using 'contain'. Only applies to layers with a shape mask (e.g. circular frames). Values: top-left, top-center, top-right, center-left, center, center-right, bottom-left, bottom-center, bottom-right.","example":"top-center"},"signed_url_expiry":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Signed Url Expiry"},"opacity":{"anyOf":[{"type":"number","maximum":1.0,"minimum":0.0},{"type":"null"}],"title":"Opacity","description":"Opacity value (0.0 = fully transparent, 1.0 = fully opaque)","example":1.0},"flip_horizontal":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Flip Horizontal","description":"Flip the layer horizontally","example":false},"flip_vertical":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Flip Vertical","description":"Flip the layer vertically","example":false}},"type":"object","title":"FlexibleLayerProperties","description":"Flexible layer properties that can handle any combination of text and image properties"},"FontInfo":{"properties":{"name":{"type":"string","title":"Name"},"weights":{"items":{"type":"string"},"type":"array","title":"Weights"},"styles":{"items":{"type":"string"},"type":"array","title":"Styles"}},"type":"object","required":["name","weights","styles"],"title":"FontInfo"},"FontStyle":{"properties":{"weight":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Weight"},"italic":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Italic"},"underline":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Underline"}},"type":"object","title":"FontStyle","description":"Font styling properties"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ImageFitValue":{"type":"string","enum":["cover","contain"],"title":"ImageFitValue"},"ImageInfo":{"properties":{"id":{"type":"string","title":"Id"},"url":{"type":"string","title":"Url"},"thumbnailUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Thumbnailurl"}},"type":"object","required":["id","url"],"title":"ImageInfo"},"ImageLayerProperties":{"properties":{"width":{"anyOf":[{"type":"number","maximum":10000.0,"minimum":1.0},{"type":"null"}],"title":"Width","description":"Layer width in pixels","example":100},"height":{"anyOf":[{"type":"number","maximum":10000.0,"minimum":1.0},{"type":"null"}],"title":"Height","description":"Layer height in pixels","example":100},"color":{"anyOf":[{"type":"string","maxLength":7},{"type":"null"}],"title":"Color","description":"Color in hex format (#RRGGBB)","example":"#FF0000"},"rotation":{"anyOf":[{"type":"number","maximum":360.0,"minimum":-360.0},{"type":"null"}],"title":"Rotation","description":"Rotation angle in degrees","example":0},"img_url":{"type":"string","maxLength":512000,"title":"Img Url","description":"Image URL or data URI","default":"","example":"https://example.com/image.png"},"image_fit":{"anyOf":[{"$ref":"#/components/schemas/ImageFitValue"},{"type":"null"}],"description":"How raster images fit within the image layer bounds: 'cover' fills the box and may crop, while 'contain' keeps the full image visible and may leave empty space.","example":"cover"},"signed_url_expiry":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Signed Url Expiry"},"opacity":{"anyOf":[{"type":"number","maximum":1.0,"minimum":0.0},{"type":"null"}],"title":"Opacity","description":"Opacity value (0.0 = fully transparent, 1.0 = fully opaque)","example":1.0},"flip_horizontal":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Flip Horizontal","description":"Flip the layer horizontally","example":false},"flip_vertical":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Flip Vertical","description":"Flip the layer vertically","example":false}},"type":"object","title":"ImageLayerProperties","description":"Properties specific to image layers"},"ImagePositionValue":{"type":"string","enum":["top-left","top-center","top-right","center-left","center","center-right","bottom-left","bottom-center","bottom-right"],"title":"ImagePositionValue"},"Layer":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"template_id":{"type":"string","format":"uuid","title":"Template Id"},"name":{"type":"string","maxLength":100,"title":"Name","description":"Layer name","example":"Title Layer"},"layer_type":{"$ref":"#/components/schemas/LayerType"},"x":{"type":"number","maximum":10000.0,"minimum":-10000.0,"title":"X","description":"X position in pixels","default":0,"example":0},"y":{"type":"number","maximum":10000.0,"minimum":-10000.0,"title":"Y","description":"Y position in pixels","default":0,"example":0},"position":{"type":"integer","maximum":1999.0,"minimum":0.0,"title":"Position","description":"Z-order position (0=bottom/back, higher=top/front)","default":0,"example":0},"page_number":{"type":"integer","minimum":0.0,"title":"Page Number","description":"Page index within a multi-page template (0-based)","default":0,"example":0},"properties":{"$ref":"#/components/schemas/FlexibleLayerProperties"}},"type":"object","required":["id","template_id","name","layer_type","properties"],"title":"Layer"},"LayerCreateRequest":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Name","description":"Layer name","example":"Title Layer"},"layer_type":{"anyOf":[{"$ref":"#/components/schemas/LayerType"},{"type":"null"}],"description":"Layer type (will be inferred from properties if not provided)"},"x":{"type":"number","maximum":10000.0,"minimum":-10000.0,"title":"X","description":"X position in pixels","default":0,"example":0},"y":{"type":"number","maximum":10000.0,"minimum":-10000.0,"title":"Y","description":"Y position in pixels","default":0,"example":0},"properties":{"anyOf":[{"$ref":"#/components/schemas/TextLayerProperties"},{"$ref":"#/components/schemas/ImageLayerProperties"},{"type":"null"}],"title":"Properties"}},"type":"object","title":"LayerCreateRequest","description":"Request for creating a new layer"},"LayerResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"template_id":{"type":"string","format":"uuid","title":"Template Id"},"name":{"type":"string","maxLength":100,"title":"Name","description":"Layer name","example":"Title Layer"},"layer_type":{"$ref":"#/components/schemas/LayerType"},"x":{"type":"number","maximum":10000.0,"minimum":-10000.0,"title":"X","description":"X position in pixels","default":0,"example":0},"y":{"type":"number","maximum":10000.0,"minimum":-10000.0,"title":"Y","description":"Y position in pixels","default":0,"example":0},"position":{"type":"integer","maximum":1999.0,"minimum":0.0,"title":"Position","description":"Z-order position (0=bottom/back, higher=top/front)","default":0,"example":0},"page_number":{"type":"integer","minimum":0.0,"title":"Page Number","description":"Page index within a multi-page template (0-based)","default":0,"example":0},"properties":{"$ref":"#/components/schemas/FlexibleLayerProperties"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","template_id","name","layer_type","properties","created_at","updated_at"],"title":"LayerResponse"},"LayerType":{"type":"string","enum":["image","text"],"title":"LayerType","description":"Enum for layer types"},"LayerUpdateRequest":{"properties":{"id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Id","description":"Layer ID (required when updating layers as part of template update)"},"name":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Name","description":"Layer name","example":"Title Layer"},"layer_type":{"anyOf":[{"$ref":"#/components/schemas/LayerType"},{"type":"null"}]},"x":{"anyOf":[{"type":"number","maximum":10000.0,"minimum":-10000.0},{"type":"null"}],"title":"X","description":"X position in pixels","example":0},"y":{"anyOf":[{"type":"number","maximum":10000.0,"minimum":-10000.0},{"type":"null"}],"title":"Y","description":"Y position in pixels","example":0},"position":{"anyOf":[{"type":"integer","maximum":1999.0,"minimum":0.0},{"type":"null"}],"title":"Position","description":"Z-order position (0=bottom/back, higher=top/front) for reordering layers","example":0},"properties":{"anyOf":[{"$ref":"#/components/schemas/FlexibleLayerProperties"},{"type":"null"}]}},"type":"object","title":"LayerUpdateRequest"},"TagCountResponse":{"properties":{"name":{"type":"string","title":"Name","description":"Tag name"},"count":{"type":"integer","title":"Count","description":"Number of templates with this tag"}},"type":"object","required":["name","count"],"title":"TagCountResponse","description":"A tag and the number of templates it is applied to."},"TemplateCreateRequest":{"properties":{"canva_url":{"type":"string","maxLength":2048,"title":"Canva Url","description":"Canva share URL","example":"https://www.canva.com/design/..."},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Tags","description":"Initial tags for the template.","example":["campaign","summer-2026"]}},"type":"object","required":["canva_url"],"title":"TemplateCreateRequest"},"TemplateResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","maxLength":100,"title":"Name","description":"Template name","example":"My Template"},"width":{"type":"integer","maximum":50000.0,"minimum":1.0,"title":"Width","description":"Template width in pixels","example":800},"height":{"type":"integer","maximum":50000.0,"minimum":1.0,"title":"Height","description":"Template height in pixels","example":600},"source_url":{"type":"string","maxLength":2048,"title":"Source Url","description":"Original Canva URL","example":"https://www.canva.com/design/..."},"background_color":{"type":"string","maxLength":7,"title":"Background Color","description":"Background color of the first page (page 0) in hex format","example":"#FFFFFF"},"page_backgrounds":{"additionalProperties":{"type":"string"},"type":"object","title":"Page Backgrounds","description":"Per-page background colors keyed by page index as a string. Page 0 is also available in background_color.","example":{"0":"#000000","1":"#FFFFFF","9":"#000000"}},"preview_url":{"anyOf":[{"type":"string","maxLength":2048},{"type":"null"}],"title":"Preview Url","description":"Preview image URL","example":"https://example.com/preview.png"},"layers":{"items":{"$ref":"#/components/schemas/Layer"},"type":"array","maxItems":2000,"title":"Layers","description":"List of layers in the template","default":[]},"tags":{"items":{"type":"string"},"type":"array","title":"Tags","description":"User-defined tags for organizing designs into folders","default":[],"example":["campaign","summer-2026"]},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"warnings":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Warnings","default":[]},"page_count":{"type":"integer","minimum":1.0,"title":"Page Count","description":"Number of pages in this template (derived from layers)","default":1},"variant_count":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Variant Count","description":"Number of variants for this template (only included in list endpoint)"}},"type":"object","required":["id","name","width","height","source_url","background_color","created_at","updated_at"],"title":"TemplateResponse"},"TemplateUpdateRequest":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Name","description":"Template name","example":"My Template"},"width":{"anyOf":[{"type":"integer","maximum":10000.0,"minimum":1.0},{"type":"null"}],"title":"Width","description":"Template width in pixels","example":800},"height":{"anyOf":[{"type":"integer","maximum":10000.0,"minimum":1.0},{"type":"null"}],"title":"Height","description":"Template height in pixels","example":600},"background_color":{"anyOf":[{"type":"string","maxLength":7},{"type":"null"}],"title":"Background Color","description":"Background color of the first page (page 0) in hex format","example":"#FFFFFF"},"page_backgrounds":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Page Backgrounds","description":"Per-page background colors to merge into the template, keyed by page index as a string. Updating page 0 also updates background_color.","example":{"1":"#1A1A2E","9":"#000000"}},"layers":{"anyOf":[{"items":{"$ref":"#/components/schemas/LayerUpdateRequest"},"type":"array"},{"type":"null"}],"title":"Layers","description":"List of layer updates (id required for each)"},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Tags","description":"Replace all tags on this template. Send an empty list to clear all tags. Omit to leave tags unchanged.","example":["campaign","summer-2026"]}},"type":"object","title":"TemplateUpdateRequest"},"TextAlign":{"type":"string","enum":["left","center","right","justify"],"title":"TextAlign","description":"Text alignment options"},"TextLayerProperties":{"properties":{"width":{"anyOf":[{"type":"number","maximum":10000.0,"minimum":1.0},{"type":"null"}],"title":"Width","description":"Layer width in pixels","example":100},"height":{"anyOf":[{"type":"number","maximum":10000.0,"minimum":1.0},{"type":"null"}],"title":"Height","description":"Layer height in pixels","example":100},"color":{"anyOf":[{"type":"string","maxLength":7},{"type":"null"}],"title":"Color","description":"Color in hex format (#RRGGBB)","example":"#FF0000"},"rotation":{"anyOf":[{"type":"number","maximum":360.0,"minimum":-360.0},{"type":"null"}],"title":"Rotation","description":"Rotation angle in degrees","example":0},"text":{"type":"string","maxLength":10000,"title":"Text","description":"Text content","default":"","example":"Hello World"},"font_size":{"anyOf":[{"type":"number","maximum":2000.0,"minimum":1.0},{"type":"null"}],"title":"Font Size","description":"Font size in pixels","example":16},"font_name":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Font Name","description":"Font family name","example":"Arial"},"font_style":{"anyOf":[{"$ref":"#/components/schemas/FontStyle"},{"type":"null"}]},"text_align":{"anyOf":[{"$ref":"#/components/schemas/TextAlign"},{"type":"null"}]},"text_direction":{"anyOf":[{"type":"string","const":"rtl"},{"type":"null"}],"title":"Text Direction","description":"Text direction; only set for right-to-left text (Arabic, Hebrew, etc.). Absent/null means LTR.","example":"rtl"},"letter_spacing":{"anyOf":[{"type":"number","maximum":800.0,"minimum":-200.0},{"type":"null"}],"title":"Letter Spacing","description":"Letter spacing in pixels","example":0},"line_spacing":{"anyOf":[{"type":"number","maximum":2500.0,"minimum":500.0},{"type":"null"}],"title":"Line Spacing","description":"Line spacing in pixels","example":1000},"vertical_align":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vertical Align","description":"Vertical alignment for text (e.g. 'middle')","example":"middle"}},"type":"object","title":"TextLayerProperties","description":"Properties specific to text layers"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"VariantBulkCreateRequest":{"properties":{"export_type":{"$ref":"#/components/schemas/ExportType","description":"Export format for every item in the batch"},"items":{"items":{"$ref":"#/components/schemas/VariantBulkItem"},"type":"array","maxItems":50,"minItems":1,"title":"Items","description":"Variant items to render"},"combine_pdf":{"type":"boolean","title":"Combine Pdf","description":"Merge all PDF items into one multi-page PDF (Plus+ only)","default":false}},"type":"object","required":["export_type","items"],"title":"VariantBulkCreateRequest"},"VariantBulkCreateResponse":{"properties":{"results":{"items":{"$ref":"#/components/schemas/VariantBulkItemResult"},"type":"array","title":"Results"},"total_requested":{"type":"integer","title":"Total Requested"},"total_created":{"type":"integer","title":"Total Created"},"total_failed":{"type":"integer","title":"Total Failed"},"combined_pdf":{"anyOf":[{"$ref":"#/components/schemas/CombinedPdfResult"},{"type":"null"}]}},"type":"object","required":["results","total_requested","total_created","total_failed"],"title":"VariantBulkCreateResponse"},"VariantBulkItem":{"properties":{"overrides":{"anyOf":[{"items":{"$ref":"#/components/schemas/VariantOverrideOptional"},"type":"array","maxItems":2000},{"type":"null"}],"title":"Overrides","description":"Per-layer overrides for this variant"},"width":{"anyOf":[{"type":"integer","maximum":10000.0,"minimum":1.0},{"type":"null"}],"title":"Width","description":"Variant width in pixels"},"height":{"anyOf":[{"type":"integer","maximum":10000.0,"minimum":1.0},{"type":"null"}],"title":"Height","description":"Variant height in pixels"},"page_number":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Page Number","description":"Page index to render (0-based)","default":0}},"type":"object","title":"VariantBulkItem","description":"Per-item fields for bulk variant creation (export_type is batch-level)."},"VariantBulkItemResult":{"properties":{"index":{"type":"integer","title":"Index"},"success":{"type":"boolean","title":"Success"},"variant":{"anyOf":[{"$ref":"#/components/schemas/VariantResponse"},{"type":"null"}]},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","required":["index","success"],"title":"VariantBulkItemResult"},"VariantCreateUpdateRequest":{"properties":{"overrides":{"anyOf":[{"items":{"$ref":"#/components/schemas/VariantOverrideOptional"},"type":"array","maxItems":2000},{"type":"null"}],"title":"Overrides","description":"Array of per-layer overrides; each entry has layer_id from GET /v1/template/{template_id} and optional properties."},"width":{"anyOf":[{"type":"integer","maximum":10000.0,"minimum":1.0},{"type":"null"}],"title":"Width","description":"Variant width in pixels","example":800},"height":{"anyOf":[{"type":"integer","maximum":10000.0,"minimum":1.0},{"type":"null"}],"title":"Height","description":"Variant height in pixels","example":600},"export_type":{"anyOf":[{"$ref":"#/components/schemas/ExportType"},{"type":"null"}],"description":"Export format for the variant","default":"png","example":"png"},"page_number":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Page Number","description":"Page index to render (0-based). Only layers on this page are included.","default":0,"example":0}},"type":"object","title":"VariantCreateUpdateRequest","example":{"export_type":"png","height":600,"overrides":[{"layer_id":"123e4567-e89b-12d3-a456-426614174000","properties":{"img_url":"https://your-cdn.com/image.jpg","image_fit":"cover"}},{"layer_id":"223e4567-e89b-12d3-a456-426614174001","properties":{"text":"Your headline here","font_size":42}}],"width":800}},"VariantOverrideOptional":{"properties":{"layer_id":{"type":"string","format":"uuid","title":"Layer Id","description":"UUID of the layer to override. Must match a layer in the target template (retrieve via GET /v1/template/{template_id})."},"x":{"anyOf":[{"type":"number","maximum":10000.0,"minimum":-10000.0},{"type":"null"}],"title":"X","description":"X position override in pixels. Omit to keep template default.","example":0},"y":{"anyOf":[{"type":"number","maximum":10000.0,"minimum":-10000.0},{"type":"null"}],"title":"Y","description":"Y position override in pixels. Omit to keep template default.","example":0},"properties":{"anyOf":[{"$ref":"#/components/schemas/FlexibleLayerProperties"},{"type":"null"}],"description":"Per-layer property overrides. Common fields for text layers include text and font_size; for image layers include img_url and image_fit. Any field omitted keeps the template default."}},"type":"object","required":["layer_id"],"title":"VariantOverrideOptional","description":"Override for a single layer in a variant render (with optional position).\n\nSame shape as `VariantOverride`, but `x` and `y` can be omitted to keep the layer\nat its default position. Use `properties` to change content (text, image URL, etc.)."},"VariantResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"template_id":{"type":"string","format":"uuid","title":"Template Id"},"url":{"type":"string","maxLength":2048,"title":"Url","description":"Rendered variant URL","example":"https://example.com/variant.png"},"signed_url_expiry":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Signed Url Expiry"},"width":{"type":"integer","maximum":10000.0,"minimum":1.0,"title":"Width","description":"Variant width in pixels","example":800},"height":{"type":"integer","maximum":10000.0,"minimum":1.0,"title":"Height","description":"Variant height in pixels","example":600},"overrides":{"items":{"$ref":"#/components/schemas/VariantOverrideOptional"},"type":"array","maxItems":2000,"title":"Overrides","description":"List of layer overrides for the variant"},"page_number":{"type":"integer","minimum":0.0,"title":"Page Number","description":"Page index this variant was rendered from (0-based)","default":0,"example":0},"is_combined_pdf":{"type":"boolean","title":"Is Combined Pdf","description":"True when this variant is a multi-section combined PDF","default":false},"combined_section_count":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Combined Section Count","description":"Number of variant sections merged into a combined PDF"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"warnings":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Warnings","default":[]}},"type":"object","required":["id","template_id","url","width","height","overrides","created_at","updated_at"],"title":"VariantResponse"}},"securitySchemes":{"HTTPBearer":{"type":"http","scheme":"bearer"}}}}
