{"components":{"schemas":{"CaptionRequest":{"properties":{"audience":{"description":"Who will see the meme (e.g. engineering slack).","maxLength":200,"type":"string"},"preferredTemplateSlug":{"description":"Catalog slug to pin as the first variant when it fits the prompt.","maxLength":200,"type":"string"},"prompt":{"description":"Situation or joke seed.","maxLength":2000,"minLength":3,"type":"string"},"tone":{"maxLength":100,"type":"string"},"uncensored":{"default":false,"description":"Use the uncensored caption model when true.","type":"boolean"}},"required":["prompt"],"type":"object"},"CaptionResponse":{"properties":{"creationId":{"format":"uuid","type":"string"},"guestQuota":{"description":"Present for anonymous sessions; null for signed-in users.","properties":{"limit":{"type":"integer"},"remaining":{"type":"integer"},"used":{"type":"integer"}},"required":["limit","remaining","used"],"type":["object","null"]},"model":{"type":"string"},"requiresAccountToSave":{"type":"boolean"},"returnedCount":{"type":"integer"},"uncensored":{"type":"boolean"},"variants":{"description":"Four to ten unique templates. Each item includes artifactId, templateSlug, and captions[].","items":{"description":"One template + caption set from a batch. Typical batches return 4 variants.","properties":{"artifactId":{"description":"Persisted artifact UUID when the row was saved. Omitted if persistence failed.","format":"uuid","type":"string"},"captions":{"description":"Caption strings in template box order. Length matches the template's textBoxes.","items":{"maxLength":80,"type":"string"},"type":"array"},"templateSlug":{"description":"Catalog JSON slug (e.g. drake-hotline-bling), not the URL path.","type":"string"}},"required":["captions","templateSlug"],"type":"object"},"minItems":4,"type":"array"}},"required":["creationId","model","requiresAccountToSave","returnedCount","uncensored","variants"],"type":"object"},"CaptionVariant":{"description":"One template + caption set from a batch. Typical batches return 4 variants.","properties":{"artifactId":{"description":"Persisted artifact UUID when the row was saved. Omitted if persistence failed.","format":"uuid","type":"string"},"captions":{"description":"Caption strings in template box order. Length matches the template's textBoxes.","items":{"maxLength":80,"type":"string"},"type":"array"},"templateSlug":{"description":"Catalog JSON slug (e.g. drake-hotline-bling), not the URL path.","type":"string"}},"required":["captions","templateSlug"],"type":"object"},"Error":{"properties":{"error":{"type":"string"}},"required":["error"],"type":"object"},"GuestQuota":{"properties":{"limit":{"type":"integer"},"remaining":{"type":"integer"},"used":{"type":"integer"}},"required":["limit","remaining","used"],"type":"object"},"MemeTemplate":{"description":"Catalog record. Blank template art lives at imageUrl. There is no public URL for a finished PNG.","properties":{"about":{"type":"string"},"category":{"type":"string"},"description":{"type":"string"},"id":{"type":"integer"},"imageUrl":{"description":"CDN URL of the blank template image.","format":"uri","type":"string"},"keywords":{"items":{"type":"string"},"type":"array"},"name":{"type":"string"},"slug":{"type":"string"},"templateSpecifics":{"properties":{"generation":{"properties":{"exampleCaptions":{"items":{"items":{"type":"string"},"type":"array"},"type":"array"},"format":{"type":"string"},"formula":{"type":"string"}},"type":"object"},"textBoxes":{"items":{"description":"Canvas-percent bounding box for a caption or image slot.","properties":{"default":{"type":"string"},"height":{"type":"number"},"id":{"type":["string","number"]},"label":{"type":"string"},"maxChars":{"type":"integer"},"origin":{"enum":["center","rect"],"type":"string"},"role":{"enum":["caption","label","dialogue","watermark"],"type":"string"},"type":{"enum":["text","image"],"type":"string"},"width":{"type":"number"},"x":{"type":"number"},"y":{"type":"number"}},"required":["width","x","y"],"type":"object"},"type":"array"}},"type":"object"},"textBoxes":{"items":{"description":"Canvas-percent bounding box for a caption or image slot.","properties":{"default":{"type":"string"},"height":{"type":"number"},"id":{"type":["string","number"]},"label":{"type":"string"},"maxChars":{"type":"integer"},"origin":{"enum":["center","rect"],"type":"string"},"role":{"enum":["caption","label","dialogue","watermark"],"type":"string"},"type":{"enum":["text","image"],"type":"string"},"width":{"type":"number"},"x":{"type":"number"},"y":{"type":"number"}},"required":["width","x","y"],"type":"object"},"type":"array"},"title":{"type":"string"},"useCases":{"items":{"type":"string"},"type":"array"}},"required":["id","imageUrl","name","slug","textBoxes"],"type":"object"},"RenderRequest":{"properties":{"captions":{"description":"Caption strings in textBoxes order.","items":{"type":"string"},"type":"array"},"format":{"default":"mp4","description":"Output container. Still PNGs are not supported.","enum":["mp4","gif"],"type":"string"},"height":{"maximum":1920,"minimum":64,"type":"integer"},"imageUrl":{"description":"Allowlisted CDN template URL (cdn.magicmeme.com). Arbitrary remote URLs are rejected.","type":"string"},"textBoxes":{"description":"Template bounding boxes used by the Remotion composition.","items":{"description":"Canvas-percent bounding box for a caption or image slot.","properties":{"default":{"type":"string"},"height":{"type":"number"},"id":{"type":["string","number"]},"label":{"type":"string"},"maxChars":{"type":"integer"},"origin":{"enum":["center","rect"],"type":"string"},"role":{"enum":["caption","label","dialogue","watermark"],"type":"string"},"type":{"enum":["text","image"],"type":"string"},"width":{"type":"number"},"x":{"type":"number"},"y":{"type":"number"}},"required":["width","x","y"],"type":"object"},"type":"array"},"width":{"maximum":1920,"minimum":64,"type":"integer"}},"required":["imageUrl"],"type":"object"},"ShareRequest":{"properties":{"artifactId":{"description":"Workspace artifact to publish as an unlisted share.","format":"uuid","type":"string"}},"required":["artifactId"],"type":"object"},"ShareResponse":{"properties":{"share":{"properties":{"artifactId":{"format":"uuid","type":"string"},"createdAt":{"format":"date-time","type":"string"},"id":{"format":"uuid","type":"string"},"noindex":{"type":"boolean"},"slug":{"type":"string"}},"required":["artifactId","id","noindex","slug"],"type":"object"},"url":{"description":"Site-relative share path, e.g. /s/a1b2c3d4e5f6.","type":"string"}},"required":["share","url"],"type":"object"},"TextBox":{"description":"Canvas-percent bounding box for a caption or image slot.","properties":{"default":{"type":"string"},"height":{"type":"number"},"id":{"type":["string","number"]},"label":{"type":"string"},"maxChars":{"type":"integer"},"origin":{"enum":["center","rect"],"type":"string"},"role":{"enum":["caption","label","dialogue","watermark"],"type":"string"},"type":{"enum":["text","image"],"type":"string"},"width":{"type":"number"},"x":{"type":"number"},"y":{"type":"number"}},"required":["width","x","y"],"type":"object"}}},"info":{"description":"Caption-on-template meme studio. One situation in, four editable memes out. PNG download happens in the browser editor — these endpoints do not return a finished still image.\n\nThere is no CORS: browser JavaScript on other origins cannot call these APIs. Server-side clients (curl, backends, MCP) can.\n\nPOST /api/ai/captions creates an anonymous session when none exists; persist Set-Cookie on follow-up calls. Guests get one template batch per UTC day (HTTP 429 when exhausted). POST /api/shares requires a signed-in, non-anonymous user. POST /api/render is for animated templates (MP4/GIF) with allowlisted CDN image URLs only.","title":"MagicMeme API","version":"0.1.0"},"jsonSchemaDialect":"https://json-schema.org/draft/2020-12/schema","openapi":"3.1.0","paths":{"/api/ai/captions":{"post":{"description":"Generate a caption batch for a prompt or situation. Only prompt is required (3–2000 characters). Optional preferredTemplateSlug, audience, tone, and uncensored pin format and voice.\n\nCreates an anonymous Better Auth session when the request has none. Response variants[] (typically 4, up to 10) each include templateSlug, captions[], and artifactId. This does not return a rendered image — send the human to /create?prompt=... to edit and download a PNG.","operationId":"generateCaptions","requestBody":{"content":{"application/json":{"schema":{"properties":{"audience":{"description":"Who will see the meme (e.g. engineering slack).","maxLength":200,"type":"string"},"preferredTemplateSlug":{"description":"Catalog slug to pin as the first variant when it fits the prompt.","maxLength":200,"type":"string"},"prompt":{"description":"Situation or joke seed.","maxLength":2000,"minLength":3,"type":"string"},"tone":{"maxLength":100,"type":"string"},"uncensored":{"default":false,"description":"Use the uncensored caption model when true.","type":"boolean"}},"required":["prompt"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"creationId":{"format":"uuid","type":"string"},"guestQuota":{"description":"Present for anonymous sessions; null for signed-in users.","properties":{"limit":{"type":"integer"},"remaining":{"type":"integer"},"used":{"type":"integer"}},"required":["limit","remaining","used"],"type":["object","null"]},"model":{"type":"string"},"requiresAccountToSave":{"type":"boolean"},"returnedCount":{"type":"integer"},"uncensored":{"type":"boolean"},"variants":{"description":"Four to ten unique templates. Each item includes artifactId, templateSlug, and captions[].","items":{"description":"One template + caption set from a batch. Typical batches return 4 variants.","properties":{"artifactId":{"description":"Persisted artifact UUID when the row was saved. Omitted if persistence failed.","format":"uuid","type":"string"},"captions":{"description":"Caption strings in template box order. Length matches the template's textBoxes.","items":{"maxLength":80,"type":"string"},"type":"array"},"templateSlug":{"description":"Catalog JSON slug (e.g. drake-hotline-bling), not the URL path.","type":"string"}},"required":["captions","templateSlug"],"type":"object"},"minItems":4,"type":"array"}},"required":["creationId","model","requiresAccountToSave","returnedCount","uncensored","variants"],"type":"object"}}},"description":"Caption batch with persisted artifact ids."},"401":{"content":{"application/json":{"schema":{"properties":{"error":{"type":"string"}},"required":["error"],"type":"object"}}},"description":"Unable to create a session."},"429":{"content":{"application/json":{"schema":{"properties":{"error":{"type":"string"}},"required":["error"],"type":"object"}}},"description":"Guest daily template allowance exhausted. Sign in to continue."},"500":{"content":{"application/json":{"schema":{"properties":{"error":{"type":"string"}},"required":["error"],"type":"object"}}},"description":"Generation failed, or the request body failed validation."}},"summary":"Generate AI meme captions","tags":["captions"]}},"/api/memes":{"get":{"description":"Full meme catalog (hundreds of records) including text-box geometry and imageUrl. Fetch when you need a slug or box count. Do not paste the catalog into chat.","operationId":"listMemes","responses":{"200":{"content":{"application/json":{"schema":{"items":{"description":"Catalog record. Blank template art lives at imageUrl. There is no public URL for a finished PNG.","properties":{"about":{"type":"string"},"category":{"type":"string"},"description":{"type":"string"},"id":{"type":"integer"},"imageUrl":{"description":"CDN URL of the blank template image.","format":"uri","type":"string"},"keywords":{"items":{"type":"string"},"type":"array"},"name":{"type":"string"},"slug":{"type":"string"},"templateSpecifics":{"properties":{"generation":{"properties":{"exampleCaptions":{"items":{"items":{"type":"string"},"type":"array"},"type":"array"},"format":{"type":"string"},"formula":{"type":"string"}},"type":"object"},"textBoxes":{"items":{"description":"Canvas-percent bounding box for a caption or image slot.","properties":{"default":{"type":"string"},"height":{"type":"number"},"id":{"type":["string","number"]},"label":{"type":"string"},"maxChars":{"type":"integer"},"origin":{"enum":["center","rect"],"type":"string"},"role":{"enum":["caption","label","dialogue","watermark"],"type":"string"},"type":{"enum":["text","image"],"type":"string"},"width":{"type":"number"},"x":{"type":"number"},"y":{"type":"number"}},"required":["width","x","y"],"type":"object"},"type":"array"}},"type":"object"},"textBoxes":{"items":{"description":"Canvas-percent bounding box for a caption or image slot.","properties":{"default":{"type":"string"},"height":{"type":"number"},"id":{"type":["string","number"]},"label":{"type":"string"},"maxChars":{"type":"integer"},"origin":{"enum":["center","rect"],"type":"string"},"role":{"enum":["caption","label","dialogue","watermark"],"type":"string"},"type":{"enum":["text","image"],"type":"string"},"width":{"type":"number"},"x":{"type":"number"},"y":{"type":"number"}},"required":["width","x","y"],"type":"object"},"type":"array"},"title":{"type":"string"},"useCases":{"items":{"type":"string"},"type":"array"}},"required":["id","imageUrl","name","slug","textBoxes"],"type":"object"},"type":"array"}}},"description":"Catalog of meme templates."},"500":{"content":{"application/json":{"schema":{"properties":{"error":{"type":"string"}},"required":["error"],"type":"object"}}},"description":"Failed to fetch memes."}},"summary":"List meme templates","tags":["catalog"]}},"/api/render":{"post":{"description":"Remotion renderer for animated templates. Accepts imageUrl (allowlisted CDN only), captions, textBoxes, optional width/height (64–1920), and format mp4 (default) or gif.\n\nDo not call this for a still PNG — those are downloaded in the editor. Untrusted image URLs return HTTP 400.","operationId":"renderAnimation","requestBody":{"content":{"application/json":{"schema":{"properties":{"captions":{"description":"Caption strings in textBoxes order.","items":{"type":"string"},"type":"array"},"format":{"default":"mp4","description":"Output container. Still PNGs are not supported.","enum":["mp4","gif"],"type":"string"},"height":{"maximum":1920,"minimum":64,"type":"integer"},"imageUrl":{"description":"Allowlisted CDN template URL (cdn.magicmeme.com). Arbitrary remote URLs are rejected.","type":"string"},"textBoxes":{"description":"Template bounding boxes used by the Remotion composition.","items":{"description":"Canvas-percent bounding box for a caption or image slot.","properties":{"default":{"type":"string"},"height":{"type":"number"},"id":{"type":["string","number"]},"label":{"type":"string"},"maxChars":{"type":"integer"},"origin":{"enum":["center","rect"],"type":"string"},"role":{"enum":["caption","label","dialogue","watermark"],"type":"string"},"type":{"enum":["text","image"],"type":"string"},"width":{"type":"number"},"x":{"type":"number"},"y":{"type":"number"}},"required":["width","x","y"],"type":"object"},"type":"array"},"width":{"maximum":1920,"minimum":64,"type":"integer"}},"required":["imageUrl"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"image/gif":{"schema":{"description":"GIF when format=gif.","format":"binary","type":"string"}},"video/mp4":{"schema":{"description":"H.264 MP4 when format=mp4 (default).","format":"binary","type":"string"}}},"description":"Rendered animation as an attachment."},"400":{"content":{"application/json":{"schema":{"properties":{"error":{"type":"string"}},"required":["error"],"type":"object"}}},"description":"Missing imageUrl, invalid dimensions, or untrusted image URL."},"500":{"content":{"application/json":{"schema":{"properties":{"error":{"type":"string"}},"required":["error"],"type":"object"}}},"description":"Composition or render failure."}},"summary":"Render animated meme (MP4/GIF)","tags":["render"]}},"/api/shares":{"post":{"description":"Create a public unlisted share link for an artifact the signed-in user owns. Anonymous sessions receive 401. Face/reference artifacts cannot be published (403). The artifact is marked visibility=unlisted. Returned url is a site-relative path under /s/{slug}.","operationId":"createShare","requestBody":{"content":{"application/json":{"schema":{"properties":{"artifactId":{"description":"Workspace artifact to publish as an unlisted share.","format":"uuid","type":"string"}},"required":["artifactId"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"share":{"properties":{"artifactId":{"format":"uuid","type":"string"},"createdAt":{"format":"date-time","type":"string"},"id":{"format":"uuid","type":"string"},"noindex":{"type":"boolean"},"slug":{"type":"string"}},"required":["artifactId","id","noindex","slug"],"type":"object"},"url":{"description":"Site-relative share path, e.g. /s/a1b2c3d4e5f6.","type":"string"}},"required":["share","url"],"type":"object"}}},"description":"Share record and relative URL."},"401":{"content":{"application/json":{"schema":{"properties":{"error":{"type":"string"}},"required":["error"],"type":"object"}}},"description":"Sign in required to publish a share link (anonymous users cannot share)."},"403":{"content":{"application/json":{"schema":{"properties":{"error":{"type":"string"}},"required":["error"],"type":"object"}}},"description":"Face/reference outputs cannot be published at launch."},"404":{"content":{"application/json":{"schema":{"properties":{"error":{"type":"string"}},"required":["error"],"type":"object"}}},"description":"Artifact not found in the user workspace."}},"summary":"Create an unlisted share link","tags":["shares"]}}},"servers":[{"description":"Production","url":"https://magicmeme.com"}],"tags":[{"description":"AI caption batches for the create studio.","name":"captions"},{"description":"Meme template catalog.","name":"catalog"},{"description":"Animated template renderer.","name":"render"},{"description":"Unlisted public share links.","name":"shares"}]}