{"openapi":"3.0.3","info":{"title":"Studio decks API","version":"1.9.0","description":"Plan a carousel, a slide deck or a one-page newsletter infographic from text, watch it generate, and get back the deck id, the finished images, a PDF or a ZIP. Create a key on the Team page — it acts for that workspace and spends its owner's credits."},"servers":[{"url":"https://directorline.i-avantage-group.com"}],"security":[{"apiKey":[]}],"tags":[{"name":"decks"},{"name":"assets","description":"Style presets and reference banks a deck can use."}],"paths":{"/api/v1/me":{"get":{"operationId":"getCaller","summary":"Who this key acts for, and the limits to build a form from","tags":["assets"],"responses":{"200":{"description":"The workspace, the key, and its bounds.","content":{"application/json":{"schema":{"type":"object","properties":{"workspace":{"type":"object","properties":{"name":{"type":"string"}}},"key":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string"},"name":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}}}},"limits":{"type":"object","properties":{"slides":{"type":"object","properties":{"min":{"type":"integer"},"max":{"type":"integer"},"default":{"type":"integer"}}},"references":{"type":"integer"},"ratios":{"type":"array","items":{"type":"string"}}}}}}}}},"401":{"description":"Missing or invalid key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/style-presets":{"get":{"operationId":"listStylePresets","summary":"Saved style presets — pass one's id as stylePresetId when creating a deck","tags":["assets"],"responses":{"200":{"description":"The workspace's presets.","content":{"application/json":{"schema":{"type":"object","properties":{"presets":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"tone":{"type":"string","nullable":true},"instructions":{"type":"string"},"structure":{"type":"string","nullable":true}}}}}}}}},"401":{"description":"Missing or invalid key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/reference-banks":{"get":{"operationId":"listReferenceBanks","summary":"Saved reference banks — pass one's id as referenceBankId when creating a deck","tags":["assets"],"responses":{"200":{"description":"The workspace's reference banks.","content":{"application/json":{"schema":{"type":"object","properties":{"banks":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"imageUrls":{"type":"array","items":{"type":"string","format":"uri"}}}}}}}}}},"401":{"description":"Missing or invalid key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/decks":{"post":{"operationId":"createDeck","summary":"Plan a deck and start generating its images","description":"Answers as soon as the plan is written; images keep generating afterwards. Poll GET /api/v1/decks/{id}, or set webhookUrl to be told when it settles. Repeat the exact same request with an Idempotency-Key header to get the same deck back instead of planning — and paying — twice.","tags":["decks"],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"generationMode":{"type":"string","enum":["fast","advanced"],"default":"fast","description":"Fast takes a topic and optional elements and runs the full production. Advanced keeps the full deck controls available."},"content":{"type":"string","description":"Advanced input: a topic, notes, an outline, or a full draft — what the deck is about."},"topic":{"type":"string","description":"Fast input: the main topic to turn into a finished deck."},"elements":{"type":"string","description":"Fast input: optional points, facts, sections, visuals, or calls to action to include."},"mode":{"type":"string","enum":["carousel","slide","newsletter","report"],"default":"carousel","description":"newsletter is one tall infographic page rather than a run of slides; report is a run of A4 pages that reads as a printed document — cover, contents, one section per page, conclusion — and its PDF is laid on true 210x297mm sheets."},"slides":{"type":"integer","minimum":1,"maximum":40,"default":5,"description":"Carousel and slide: 3–40. Newsletter: 1–6, default 1."},"ratio":{"type":"string","enum":["1:1","16:9","9:16","4:3","3:4","3:2","2:3","21:9","2:1","1:2","210:297","297:210"],"description":"Defaults by mode: 1:1 carousel, 16:9 slide, 1:2 newsletter."},"quality":{"type":"string","enum":["low","medium","high"],"default":"low","description":"medium is sharper and costs 5 credits per base image; high is the highest-detail tier and costs 50 credits per base image."},"textAmount":{"type":"string","enum":["short","detailed","hyper"],"default":"detailed"},"tone":{"type":"string"},"styleInstructions":{"type":"string"},"structure":{"type":"string","description":"How the deck is built, slide by slide."},"stylePresetId":{"type":"string","description":"From GET /api/v1/style-presets."},"referenceImageUrls":{"type":"array","items":{"type":"string","format":"uri"},"maxItems":3,"description":"Default references sent with every slide."},"slideSpecs":{"type":"array","maxItems":40,"description":"Optional per-slide overrides indexed from slide 1. Omitted fields remain planner-generated.","items":{"type":"object","minProperties":1,"properties":{"caption":{"type":"string"},"imagePrompt":{"type":"string"},"referenceImageUrls":{"type":"array","items":{"type":"string","format":"uri"},"maxItems":3,"description":"Overrides the deck references for this slide."}}}},"referenceBankId":{"type":"string","description":"From GET /api/v1/reference-banks."},"webhookUrl":{"type":"string","format":"uri","description":"https URL that receives deck.planned / deck.completed / deck.failed, HMAC-signed."},"planOnly":{"type":"boolean","default":false},"proofread":{"type":"boolean","default":false,"description":"Read each page back after drawing and redraw it once if a word or a number is wrong, or the page is overfull, clipped or not the composition its layout asks for. For decks whose text must be exact and whose pages have to look right. A redraw costs a page."}}}}}},"responses":{"200":{"description":"The same deck as a prior request with this Idempotency-Key (replayed: true).","content":{"application/json":{"schema":{"type":"object","properties":{"deck":{"$ref":"#/components/schemas/Deck"}}}}}},"202":{"description":"The plan is written; images are generating.","content":{"application/json":{"schema":{"type":"object","properties":{"deck":{"$ref":"#/components/schemas/Deck"}}}}}},"400":{"description":"Missing content, or an invalid field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"The workspace's credit balance is empty.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"get":{"operationId":"listDecks","summary":"The workspace's recent decks, newest first (without slides)","tags":["decks"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":30}}],"responses":{"200":{"description":"Recent decks.","content":{"application/json":{"schema":{"type":"object","properties":{"decks":{"type":"array","items":{"$ref":"#/components/schemas/Deck"}}}}}}},"401":{"description":"Missing or invalid key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/decks/{id}":{"get":{"operationId":"getDeck","summary":"Read a deck: status, every slide, and its links","tags":["decks"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The deck.","content":{"application/json":{"schema":{"type":"object","properties":{"deck":{"$ref":"#/components/schemas/Deck"}}}}}},"401":{"description":"Missing or invalid key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"No deck with this id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"resumeDeck","summary":"Start or resume generating a deck's pending and failed slides","tags":["decks"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"202":{"description":"Generation (re)started.","content":{"application/json":{"schema":{"type":"object","properties":{"queued":{"type":"integer"}}}}}},"401":{"description":"Missing or invalid key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"No deck with this id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/decks/{id}/slides/{n}/regenerate":{"post":{"operationId":"regenerateSlide","summary":"Regenerate one slide's image now, with its current prompt","description":"The previous image stays in the slide's history. An optional note says what was wrong last time; it goes into this one prompt only.","tags":["decks"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"n","in":"path","required":true,"description":"1-based slide position.","schema":{"type":"integer","minimum":1}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"note":{"type":"string","description":"What was wrong with the previous attempt, e.g. 'the figure reads 21% instead of 12%'."}}}}}},"responses":{"200":{"description":"The whole deck, with the slide regenerated.","content":{"application/json":{"schema":{"type":"object","properties":{"deck":{"$ref":"#/components/schemas/Deck"}}}}}},"400":{"description":"This slide has no prompt yet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"The workspace's credit balance is empty.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"No such deck or slide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/decks/{id}/slides/{n}/revert":{"post":{"operationId":"revertSlide","summary":"Put a page's previous image back","description":"The image set aside joins the history, so a revert can be undone. The deck's files go stale until rebuilt.","tags":["editing"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"n","in":"path","required":true,"schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"The deck.","content":{"application/json":{"schema":{"type":"object","properties":{"deck":{"$ref":"#/components/schemas/Deck"},"restored":{"type":"string","format":"uri"}}}}}},"404":{"description":"No such deck or slide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"This page has no earlier image.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/decks/{id}/proofread":{"post":{"operationId":"proofreadDeck","summary":"Read the finished pages back and report where the drawn text departs from the caption","description":"The planner model looks at each page image with its caption and lists what is missing, wrong (a changed figure, a misspelled word), extra (an invented heading) or illegible — and, in the same pass, how the page is laid out against the layout it was briefed with: overfull, clipped, bad margins, no hierarchy, overlapping, the wrong composition, unasked-for decoration. Costs no credits; uses the planner's image quota. Verdicts are written on the slides and appear under each slide's `proofread` in every deck response until the page is drawn again.","tags":["editing"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"positions":{"type":"array","items":{"type":"integer","minimum":1},"description":"Only these pages. Default: every finished page."}}}}}},"responses":{"200":{"description":"The verdicts.","content":{"application/json":{"schema":{"type":"object","properties":{"deck":{"$ref":"#/components/schemas/Deck"},"pages":{"type":"array","items":{"type":"object","properties":{"position":{"type":"integer"},"verdict":{"type":"string","enum":["ok","issues","unchecked"]},"findings":{"type":"array","items":{"type":"object"}},"renderedText":{"type":"string","nullable":true},"reason":{"type":"string","nullable":true}}}},"summary":{"type":"object","properties":{"checked":{"type":"integer"},"ok":{"type":"integer"},"issues":{"type":"integer"},"unchecked":{"type":"integer"}}},"next":{"type":"string","nullable":true}}}}}},"400":{"description":"positions is not a list of page numbers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"No such deck.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"The planner is not configured on this deployment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/decks/{id}/remake":{"post":{"operationId":"remakeDeck","summary":"A new deck from this one's plan, drawn again with other settings","description":"Copies the captions, prompts and visual system — no planner call, so the words stay exactly as approved — and draws them at another ratio, quality, style or with other references. This is how a low-quality draft becomes a medium- or high-quality final, and how one plan is published as a square carousel and a 16:9 deck. A new style sets the old visual system aside. Costs credits like any deck of that size.","tags":["editing"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"mode":{"type":"string","enum":["carousel","slide","newsletter","report"],"description":"Default: the source deck's mode. A changed mode takes that mode's default ratio unless ratio is given."},"ratio":{"type":"string","enum":["1:1","16:9","9:16","4:3","3:4","3:2","2:3","21:9","2:1","1:2","210:297","297:210"]},"quality":{"type":"string","enum":["low","medium","high"]},"stylePresetId":{"type":"string"},"styleInstructions":{"type":"string"},"referenceBankId":{"type":"string"},"referenceImageUrls":{"type":"array","items":{"type":"string","format":"uri"},"maxItems":3,"description":"An empty list drops the source deck's references."},"proofread":{"type":"boolean","description":"Default: the source deck's setting."},"draw":{"type":"boolean","default":true,"description":"false leaves every page pending for POST /api/v1/decks/{id}."}}}}}},"responses":{"202":{"description":"The new deck, its pages pending or drawing.","content":{"application/json":{"schema":{"type":"object","properties":{"deck":{"$ref":"#/components/schemas/Deck"},"source":{"type":"string"},"queued":{"type":"integer"}}}}}},"400":{"description":"An invalid mode or ratio, or more pages than the mode allows.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"No such deck, preset or bank.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"The source deck has no pages.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/decks/{id}/slides":{"post":{"operationId":"addSlide","summary":"Add a page after a position, or at the end","tags":["editing"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"afterPosition":{"type":"integer","minimum":1},"copyFromPosition":{"type":"integer","minimum":1},"caption":{"type":"string"},"imagePrompt":{"type":"string"}}}}}},"responses":{"200":{"description":"The deck, renumbered.","content":{"application/json":{"schema":{"type":"object","properties":{"deck":{"$ref":"#/components/schemas/Deck"}}}}}}}}},"/api/v1/decks/{id}/slides/{n}":{"patch":{"operationId":"editSlide","summary":"Change a page's caption and/or image prompt","description":"The image is kept unless regenerate is true; a page already drawn comes back with imageStale: true.","tags":["editing"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"n","in":"path","required":true,"schema":{"type":"integer","minimum":1}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"caption":{"type":"string"},"imagePrompt":{"type":"string"},"layout":{"type":"string","nullable":true,"description":"The page's named shape, or null to return it to the format's default."},"referenceImageUrls":{"type":"array","nullable":true,"items":{"type":"string","format":"uri"},"maxItems":3,"description":"Set an array to override deck references, or null to inherit them again."},"regenerate":{"type":"boolean","default":false}}}}}},"responses":{"200":{"description":"The deck.","content":{"application/json":{"schema":{"type":"object","properties":{"deck":{"$ref":"#/components/schemas/Deck"},"imageStale":{"type":"boolean"}}}}}}}},"delete":{"operationId":"deleteSlide","summary":"Remove a page; the rest are renumbered","tags":["editing"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"n","in":"path","required":true,"schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"The deck.","content":{"application/json":{"schema":{"type":"object","properties":{"deck":{"$ref":"#/components/schemas/Deck"}}}}}}}}},"/api/v1/decks/{id}/order":{"patch":{"operationId":"reorderSlides","summary":"Put the pages in a new order, given as today's positions","description":"[3, 1, 2] makes today's page 3 the new page 1. Every position must appear exactly once.","tags":["editing"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"order":{"type":"array","items":{"type":"integer","minimum":1}}},"required":["order"]}}}},"responses":{"200":{"description":"The deck.","content":{"application/json":{"schema":{"type":"object","properties":{"deck":{"$ref":"#/components/schemas/Deck"}}}}}}}}},"/api/v1/decks/{id}/refine":{"post":{"operationId":"refineDeck","summary":"The planner rewrites the plan from feedback","description":"Captions and prompts change; images do not — regenerate the pages that changed. No credits.","tags":["editing"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"feedback":{"type":"string"}},"required":["feedback"]}}}},"responses":{"200":{"description":"The deck.","content":{"application/json":{"schema":{"type":"object","properties":{"deck":{"$ref":"#/components/schemas/Deck"}}}}}}}}},"/api/v1/decks/{id}/wait":{"post":{"operationId":"waitForDeck","summary":"Block until every page has settled, or the time is up","description":"Default 90 seconds, at most 240. Publishes the permanent files when it finishes. Returns settled: true|false and the deck either way.","tags":["decks"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"seconds":{"type":"integer","minimum":0,"maximum":240}}}}}},"responses":{"200":{"description":"The deck.","content":{"application/json":{"schema":{"type":"object","properties":{"settled":{"type":"boolean"},"waitedSeconds":{"type":"integer"},"deck":{"$ref":"#/components/schemas/Deck"}}}}}}}}},"/api/v1/decks/{id}/share":{"post":{"operationId":"shareDeck","summary":"A public, revocable share page for the deck","description":"Open to anyone with the link, or gated behind an email address. Asking again returns the same link with the same gate.","tags":["decks"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"access":{"type":"string","enum":["open","email"],"default":"open"}}}}}},"responses":{"200":{"description":"The share link.","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"token":{"type":"string"},"access":{"type":"string","enum":["open","email"]}}}}}}}}},"/api/v1/estimate":{"post":{"operationId":"estimateCost","summary":"What a deck would cost, against the balance, before anything is spent","tags":["decks"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"mode":{"type":"string","enum":["carousel","slide","newsletter","report"]},"slides":{"type":"integer","minimum":1,"maximum":40},"quality":{"type":"string","enum":["low","medium","high"]},"referenceCount":{"type":"integer","minimum":0,"maximum":3},"referenceBankId":{"type":"string"}}}}}},"responses":{"200":{"description":"The estimate.","content":{"application/json":{"schema":{"type":"object","properties":{"credits":{"type":"integer"},"charged":{"type":"integer"},"perPage":{"type":"integer"},"pages":{"type":"integer"},"references":{"type":"integer"},"quality":{"type":"string"},"balance":{"type":"integer","nullable":true},"unlimited":{"type":"boolean"},"affordable":{"type":"boolean"},"note":{"type":"string"}}}}}}}}},"/api/v1/images":{"post":{"operationId":"generateImage","summary":"One to three standalone images from a prompt, outside any deck","description":"Same reference banks and quality tiers as a deck; costs credits like a page. Returns permanent image URLs.","tags":["decks"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"prompt":{"type":"string"},"ratio":{"type":"string","enum":["1:1","16:9","9:16","4:3","3:4","3:2","2:3","21:9","2:1","1:2","210:297","297:210"],"default":"1:1"},"quality":{"type":"string","enum":["low","medium","high"]},"count":{"type":"integer","minimum":1,"maximum":3,"default":1},"referenceBankId":{"type":"string"},"referenceImageUrls":{"type":"array","items":{"type":"string","format":"uri"},"maxItems":3}},"required":["prompt"]}}}},"responses":{"200":{"description":"The images.","content":{"application/json":{"schema":{"type":"object","properties":{"images":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string","format":"uri"}}}},"ratio":{"type":"string"},"quality":{"type":"string"},"charged":{"type":"integer"}}}}}}}}},"/api/v1/decks/{id}/files":{"get":{"operationId":"getDeckFiles","summary":"The deck's permanent public file URLs, as they stand","description":"Answers with what is already published, building nothing. Use POST when you need the URLs now.","tags":["decks"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The files.","content":{"application/json":{"schema":{"type":"object","properties":{"files":{"$ref":"#/components/schemas/DeckFiles"}}}}}}}},"post":{"operationId":"publishDeckFiles","summary":"Publish the deck's PDF and ZIP to permanent public URLs","description":"Renders the deck's PDF and its ZIP of images and stores them at permanent, public URLs, then returns them. Already-published files are returned untouched, so calling this twice costs nothing. The URLs need no Authorization header and never expire — hand them to a publishing tool, a CMS or a scheduler. Regenerating a slide publishes a new pair on the next call; the old URL keeps serving the old pages. Rendering a long deck takes a while, so allow a generous timeout.","tags":["decks"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The published files.","content":{"application/json":{"schema":{"type":"object","properties":{"files":{"$ref":"#/components/schemas/DeckFiles"}}}}}}}}},"/api/v1/decks/{id}/export.pdf":{"get":{"operationId":"exportDeckPdf","summary":"The finished slides as a PDF, one page each","tags":["decks"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"token","in":"query","required":false,"description":"The short-lived, pre-signed token this route's own URL already carries in a deck response's links.pdf / links.zip — present it and no Authorization header is needed. Expires after 30 minutes; GET the deck again for a fresh one.","schema":{"type":"string"}}],"responses":{"200":{"description":"A PDF file.","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Missing or invalid key, and no valid token query parameter either.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"No deck with this id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"No slide has finished generating yet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/decks/{id}/export.zip":{"get":{"operationId":"exportDeckZip","summary":"The finished slides as numbered image files in a ZIP","tags":["decks"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"token","in":"query","required":false,"description":"The short-lived, pre-signed token this route's own URL already carries in a deck response's links.pdf / links.zip — present it and no Authorization header is needed. Expires after 30 minutes; GET the deck again for a fresh one.","schema":{"type":"string"}}],"responses":{"200":{"description":"A ZIP file.","content":{"application/zip":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Missing or invalid key, and no valid token query parameter either.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"No deck with this id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"No slide has finished generating yet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/decks/{id}/export.pptx":{"get":{"operationId":"exportDeckPptx","summary":"The deck as a PowerPoint file, one slide per finished page","description":"A real .pptx that opens in PowerPoint, Keynote and Google Slides. Each page's image is placed on a slide cut to the deck's shape (13.333 x 7.5 in for a 16:9 deck, true A4 for a report), fitted and centred, never stretched. Each page's caption travels as that slide's speaker notes, so the text is selectable and searchable even though the page itself is an image.","tags":["decks"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"token","in":"query","required":false,"description":"The short-lived, pre-signed token a deck response's links.pptx already carries — present it and no Authorization header is needed. Expires after 30 minutes.","schema":{"type":"string"}}],"responses":{"200":{"description":"A PPTX file.","content":{"application/vnd.openxmlformats-officedocument.presentationml.presentation":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Missing or invalid key, and no valid token query parameter either.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"No deck with this id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"No slide has finished generating yet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/extract":{"post":{"operationId":"extractDocument","summary":"Read a PDF, a Word file, text, or a web page down to plannable text","description":"Multipart with a file field, or JSON with a url field. Use the result as `content` when creating a deck.","tags":["assets"],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"}}}},"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri"}}}}}},"responses":{"200":{"description":"The extracted text.","content":{"application/json":{"schema":{"type":"object","properties":{"document":{"type":"object","properties":{"name":{"type":"string"},"text":{"type":"string"},"pages":{"type":"integer","nullable":true}}}}}}}},"400":{"description":"Neither a file nor a url was sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"415":{"description":"That file type is not readable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/production-links":{"post":{"operationId":"createProductionLink","summary":"Mint a hosted, no-sign-in production form from this key","description":"Only an API key can call this — a production link cannot mint another one.","tags":["assets"],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"ttlDays":{"type":"integer","minimum":1,"maximum":365,"default":90}}}}}},"responses":{"200":{"description":"The link.","content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string"},"url":{"type":"string","format":"uri"},"embed":{"type":"string"}}}}}},"401":{"description":"Missing or invalid key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"A production link tried to mint another one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}}},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","bearerFormat":"sk_live_…","description":"A key from the Team page, sent as `Authorization: Bearer sk_live_…`."}},"schemas":{"Deck":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["planning","generating","done"]},"mode":{"type":"string","enum":["carousel","slide","newsletter","report"]},"ratio":{"type":"string","enum":["1:1","16:9","9:16","4:3","3:4","3:2","2:3","21:9","2:1","1:2","210:297","297:210"]},"topic":{"type":"string"},"slideCount":{"type":"integer"},"quality":{"type":"string","enum":["low","medium","high"]},"proofread":{"type":"boolean","description":"Whether each page is read back after drawing and redrawn once if its text is wrong, or it is laid out so badly it no longer does its job."},"remadeFrom":{"type":"string","nullable":true,"description":"The deck this one was remade from (same plan, other settings), or null."},"visualSystem":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"slides":{"type":"array","items":{"type":"object","properties":{"position":{"type":"integer"},"status":{"type":"string","enum":["pending","generating","done","error","blocked"]},"caption":{"type":"string"},"imagePrompt":{"type":"string"},"layout":{"type":"string","nullable":true,"description":"The named shape of this page — cover, figure, steps, comparison, table, diagram, quote, split, section, band, closing — chosen by the planner. It decides the composition the image model is briefed with and how much text the page holds."},"referenceImageUrls":{"type":"array","nullable":true,"items":{"type":"string","format":"uri"},"maxItems":3,"description":"Explicit references for this slide; null means the deck references are inherited."},"imageUrl":{"type":"string","nullable":true,"format":"uri"},"error":{"type":"string","nullable":true},"proofread":{"type":"object","nullable":true,"description":"What the proofreader said about the image shown now; null until the page is proofread, and again after a redraw.","properties":{"verdict":{"type":"string","enum":["ok","issues"]},"findings":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["missing","wrong","extra","illegible"]},"expected":{"type":"string","nullable":true},"found":{"type":"string","nullable":true},"note":{"type":"string"}}}},"renderedText":{"type":"string","nullable":true},"checkedAt":{"type":"string","format":"date-time"},"redrawn":{"type":"boolean","description":"The engine already drew this page again because of an earlier verdict."},"redrawError":{"type":"string","nullable":true,"description":"Why the engine could not draw the page again when the verdict asked for it."},"layoutVerdict":{"type":"string","nullable":true,"enum":["ok","issues"],"description":"How the page is composed against the layout it was briefed with. Null when the page had no layout to be judged against, or was read before this check existed — never \"ok\" by default."},"layoutFindings":{"type":"array","description":"What is wrong with how the page is laid out, as opposed to what it says. Empty when it is composed as briefed.","items":{"type":"object","properties":{"kind":{"type":"string","enum":["overflow","clipped","margin","hierarchy","collision","layout","decoration"],"description":"overflow: more text than the layout holds. clipped: cut off by the edge. margin: crosses the margin or touches the trim. hierarchy: no clear order, or body type too small. collision: overlapping, or text over a busy area. layout: not the composition briefed. decoration: an effect or a fake chart label nobody asked for."},"where":{"type":"string","nullable":true,"description":"Where on the page it is, in plain words."},"note":{"type":"string"},"severity":{"type":"string","enum":["blocking","minor"],"description":"blocking costs the page its purpose — text cut off, unreadable, overlapping, or the wrong composition — and is what the engine pays to redraw. minor is reported and left alone."}}}}}},"history":{"type":"array","description":"Earlier images of this page, newest first. POST …/slides/{n}/revert brings the first one back.","items":{"type":"object","properties":{"imageUrl":{"type":"string","format":"uri"},"replacedAt":{"type":"string","format":"date-time"}}}}}}},"files":{"type":"object","description":"The deck's PDF, ZIP and PowerPoint file at permanent, public URLs on a CDN. No Authorization header, no expiry, safe to store — this is what to give a publishing tool, a CMS or a scheduler that will download the file later. \"ready\" means all three URLs are current for the slides the deck shows now; \"pending\" means they are still being built (poll the deck, or POST /api/v1/decks/{id}/files to build them on the spot); \"unavailable\" means no slide has been generated yet.","properties":{"status":{"type":"string","enum":["ready","pending","unavailable"]},"pdf":{"type":"string","nullable":true,"format":"uri"},"zip":{"type":"string","nullable":true,"format":"uri"},"pptx":{"type":"string","nullable":true,"format":"uri","description":"The deck as a .pptx: one slide per page, captions as speaker notes."},"updatedAt":{"type":"string","nullable":true,"format":"date-time"}}},"links":{"type":"object","properties":{"self":{"type":"string","format":"uri"},"pdf":{"type":"string","format":"uri","description":"Renders on demand and carries a token that expires after 30 minutes. For a person clicking it. For a stored URL take files.pdf."},"zip":{"type":"string","format":"uri","description":"As links.pdf. For a stored URL take files.zip."},"pptx":{"type":"string","format":"uri","description":"As links.pdf, for the PowerPoint file. For a stored URL take files.pptx."},"studio":{"type":"string","format":"uri"}}}}},"DeckFiles":{"type":"object","description":"The deck's PDF, ZIP and PowerPoint file at permanent, public URLs on a CDN. No Authorization header, no expiry, safe to store — this is what to give a publishing tool, a CMS or a scheduler that will download the file later. \"ready\" means all three URLs are current for the slides the deck shows now; \"pending\" means they are still being built (poll the deck, or POST /api/v1/decks/{id}/files to build them on the spot); \"unavailable\" means no slide has been generated yet.","properties":{"status":{"type":"string","enum":["ready","pending","unavailable"]},"pdf":{"type":"string","nullable":true,"format":"uri"},"zip":{"type":"string","nullable":true,"format":"uri"},"pptx":{"type":"string","nullable":true,"format":"uri","description":"The deck as a .pptx: one slide per page, captions as speaker notes."},"updatedAt":{"type":"string","nullable":true,"format":"date-time"}}},"ApiError":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"}},"required":["error","code"]}}}}