{"openapi":"3.1.0","info":{"title":"ContentImage API","version":"1.0.0","description":"Render on-brand featured, OG and social images, manage brands and sites, and approve results. Bearer API key (ci_...), 60 requests per minute per key. Errors are always JSON: {\"error\":{\"code\",\"message\"}}."},"servers":[{"url":"https://contentimage.io/api/v1"}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"API key starting with ci_, created in the app."}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}},"paths":{"/render":{"post":{"operationId":"render_image","summary":"Render images for an article","description":"Render on-brand featured/OG/social images for one article. Give a url (the page is read for title, language and brand) or just a title. Sizes: og 1200x630, featured 1600x900, square 1080x1080, story 1080x1920. Pass brand to override name, logo_url, colors or font_pair for this render only. Headlines are typeset per language (fi, de, fr, es, en) with hyphenation. Returns image URLs plus previews. Counts against the monthly image quota.","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","maxLength":1000,"format":"uri"},"title":{"type":"string","minLength":1,"maxLength":300},"lang":{"type":"string","enum":["fi","de","fr","es","en"]},"sizes":{"minItems":1,"maxItems":4,"type":"array","items":{"type":"string","enum":["og","featured","square","story"]}},"style":{"type":"string","enum":["typographic","photo","quote","split"]},"brand":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"logo_url":{"anyOf":[{"type":"string","maxLength":500,"format":"uri"},{"type":"null"}]},"colors":{"maxItems":6,"type":"array","items":{"type":"string","pattern":"^#[0-9a-fA-F]{3}([0-9a-fA-F]{3})?$"}},"font_pair":{"type":"string","enum":["inter-serif","inter","serif"]},"site_id":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}}},"brand_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"site_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"images":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"size":{"type":"string","enum":["og","featured","square","story"]},"style":{"type":"string","enum":["typographic","photo","quote","split"]},"url":{"type":"string"},"width":{"type":"number"},"height":{"type":"number"},"alt":{"type":"string"}},"required":["id","size","style","url","width","height","alt"],"additionalProperties":false}},"qa":{"type":"object","properties":{"score":{"type":["number","null"]},"notes":{"type":"string"},"needs_review":{"type":"boolean"},"skipped":{"type":"boolean"}},"required":["score","notes","needs_review","skipped"],"additionalProperties":false}},"required":["images","qa"],"additionalProperties":false}}}},"400":{"description":"Invalid request body, query or path.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Plan limit reached (images, sites or API calls).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The input is valid but cannot be processed (unreachable URL, unsupported script, no title).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit: 60 requests per minute per key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/brands":{"get":{"operationId":"get_brand","summary":"List brand kits, or fetch one by site_id or brand_id","description":"Get brand kits (logo, colors, font pair). Pass site_id or brand_id to fetch one; with no arguments, lists all brand kits in the workspace. Always returns {brands: [...]}.","parameters":[{"name":"site_id","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"brand_id","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"brands":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"site_id":{"type":["string","null"]},"name":{"type":"string"},"logo_url":{"type":["string","null"]},"colors":{"type":"array","items":{"type":"string"}},"font_pair":{"type":"string","enum":["inter-serif","inter","serif"]}},"required":["id","site_id","name","logo_url","colors","font_pair"],"additionalProperties":false}}},"required":["brands"],"additionalProperties":false}}}},"400":{"description":"Invalid request body, query or path.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit: 60 requests per minute per key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"set_brand","summary":"Create or update a brand kit","description":"Create or update a brand kit. Pass brand_id to update an existing kit, or site_id to set the kit of a site. Only the fields you pass change; everything else is kept. colors are hex strings; the first is the background, the second the accent. font_pair is inter-serif, inter or serif.","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"brand_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string","minLength":1,"maxLength":80},"logo_url":{"anyOf":[{"type":"string","maxLength":500,"format":"uri"},{"type":"null"}]},"colors":{"maxItems":6,"type":"array","items":{"type":"string","pattern":"^#[0-9a-fA-F]{3}([0-9a-fA-F]{3})?$"}},"font_pair":{"type":"string","enum":["inter-serif","inter","serif"]},"site_id":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"additionalProperties":false}}}},"responses":{"201":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"site_id":{"type":["string","null"]},"name":{"type":"string"},"logo_url":{"type":["string","null"]},"colors":{"type":"array","items":{"type":"string"}},"font_pair":{"type":"string","enum":["inter-serif","inter","serif"]}},"required":["id","site_id","name","logo_url","colors","font_pair"],"additionalProperties":false}}}},"400":{"description":"Invalid request body, query or path.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit: 60 requests per minute per key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/brands/{id}":{"patch":{"operationId":"update_brand","summary":"Update a brand kit (partial)","description":"Update a brand kit by id. Only the fields you send change.","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"logo_url":{"anyOf":[{"type":"string","maxLength":500,"format":"uri"},{"type":"null"}]},"colors":{"maxItems":6,"type":"array","items":{"type":"string","pattern":"^#[0-9a-fA-F]{3}([0-9a-fA-F]{3})?$"}},"font_pair":{"type":"string","enum":["inter-serif","inter","serif"]},"site_id":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"additionalProperties":false}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"site_id":{"type":["string","null"]},"name":{"type":"string"},"logo_url":{"type":["string","null"]},"colors":{"type":"array","items":{"type":"string"}},"font_pair":{"type":"string","enum":["inter-serif","inter","serif"]}},"required":["id","site_id","name","logo_url","colors","font_pair"],"additionalProperties":false}}}},"400":{"description":"Invalid request body, query or path.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit: 60 requests per minute per key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/brands/from-url":{"post":{"operationId":"draft_brand_from_url","summary":"Draft a brand kit from a website (not saved)","description":"Read a website and propose a brand kit (logo, theme colors, font guess). Does not save anything; pass the result to set_brand if it looks right.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"}},"required":["url"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"logo_url":{"type":["string","null"]},"colors":{"type":"array","items":{"type":"string"}},"font_pair":{"type":"string"},"saved":{"type":"boolean"}},"required":["name","logo_url","colors","font_pair","saved"],"additionalProperties":false}}}},"400":{"description":"Invalid request body, query or path.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The input is valid but cannot be processed (unreachable URL, unsupported script, no title).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit: 60 requests per minute per key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sites":{"get":{"operationId":"list_sites","summary":"List sites","description":"List the sites in this workspace with their agent setting (on/off), approval mode (auto or approve), CMS type and language. Call this first to get site ids.","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"sites":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"url":{"type":"string"},"feed_url":{"type":["string","null"]},"cms_type":{"type":"string","enum":["wordpress","ghost","webhook","none"]},"agent_enabled":{"type":"boolean"},"mode":{"type":"string","enum":["auto","approve"]},"language":{"anyOf":[{"type":"string","enum":["fi","de","fr","es","en"]},{"type":"null"}]},"has_cms_credentials":{"type":"boolean"},"last_feed_error":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","url","feed_url","cms_type","agent_enabled","mode","language","has_cms_credentials","last_feed_error","created_at"],"additionalProperties":false}}},"required":["sites"],"additionalProperties":false}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit: 60 requests per minute per key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"create_site","summary":"Add a site and draft its brand kit","description":"Add a site (http or https only) and draft its brand kit from the page.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","maxLength":500,"format":"uri"},"feed_url":{"anyOf":[{"type":"string","maxLength":500,"format":"uri"},{"type":"null"}]},"cms_type":{"default":"none","type":"string","enum":["wordpress","ghost","webhook","none"]},"cms_credentials":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"language":{"anyOf":[{"type":"string","enum":["fi","de","fr","es","en"]},{"type":"null"}]}},"required":["url"],"additionalProperties":false}}}},"responses":{"201":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"url":{"type":"string"},"feed_url":{"type":["string","null"]},"cms_type":{"type":"string","enum":["wordpress","ghost","webhook","none"]},"agent_enabled":{"type":"boolean"},"mode":{"type":"string","enum":["auto","approve"]},"language":{"anyOf":[{"type":"string","enum":["fi","de","fr","es","en"]},{"type":"null"}]},"has_cms_credentials":{"type":"boolean"},"last_feed_error":{"type":["string","null"]},"created_at":{"type":"string"},"brand_id":{"type":["string","null"]}},"required":["id","url","feed_url","cms_type","agent_enabled","mode","language","has_cms_credentials","last_feed_error","created_at","brand_id"],"additionalProperties":false}}}},"400":{"description":"Invalid request body, query or path.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Plan limit reached (images, sites or API calls).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit: 60 requests per minute per key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sites/{id}":{"patch":{"operationId":"update_site","summary":"Update agent, mode, CMS or feed","description":"Update a site. Only the fields you send change; cms_credentials are merged with the stored ones.","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"agent_enabled":{"type":"boolean"},"mode":{"type":"string","enum":["auto","approve"]},"feed_url":{"anyOf":[{"type":"string","maxLength":500,"format":"uri"},{"type":"null"}]},"cms_type":{"type":"string","enum":["wordpress","ghost","webhook","none"]},"cms_credentials":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"language":{"anyOf":[{"type":"string","enum":["fi","de","fr","es","en"]},{"type":"null"}]}},"additionalProperties":false}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"url":{"type":"string"},"feed_url":{"type":["string","null"]},"cms_type":{"type":"string","enum":["wordpress","ghost","webhook","none"]},"agent_enabled":{"type":"boolean"},"mode":{"type":"string","enum":["auto","approve"]},"language":{"anyOf":[{"type":"string","enum":["fi","de","fr","es","en"]},{"type":"null"}]},"has_cms_credentials":{"type":"boolean"},"last_feed_error":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","url","feed_url","cms_type","agent_enabled","mode","language","has_cms_credentials","last_feed_error","created_at"],"additionalProperties":false}}}},"400":{"description":"Invalid request body, query or path.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Plan limit reached (images, sites or API calls).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit: 60 requests per minute per key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"delete_site","summary":"Delete a site and everything under it","description":"Permanently delete a site with its brand kit, posts, images and queued jobs. Cannot be undone. Requires `confirm` set to the site's exact URL (as shown by list_sites) so a model cannot delete a site by accident: ask the user to confirm the URL first.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"confirm","in":"query","required":true,"schema":{"type":"string","minLength":1,"description":"The site's URL, exactly as list_sites returns it. A different value deletes nothing."}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"boolean"}},"required":["deleted"],"additionalProperties":false}}}},"400":{"description":"Invalid request body, query or path.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit: 60 requests per minute per key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/account":{"delete":{"operationId":"delete_account","summary":"Delete your account and all its data","description":"Permanently delete the account behind this API key: every site, brand kit, image, API key and usage record. Requires `confirm` set to the account email address.","parameters":[{"name":"confirm","in":"query","required":true,"schema":{"type":"string","minLength":1,"description":"The account email address."}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"boolean"}},"required":["deleted"],"additionalProperties":false}}}},"400":{"description":"Invalid request body, query or path.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit: 60 requests per minute per key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sites/{id}/sweep":{"post":{"operationId":"sweep_site","summary":"Queue a backfill of posts without a featured image (50 per hour)","description":"Queue a backfill that renders images for existing posts that have none, 50 posts per hour. The agent worker must be running.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"202":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"queued":{"type":"boolean"},"already_queued":{"type":"boolean"},"job_id":{"type":["number","null"]},"note":{"type":"string"}},"required":["queued","already_queued","job_id","note"],"additionalProperties":false}}}},"400":{"description":"Invalid request body, query or path.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit: 60 requests per minute per key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/images":{"get":{"operationId":"list_images","summary":"List images","description":"List generated images, newest first. Filter by site_id and status (draft, approved, published, rejected). Draft images are waiting for approval.","parameters":[{"name":"site_id","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["draft","approved","published","rejected"]}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"images":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"url":{"type":"string"},"size":{"type":"string"},"style":{"type":"string"},"width":{"type":"number"},"height":{"type":"number"},"alt":{"type":"string"},"status":{"type":"string","enum":["draft","approved","published","rejected"]},"qa_score":{"type":["number","null"]},"qa_notes":{"type":["string","null"]},"needs_review":{"type":"boolean"},"post_id":{"type":["string","null"]},"site_id":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","url","size","style","width","height","alt","status","qa_score","qa_notes","needs_review","post_id","site_id","created_at"],"additionalProperties":false}}},"required":["images"],"additionalProperties":false}}}},"400":{"description":"Invalid request body, query or path.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit: 60 requests per minute per key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/images/{id}/approve":{"post":{"operationId":"approve_image","summary":"Approve an image (queues publishing if it belongs to a post)","description":"Approve a draft image (or reject it with approve=false). Approving an image that belongs to a post queues publishing of the post's featured image to the site's CMS.","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"approve":{"type":"boolean"}},"additionalProperties":false}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"url":{"type":"string"},"size":{"type":"string"},"style":{"type":"string"},"width":{"type":"number"},"height":{"type":"number"},"alt":{"type":"string"},"status":{"type":"string","enum":["draft","approved","published","rejected"]},"qa_score":{"type":["number","null"]},"qa_notes":{"type":["string","null"]},"needs_review":{"type":"boolean"},"post_id":{"type":["string","null"]},"site_id":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","url","size","style","width","height","alt","status","qa_score","qa_notes","needs_review","post_id","site_id","created_at"],"additionalProperties":false}}}},"400":{"description":"Invalid request body, query or path.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit: 60 requests per minute per key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/images/{id}/reject":{"post":{"operationId":"reject_image","summary":"Reject an image","description":"Reject a draft or approved image. A published image is never changed.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"url":{"type":"string"},"size":{"type":"string"},"style":{"type":"string"},"width":{"type":"number"},"height":{"type":"number"},"alt":{"type":"string"},"status":{"type":"string","enum":["draft","approved","published","rejected"]},"qa_score":{"type":["number","null"]},"qa_notes":{"type":["string","null"]},"needs_review":{"type":"boolean"},"post_id":{"type":["string","null"]},"site_id":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","url","size","style","width","height","alt","status","qa_score","qa_notes","needs_review","post_id","site_id","created_at"],"additionalProperties":false}}}},"400":{"description":"Invalid request body, query or path.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit: 60 requests per minute per key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}