{"openapi":"3.1.0","info":{"title":"Based on Us Connector API","description":"Create a personalized comic-book draft on Based on Us from a conversation, and\nhand the person a link to finish it on basedonus.com — add photos, see a free\npreview drawn from their real faces, and pay.\n\nThis API does not accept payment itself: purchase happens on basedonus.com\n(Creem is the merchant of record). It never receives photos either — those go\nstraight from the person's browser to Based on Us, matching our privacy\npolicy. See https://basedonus.com/privacy and https://basedonus.com/terms.\n","termsOfService":"https://basedonus.com/terms","contact":{"name":"Based on Us Support","url":"https://basedonus.com/","email":"support@basedonus.com"},"version":"1.0.0"},"servers":[{"url":"https://api.basedonus.com"}],"paths":{"/connector/v1/catalog":{"get":{"tags":["connector"],"summary":"List occasions, styles, tones, and length tiers","description":"Everything POST /comics validates its fields against. Poll this rather\nthan hardcoding ids — a style can be withdrawn (see\nconnector_catalog.HIDDEN_STYLE_IDS) and prices can change.","operationId":"get_catalog_connector_v1_catalog_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogOut"}}}}}}},"/connector/v1/comics":{"post":{"tags":["connector"],"summary":"Create a comic draft from what the person told the assistant","description":"Creates a `draft` order with no browser attached yet — its\n`session_id` is a unique no-browser placeholder,\n`\"connector:<random>\"`, distinct from the claim token itself (see\napp.auth.claim_token_for). POST /orders/{id}/claim-session\n(routers/orders.py) is the only thing that can bind a real browser onto\nit; MUSE_CONNECTOR_PLAN.md's \"Handoff\" section has the full design.\n\nNOT idempotent: a retried call (e.g. after a dropped response) creates a\nsecond draft, since there's no client-supplied id to dedupe on the way\nPOST /orders has one. Callers should only retry this on a connection\nerror or 5xx, never on ambiguous timeout-and-hope.","operationId":"create_comic_connector_v1_comics_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorComicCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorComicCreateOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/connector/v1/comics/{comic_id}":{"get":{"tags":["connector"],"summary":"Poll a comic draft's stage","description":"Deliberately readable by anyone holding `comic_id` — no auth — UNLIKE\nGET /orders/{id} (app.auth.check_order_access), which now 404s an\nunclaimed connector draft outright (fixes a false privacy claim: before\nthat change, this endpoint's careful redaction was pointless, since\nanyone could get the full order — story, characters, photos — straight\nthrough the ordinary wizard API). This endpoint's own redaction is the\nreal privacy boundary before the person opens continue_url: it NEVER\nreturns story text, characters, photos, the buyer's email, or a share\nlink/id, claimed or not. `continue_url` here carries NO claim token\n(unlike the one POST /comics returns) — a stranger who only knows\ncomic_id must not be able to derive it (claim_token_for(comic_id) is\nexactly that derivation) and claim the draft.","operationId":"get_comic_status_connector_v1_comics__comic_id__get","parameters":[{"name":"comic_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Comic Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorComicStatusOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"CatalogOut":{"properties":{"occasions":{"items":{"$ref":"#/components/schemas/OccasionOut"},"type":"array","title":"Occasions"},"styles":{"items":{"$ref":"#/components/schemas/StyleOut"},"type":"array","title":"Styles"},"tones":{"items":{"$ref":"#/components/schemas/ToneOut"},"type":"array","title":"Tones"},"lengths":{"items":{"$ref":"#/components/schemas/LengthOut"},"type":"array","title":"Lengths"},"limits":{"$ref":"#/components/schemas/LimitsOut"}},"type":"object","required":["occasions","styles","tones","lengths","limits"],"title":"CatalogOut"},"ConnectorCharacter":{"properties":{"name":{"type":"string","maxLength":80,"minLength":1,"title":"Name","description":"Character's name (required)."},"role":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Role","description":"Who they are, e.g. \"girlfriend\", \"our dog\"."},"traits":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Traits","description":"Personality or physical traits."},"visual_notes":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Visual Notes","description":"Notes for how they should look."}},"type":"object","required":["name"],"title":"ConnectorCharacter","description":"One cast member. Photos are added later, in the browser — see the\nmodule docstring for why they never transit the connector."},"ConnectorComicCreate":{"properties":{"occasion":{"type":"string","title":"Occasion","description":"Occasion id from GET /catalog."},"style":{"type":"string","title":"Style","description":"Visible style id from GET /catalog (a hidden/unknown id 422s)."},"tone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tone","description":"Tone id from GET /catalog."},"length":{"type":"string","title":"Length","description":"Panel-count tier id from GET /catalog: \"12\" | \"18\" | \"24\".","default":"18"},"story":{"$ref":"#/components/schemas/ConnectorStoryDetails"},"characters":{"anyOf":[{"items":{"$ref":"#/components/schemas/ConnectorCharacter"},"type":"array","maxItems":4},{"type":"null"}],"title":"Characters","description":"Cast, if known yet."},"gift_to":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Gift To","description":"Recipient's name."},"gift_from":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Gift From","description":"Sender's name."},"gift_message":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Gift Message","description":"A short gift note."},"source":{"type":"string","maxLength":40,"title":"Source","description":"Caller identity for analytics, e.g. \"muse\".","default":"connector"}},"type":"object","required":["occasion","style","story"],"title":"ConnectorComicCreate","example":{"characters":[{"name":"Alex","role":"me"},{"name":"Sam","role":"my partner"}],"gift_from":"Alex","length":"18","occasion":"couple","source":"muse","story":{"about":"Our first camping trip together, and the raccoon that stole our marshmallows.","ending_preference":"with us laughing about it back at the tent"},"style":"watercolor","tone":"romantic"}},"ConnectorComicCreateOut":{"properties":{"comic_id":{"type":"string","format":"uuid","title":"Comic Id"},"stage":{"type":"string","enum":["draft","preview_ready","generating","ready","failed"],"title":"Stage"},"continue_url":{"type":"string","title":"Continue Url","description":"Open this on basedonus.com to finish the comic: add photos, see the free preview, and pay. Carries a claim token that stays valid until the person starts adding photos — see 'How the handoff works' on /developers."},"next_steps":{"items":{"type":"string"},"type":"array","title":"Next Steps"},"length":{"type":"string","title":"Length"},"price_cents":{"type":"integer","title":"Price Cents"},"currency":{"type":"string","title":"Currency"}},"type":"object","required":["comic_id","stage","continue_url","next_steps","length","price_cents","currency"],"title":"ConnectorComicCreateOut"},"ConnectorComicStatusOut":{"properties":{"comic_id":{"type":"string","format":"uuid","title":"Comic Id"},"stage":{"type":"string","enum":["draft","preview_ready","generating","ready","failed"],"title":"Stage"},"length":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Length"},"price_cents":{"type":"integer","title":"Price Cents"},"currency":{"type":"string","title":"Currency"},"continue_url":{"type":"string","title":"Continue Url","description":"Open this on basedonus.com to continue the comic."}},"type":"object","required":["comic_id","stage","length","price_cents","currency","continue_url"],"title":"ConnectorComicStatusOut"},"ConnectorStoryDetails":{"properties":{"about":{"type":"string","maxLength":2000,"minLength":1,"title":"About","description":"What is this comic about? (required)"},"inside_jokes":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Inside Jokes","description":"Inside jokes to weave in."},"important_memory":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Important Memory","description":"A specific memory to include."},"things_to_include":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Things To Include","description":"Anything else that must appear."},"things_to_avoid":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Things To Avoid","description":"Anything to leave out."},"ending_preference":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Ending Preference","description":"How the story should end."}},"type":"object","required":["about"],"title":"ConnectorStoryDetails","description":"Same field caps as schemas.StoryFields, minus `clarifications` — that\nfield is an AI-generated question/answer round trip that only happens\nonce the person is on the wizard, after handoff."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"LengthOut":{"properties":{"id":{"type":"string","title":"Id","description":"Panel-count tier: \"12\" | \"18\" | \"24\"."},"label":{"type":"string","title":"Label"},"panels":{"type":"integer","title":"Panels"},"price_cents":{"type":"integer","title":"Price Cents"},"currency":{"type":"string","title":"Currency"},"recommended":{"type":"boolean","title":"Recommended","description":"The tier most buyers pick."}},"type":"object","required":["id","label","panels","price_cents","currency","recommended"],"title":"LengthOut"},"LimitsOut":{"properties":{"max_characters":{"type":"integer","title":"Max Characters"},"max_photos_per_character":{"type":"integer","title":"Max Photos Per Character","description":"Photos are added later, in the browser — the connector never uploads any."}},"type":"object","required":["max_characters","max_photos_per_character"],"title":"LimitsOut"},"OccasionOut":{"properties":{"id":{"type":"string","title":"Id","description":"Occasion id — pass this to POST /comics."},"label":{"type":"string","title":"Label"},"description":{"type":"string","title":"Description"}},"type":"object","required":["id","label","description"],"title":"OccasionOut"},"StyleOut":{"properties":{"id":{"type":"string","title":"Id","description":"Visible style id — pass this to POST /comics."},"label":{"type":"string","title":"Label"}},"type":"object","required":["id","label"],"title":"StyleOut"},"ToneOut":{"properties":{"id":{"type":"string","title":"Id"},"label":{"type":"string","title":"Label"}},"type":"object","required":["id","label"],"title":"ToneOut"},"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"}}}}