{"openapi":"3.1.0","info":{"title":"Pictomancer.ai Gateway","version":"0.1.0"},"paths":{"/v1/info":{"get":{"summary":"Get supported formats and options","description":"Returns supported output formats and their configurable options.","operationId":"get_format_info","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/analyze":{"post":{"summary":"Analyze an image","description":"Fetch an image from a URL or base64 and return its metadata (size in bytes). Always free.","operationId":"analyze_image","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageSource"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyzeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/resize":{"post":{"summary":"Resize an image","description":"Scale an image by a factor. Use 'scale' for uniform scaling, or 'scale_x'/'scale_y' for independent axes. Values are float factors (e.g. 0.5 = half size).","operationId":"resize_image","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResizeRequest"}}},"required":true},"responses":{"200":{"description":"Processed image binary","content":{"application/json":{"schema":{}},"image/jpeg":{"schema":{"type":"string","format":"binary"}},"image/png":{"schema":{"type":"string","format":"binary"}},"image/webp":{"schema":{"type":"string","format":"binary"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/compress":{"post":{"summary":"Compress an image","description":"Re-encode an image with quality/format options to reduce file size. Supports jpeg, png, webp, tiff, gif.","operationId":"compress_image","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompressRequest"}}},"required":true},"responses":{"200":{"description":"Processed image binary","content":{"application/json":{"schema":{}},"image/jpeg":{"schema":{"type":"string","format":"binary"}},"image/png":{"schema":{"type":"string","format":"binary"}},"image/webp":{"schema":{"type":"string","format":"binary"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/convert":{"post":{"summary":"Convert image format","description":"Convert an image to a different format (jpeg, png, webp, tiff, gif). Optionally set quality, strip metadata, or enable lossless mode (webp).","operationId":"convert_image","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConvertRequest"}}},"required":true},"responses":{"200":{"description":"Processed image binary","content":{"application/json":{"schema":{}},"image/jpeg":{"schema":{"type":"string","format":"binary"}},"image/png":{"schema":{"type":"string","format":"binary"}},"image/webp":{"schema":{"type":"string","format":"binary"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/crop":{"post":{"summary":"Crop an image","description":"Extract a rectangular region from an image. Specify the top-left corner (x, y) and the dimensions (width, height) in pixels.","operationId":"crop_image","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CropRequest"}}},"required":true},"responses":{"200":{"description":"Processed image binary","content":{"application/json":{"schema":{}},"image/jpeg":{"schema":{"type":"string","format":"binary"}},"image/png":{"schema":{"type":"string","format":"binary"}},"image/webp":{"schema":{"type":"string","format":"binary"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/pipeline":{"post":{"summary":"Run a multi-step image pipeline","description":"Chain multiple operations (resize, compress, convert, crop) in sequence. The image is fetched once, then each operation is applied to the output of the previous one. Max 10 operations per pipeline.","operationId":"image_pipeline","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PipelineRequest"}}},"required":true},"responses":{"200":{"description":"Processed image binary","content":{"application/json":{"schema":{}},"image/jpeg":{"schema":{"type":"string","format":"binary"}},"image/png":{"schema":{"type":"string","format":"binary"}},"image/webp":{"schema":{"type":"string","format":"binary"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AnalyzeResponse":{"properties":{"size_bytes":{"type":"integer","title":"Size Bytes","description":"File size of the fetched image in bytes."}},"type":"object","required":["size_bytes"],"title":"AnalyzeResponse"},"CompressRequest":{"properties":{"delivery":{"oneOf":[{"$ref":"#/components/schemas/InlineDelivery"},{"$ref":"#/components/schemas/PutUrlDelivery"}],"title":"Delivery","discriminator":{"propertyName":"mode","mapping":{"inline":"#/components/schemas/InlineDelivery","put_url":"#/components/schemas/PutUrlDelivery"}}},"source":{"type":"string","title":"Source","description":"Image source: a public URL (https://...) or a base64-encoded string (optionally as a data URI like data:image/png;base64,...)."},"q":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Q","description":"Quality (1-100). Lower = smaller file. Typical values: 60-80 for web, 85-95 for print. Maps to libvips Q parameter."},"format":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Format","description":"Output format: jpeg, png, webp, tiff, or gif. If omitted, the original format is preserved."},"strip":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Strip","description":"Strip metadata (EXIF, ICC profile, etc.) from the output. Reduces file size slightly."}},"additionalProperties":true,"type":"object","required":["source"],"title":"CompressRequest"},"ConvertRequest":{"properties":{"delivery":{"oneOf":[{"$ref":"#/components/schemas/InlineDelivery"},{"$ref":"#/components/schemas/PutUrlDelivery"}],"title":"Delivery","discriminator":{"propertyName":"mode","mapping":{"inline":"#/components/schemas/InlineDelivery","put_url":"#/components/schemas/PutUrlDelivery"}}},"source":{"type":"string","title":"Source","description":"Image source: a public URL (https://...) or a base64-encoded string (optionally as a data URI like data:image/png;base64,...)."},"format":{"type":"string","title":"Format","description":"Target format: jpeg, png, webp, tiff, or gif."},"q":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Q","description":"Quality (1-100). Maps to libvips Q parameter."},"strip":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Strip","description":"Strip metadata (EXIF, ICC profile, etc.) from the output."},"lossless":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Lossless","description":"Enable lossless encoding. Only applies to webp."}},"additionalProperties":true,"type":"object","required":["source","format"],"title":"ConvertRequest"},"CropRequest":{"properties":{"delivery":{"oneOf":[{"$ref":"#/components/schemas/InlineDelivery"},{"$ref":"#/components/schemas/PutUrlDelivery"}],"title":"Delivery","discriminator":{"propertyName":"mode","mapping":{"inline":"#/components/schemas/InlineDelivery","put_url":"#/components/schemas/PutUrlDelivery"}}},"source":{"type":"string","title":"Source","description":"Image source: a public URL (https://...) or a base64-encoded string (optionally as a data URI like data:image/png;base64,...)."},"x":{"type":"integer","title":"X","description":"Left edge of the crop rectangle in pixels."},"y":{"type":"integer","title":"Y","description":"Top edge of the crop rectangle in pixels."},"width":{"type":"integer","title":"Width","description":"Width of the crop rectangle in pixels."},"height":{"type":"integer","title":"Height","description":"Height of the crop rectangle in pixels."},"format":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Format","description":"Output format: jpeg, png, webp, tiff, or gif. If omitted, the original format is preserved."}},"additionalProperties":true,"type":"object","required":["source","x","y","width","height"],"title":"CropRequest"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ImageSource":{"properties":{"source":{"type":"string","title":"Source","description":"Image source: a public URL (https://...) or a base64-encoded string (optionally as a data URI like data:image/png;base64,...)."}},"type":"object","required":["source"],"title":"ImageSource"},"InlineDelivery":{"properties":{"mode":{"type":"string","const":"inline","title":"Mode","default":"inline"}},"additionalProperties":false,"type":"object","title":"InlineDelivery"},"PipelineOperation":{"properties":{"type":{"type":"string","title":"Type","description":"Operation type: resize, compress, convert, or crop."},"params":{"additionalProperties":{"type":"string"},"type":"object","title":"Params","description":"Operation parameters as key-value string pairs. E.g. {\"scale\": \"0.5\"} for resize, {\"format\": \"webp\"} for convert.","default":{}}},"type":"object","required":["type"],"title":"PipelineOperation"},"PipelineRequest":{"properties":{"delivery":{"oneOf":[{"$ref":"#/components/schemas/InlineDelivery"},{"$ref":"#/components/schemas/PutUrlDelivery"}],"title":"Delivery","discriminator":{"propertyName":"mode","mapping":{"inline":"#/components/schemas/InlineDelivery","put_url":"#/components/schemas/PutUrlDelivery"}}},"source":{"type":"string","title":"Source","description":"Image source: a public URL (https://...) or a base64-encoded string (optionally as a data URI like data:image/png;base64,...)."},"operations":{"items":{"$ref":"#/components/schemas/PipelineOperation"},"type":"array","title":"Operations","description":"Ordered list of operations to apply sequentially. Each operation receives the output of the previous one. Max 10."}},"type":"object","required":["source","operations"],"title":"PipelineRequest"},"PutUrlDelivery":{"properties":{"mode":{"type":"string","const":"put_url","title":"Mode"},"put_url":{"type":"string","maxLength":2083,"minLength":1,"format":"uri","title":"Put Url","description":"Customer-signed presigned PUT URL where the optimized bytes will be written. Must be https://. Cloud credentials never reach our infrastructure; only the URL itself is used and discarded after the request."},"headers":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Headers","description":"Optional storage headers to include on the PUT call (Content-Type, Cache-Control, x-amz-acl, etc.). Whitelisted at SSRF layer."}},"additionalProperties":false,"type":"object","required":["mode","put_url"],"title":"PutUrlDelivery"},"ResizeRequest":{"properties":{"delivery":{"oneOf":[{"$ref":"#/components/schemas/InlineDelivery"},{"$ref":"#/components/schemas/PutUrlDelivery"}],"title":"Delivery","discriminator":{"propertyName":"mode","mapping":{"inline":"#/components/schemas/InlineDelivery","put_url":"#/components/schemas/PutUrlDelivery"}}},"source":{"type":"string","title":"Source","description":"Image source: a public URL (https://...) or a base64-encoded string (optionally as a data URI like data:image/png;base64,...)."},"scale_x":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Scale X","description":"Horizontal scale factor (e.g. 0.5 = half width). If only scale_x is given, scale_y defaults to the same value."},"scale_y":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Scale Y","description":"Vertical scale factor (e.g. 0.75 = 75% height). Optional; defaults to scale_x if omitted."},"scale":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Scale","description":"Uniform scale factor applied to both axes (e.g. 0.5 = half size). Use this for simple scaling; use scale_x/scale_y for independent axes."},"format":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Format","description":"Output format: jpeg, png, webp, tiff, or gif. If omitted, the original format is preserved."}},"additionalProperties":true,"type":"object","required":["source"],"title":"ResizeRequest"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}}}