{"openapi":"3.1.0","info":{"title":"Signal API","version":"0.1.0"},"paths":{"/auth/me":{"get":{"tags":["auth"],"summary":"Me","description":"Identity + onboarding + plan state. One round-trip on first paint\nof any authed page; cached client-side until sign-out.","operationId":"me_auth_me_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/me/welcome":{"patch":{"tags":["auth"],"summary":"Mark Welcome Seen","description":"Mark the welcome deck as seen. Called when the user clicks\n'Type your beat →' on the final slide OR clicks 'Skip'. Idempotent —\nre-marking just leaves the existing timestamp in place.","operationId":"mark_welcome_seen_auth_me_welcome_patch","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/me/api-keys":{"get":{"tags":["auth"],"summary":"List Api Keys","description":"List all keys for the current user, including 24h credit burn\nper PAT. The full token is never returned — only the prefix +\nmetadata + burn.\n\nBurn computation: one GROUP BY on credit_transactions for the\nuser's keys. Avoids N+1; cheap even at hundreds of PATs.","operationId":"list_api_keys_auth_me_api_keys_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Api Keys Auth Me Api Keys Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["auth"],"summary":"Create Api Key Route","description":"Mint a new PAT. The plaintext is returned exactly once in the\nresponse body — the UI must show it immediately and warn the user\nthey won't see it again.","operationId":"create_api_key_route_auth_me_api_keys_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateKeyRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateKeyResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/me/api-keys/{key_id}":{"delete":{"tags":["auth"],"summary":"Revoke Api Key Route","description":"Soft-delete the key. Subsequent requests with that token return 401.","operationId":"revoke_api_key_route_auth_me_api_keys__key_id__delete","parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Key Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sessions":{"get":{"tags":["sessions"],"summary":"List Sessions","description":"List all sessions for the current user, newest first.","operationId":"list_sessions_sessions_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":100,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SessionResponse"},"title":"Response List Sessions Sessions Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["sessions"],"summary":"Start Session","operationId":"start_session_sessions_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartSessionRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sessions/{session_id}/stream":{"get":{"tags":["sessions"],"summary":"Stream Session","description":"SSE endpoint. Client connects and receives progress events until complete.\n\nBrowser `EventSource` cannot attach an Authorization header — so this\nendpoint accepts the Supabase access token via `?token=` query param as a\nfallback. The Bearer-header path still works for non-EventSource callers\n(curl, agent SDKs). Token is shipped over TLS only and never logged.","operationId":"stream_session_sessions__session_id__stream_get","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}},{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sessions/{session_id}/story":{"post":{"tags":["sessions"],"summary":"Select Story","operationId":"select_story_sessions__session_id__story_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StorySelectionRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sessions/seen-titles":{"get":{"tags":["sessions"],"summary":"Seen Story Titles","description":"Return the set of normalized titles this user has already picked. Used by\nthe StoryGrid frontend to show the 'Previously covered' badge across runs.","operationId":"seen_story_titles_sessions_seen_titles_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"string"},"title":"Response Seen Story Titles Sessions Seen Titles Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sessions/{session_id}/stories/refine":{"post":{"tags":["sessions"],"summary":"Refine Stories","operationId":"refine_stories_sessions__session_id__stories_refine_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StoryRefineRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StoryWorkspaceResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sessions/{session_id}/angle":{"post":{"tags":["sessions"],"summary":"Select Angle","operationId":"select_angle_sessions__session_id__angle_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AngleSelectionRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sessions/{session_id}/angles/regenerate":{"post":{"tags":["sessions"],"summary":"Regenerate Angles","operationId":"regenerate_angles_sessions__session_id__angles_regenerate_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AngleRegenerateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sessions/{session_id}/revert-to-story":{"post":{"tags":["sessions"],"summary":"Revert To Story","description":"Go back to CP1 (story selection) from anywhere in or past the pipeline.\nCancels the current orchestrator task, clears all state from CP1 onward,\nand re-spawns. The orchestrator's idempotent stages will skip work that's\nalready done (research, clustering, ranking) and land cleanly at CP1.\n\nAllowed at any point after stories have been ranked — including during\nin-flight stages like generating_angles, applying_voice, generating_content,\nor rendering. The orchestrator handles the cancellation cleanly via\ntask_registry.cancel.","operationId":"revert_to_story_sessions__session_id__revert_to_story_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StoryWorkspaceResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sessions/{session_id}/revert-to-angle":{"post":{"tags":["sessions"],"summary":"Revert To Angle","description":"Go back to CP2 (angle selection) from anywhere past angle generation.\nKeeps the selected story; clears the chosen angle and downstream content/renders.\n\nAllowed at any point after angles have been generated — including during\nin-flight stages like applying_voice, generating_content, or rendering.","operationId":"revert_to_angle_sessions__session_id__revert_to_angle_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AngleListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sessions/{session_id}/review":{"post":{"tags":["sessions"],"summary":"Submit Review","operationId":"submit_review_sessions__session_id__review_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewSubmitRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sessions/{session_id}/outputs/add":{"post":{"tags":["sessions"],"summary":"Add Output Endpoint","description":"Add an output cell to a session that's at CP3+. Web-facing wrapper\nover the same logic as the niche_add_output MCP tool. Idempotent on\n(session_id, cell) — returns 200 with the existing Output when the\ncell is already on the session.\n\nUsed by the filing sheet's \"+ Add output\" picker to drop in another\nsurface mid-review (e.g. session started with linkedin:text_post,\nuser reviews drafts, decides to also add instagram:carousel).","operationId":"add_output_endpoint_sessions__session_id__outputs_add_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddOutputRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sessions/{session_id}/render/image-card":{"post":{"tags":["sessions"],"summary":"Render Image Card Endpoint","description":"On-demand image-card render at CP3. Thin REST wrapper over\napp.services.render — same code path serves the MCP\n`niche_render_image_card` tool.","operationId":"render_image_card_endpoint_sessions__session_id__render_image_card_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ImageCardRenderRequest"},{"type":"null"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sessions/{session_id}/render/video":{"post":{"tags":["sessions"],"summary":"Render Video Endpoint","description":"On-demand reel render at CP3. Thin REST wrapper over\napp.services.render — same code path serves the MCP\n`niche_render_reel` tool.","operationId":"render_video_endpoint_sessions__session_id__render_video_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VideoRenderRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sessions/niches":{"get":{"tags":["sessions"],"summary":"List Niches","description":"Return all distinct niches with run counts and last-run date.","operationId":"list_niches_sessions_niches_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["sessions"],"summary":"Delete Niche","description":"Delete all sessions for a given niche.","operationId":"delete_niche_sessions_niches_delete","parameters":[{"name":"niche","in":"query","required":true,"schema":{"type":"string","title":"Niche"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sessions/niches/rename":{"patch":{"tags":["sessions"],"summary":"Rename Niche","description":"Rename all sessions with old_niche to new_niche.","operationId":"rename_niche_sessions_niches_rename_patch","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NicheRenameRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sessions/niches/merge":{"post":{"tags":["sessions"],"summary":"Merge Niches","description":"Fold all sessions from source niche into target niche, then return combined list.","operationId":"merge_niches_sessions_niches_merge_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NicheMergeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sessions/{session_id}":{"delete":{"tags":["sessions"],"summary":"Delete Session","description":"Hard-delete a session and everything it owns. Used by the archive\nUI to clean up stalled / failed / abandoned runs. Cancels any in-flight\norchestrator first so the worker doesn't write to a deleted session.\n\nSafe to call on any session the user owns regardless of status —\ncompleted runs delete cleanly too (the user might want to clear the\narchive). FK children that don't have CASCADE are wiped here:\noutputs, story_picks, scheduled_posts.","operationId":"delete_session_sessions__session_id__delete","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["sessions"],"summary":"Get Session","description":"Returns the session row plus a few derived fields the run page needs\nfor its wait states (niche_profile, selected_story, contributing signals\nfor the picked story).","operationId":"get_session_sessions__session_id__get","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sessions/{session_id}/provenance":{"get":{"tags":["sessions"],"summary":"Get Provenance","description":"Return the 'how this was made' chain for a completed (or in-review) session.","operationId":"get_provenance_sessions__session_id__provenance_get","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProvenanceResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sessions/{session_id}/credits":{"get":{"tags":["sessions"],"summary":"Get Session Credits","description":"Per-run credit breakdown by action. Sums commit-kind rows on the\nledger grouped by `action`. Surfaced on the archive row hover + on\nthe run page's post-run summary card.","operationId":"get_session_credits_sessions__session_id__credits_get","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditBreakdownResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sessions/{session_id}/hooks":{"post":{"tags":["sessions"],"summary":"Generate Hook Variants","description":"Generate alternate opening lines for an already-rendered post. Body stays;\nuser picks a hook variant and the frontend replaces the leading paragraph.","operationId":"generate_hook_variants_sessions__session_id__hooks_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HookVariantsRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HookVariantsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/brand-kit/list":{"get":{"tags":["brand-kit"],"summary":"List Brands","description":"All brand kits the user owns + plan-cap state. Drives the\n/brand-kit roster surface + the composer brand picker.","operationId":"list_brands_brand_kit_list_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandKitListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/brand-kit/create":{"post":{"tags":["brand-kit"],"summary":"Create Brand","description":"Create a new brand kit. Slug must be unique-per-user + matches\n`[a-z0-9][a-z0-9_-]*`. 402 when the user is at their plan cap;\n409 when the slug is already in use.","operationId":"create_brand_brand_kit_create_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandKitCreateRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandKitResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/brand-kit":{"get":{"tags":["brand-kit"],"summary":"Get Brand Kit","operationId":"get_brand_kit_brand_kit_get","parameters":[{"name":"brand_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Brand Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandKitResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["brand-kit"],"summary":"Update Brand Kit","operationId":"update_brand_kit_brand_kit_put","parameters":[{"name":"brand_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Brand Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandKitUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandKitResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/brand-kit/upload/logo":{"post":{"tags":["brand-kit"],"summary":"Upload Logo","operationId":"upload_logo_brand_kit_upload_logo_post","parameters":[{"name":"brand_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Brand Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_logo_brand_kit_upload_logo_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandKitResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/brand-kit/upload/endcard-image":{"post":{"tags":["brand-kit"],"summary":"Upload Endcard Image","description":"Upload a custom 1080×1920 PNG/JPG to use as the reel endcard.\nWhen set, the renderer short-circuits the Playwright endcard render and\nuses this image as-is (still + Ken-Burns motion via ffmpeg). Replaces\nany previously-uploaded endcard image.","operationId":"upload_endcard_image_brand_kit_upload_endcard_image_post","parameters":[{"name":"brand_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Brand Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_endcard_image_brand_kit_upload_endcard_image_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandKitResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/brand-kit/upload/endcard-video":{"post":{"tags":["brand-kit"],"summary":"Upload Endcard Video","description":"Upload a custom 1080×1920 MP4 clip (≤ ~5s recommended) to use as the\nreel endcard. The renderer normalizes it (scale-pad to 1080×1920, trim\nor loop to the endcard beat duration, strip audio) and splices it into\nthe reel in place of the rendered endcard PNG.","operationId":"upload_endcard_video_brand_kit_upload_endcard_video_post","parameters":[{"name":"brand_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Brand Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_endcard_video_brand_kit_upload_endcard_video_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandKitResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/brand-kit/endcard-asset":{"delete":{"tags":["brand-kit"],"summary":"Remove Endcard Asset","description":"Drop the custom endcard image + video so the renderer falls back to\nthe template + mark preference. Doesn't touch the R2 files; orphaned\nbut cheap.","operationId":"remove_endcard_asset_brand_kit_endcard_asset_delete","parameters":[{"name":"brand_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Brand Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandKitResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/brand-kit/upload/product-image":{"post":{"tags":["brand-kit"],"summary":"Upload Product Image","operationId":"upload_product_image_brand_kit_upload_product_image_post","parameters":[{"name":"brand_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Brand Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_product_image_brand_kit_upload_product_image_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandKitResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/brand-kit/import/shopify":{"post":{"tags":["brand-kit"],"summary":"Import Shopify","operationId":"import_shopify_brand_kit_import_shopify_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShopifyImportRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/brand-kit/sources":{"delete":{"tags":["brand-kit"],"summary":"Remove Source Asset","description":"Remove a single source asset from the kit's `source_assets` list by URL.\nThe underlying file on R2 is left in place — orphaned, but cheap; a\nsweep job can clean orphans later.","operationId":"remove_source_asset_brand_kit_sources_delete","parameters":[{"name":"url","in":"query","required":true,"schema":{"type":"string","title":"Url"}},{"name":"brand_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Brand Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandKitResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/brand-kit/reset":{"post":{"tags":["brand-kit"],"summary":"Reset Brand Kit","description":"Wipe the brand kit back to defaults — drops every extracted field,\nevery source asset, every override. Use after removing source files so\nthe kit reflects an empty state instead of stale extractions.\n\nNote: R2 files referenced by old source_assets are left orphan-but-cheap.\nFuture cleanup job sweeps unreferenced keys.","operationId":"reset_brand_kit_brand_kit_reset_post","parameters":[{"name":"brand_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Brand Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandKitResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/brand-kit/ingest":{"post":{"tags":["brand-kit"],"summary":"Ingest Brand Kit","description":"Drop-zone + URL/text ingest. See `app.services.brand_kit_ingest` for the\nengine. Engine commits confidently — fills empty fields, leaves populated\nones alone. Never asks the user to clarify.","operationId":"ingest_brand_kit_brand_kit_ingest_post","parameters":[{"name":"brand_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Brand Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_ingest_brand_kit_brand_kit_ingest_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IngestReport"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/brand-kit/{brand_id}":{"delete":{"tags":["brand-kit"],"summary":"Delete Brand","description":"Delete a non-default brand kit. Cannot delete the user's default\nbrand — they must promote another first via /set-default.","operationId":"delete_brand_brand_kit__brand_id__delete","parameters":[{"name":"brand_id","in":"path","required":true,"schema":{"type":"string","title":"Brand Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/brand-kit/{brand_id}/set-default":{"post":{"tags":["brand-kit"],"summary":"Set Default Brand","description":"Promote a brand to the user's default. The pipeline picks the\ndefault whenever session_start doesn't pass an explicit brand_id.","operationId":"set_default_brand_brand_kit__brand_id__set_default_post","parameters":[{"name":"brand_id","in":"path","required":true,"schema":{"type":"string","title":"Brand Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/voice/extract":{"post":{"tags":["voice"],"summary":"Extract Voice","description":"Extract voice primitives from 1-10 pasted past posts. Stores on the user's\nVoiceProfile row (creating one if needed). Layers the optional audience + avoid\ndescriptors alongside.\n\nBacked by `app.services.voice_extraction` — the same engine the brand-kit\ningest calls into when it auto-scrapes a social URL.","operationId":"extract_voice_voice_extract_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoiceExtractRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoiceExtractResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/voice/questions":{"get":{"tags":["voice"],"summary":"Get Interview Questions","operationId":"get_interview_questions_voice_questions_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/voice/interview":{"post":{"tags":["voice"],"summary":"Submit Interview","operationId":"submit_interview_voice_interview_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InterviewRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoiceProfileResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/voice":{"get":{"tags":["voice"],"summary":"Get Voice Profile","operationId":"get_voice_profile_voice_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoiceProfileResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/outputs":{"get":{"tags":["outputs"],"summary":"List Outputs","operationId":"list_outputs_outputs_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/OutputResponse"},"title":"Response List Outputs Outputs Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/outputs/{output_id}":{"get":{"tags":["outputs"],"summary":"Get Output","operationId":"get_output_outputs__output_id__get","parameters":[{"name":"output_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Output Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OutputResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/outputs/{output_id}/download":{"get":{"tags":["outputs"],"summary":"Download Output","description":"Download an output as the most natural file for its shape.\n\n  - Pure video (video_url, no images) → returns the MP4 directly.\n  - Single image (image_card with one static_url, no video) → PNG directly.\n  - Everything else → ZIP with images + video + caption.txt.\n\nThe MP4 case is the one Cal flagged 2026-05-25: previously the endpoint\nzipped only static_urls + caption.txt, so a reel download was a tiny zip\nwith a single text file — looked like \"the download is a text file.\"","operationId":"download_output_outputs__output_id__download_get","parameters":[{"name":"output_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Output Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/outputs/session/{session_id}":{"get":{"tags":["outputs"],"summary":"Get Session Outputs","operationId":"get_session_outputs_outputs_session__session_id__get","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/OutputResponse"},"title":"Response Get Session Outputs Outputs Session  Session Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/social/connections":{"get":{"tags":["social"],"summary":"List Connections","operationId":"list_connections_social_connections_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ConnectionStatus"},"title":"Response List Connections Social Connections Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/social/linkedin/connect":{"get":{"tags":["social"],"summary":"Linkedin Connect","operationId":"linkedin_connect_social_linkedin_connect_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/social/linkedin/callback":{"get":{"tags":["social"],"summary":"Linkedin Callback","operationId":"linkedin_callback_social_linkedin_callback_get","parameters":[{"name":"code","in":"query","required":true,"schema":{"type":"string","title":"Code"}},{"name":"state","in":"query","required":true,"schema":{"type":"string","title":"State"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/social/instagram/connect":{"get":{"tags":["social"],"summary":"Instagram Connect","operationId":"instagram_connect_social_instagram_connect_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/social/instagram/callback":{"get":{"tags":["social"],"summary":"Instagram Callback","operationId":"instagram_callback_social_instagram_callback_get","parameters":[{"name":"code","in":"query","required":true,"schema":{"type":"string","title":"Code"}},{"name":"state","in":"query","required":true,"schema":{"type":"string","title":"State"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/social/twitter/connect":{"get":{"tags":["social"],"summary":"Twitter Connect","operationId":"twitter_connect_social_twitter_connect_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/social/twitter/callback":{"get":{"tags":["social"],"summary":"Twitter Callback","operationId":"twitter_callback_social_twitter_callback_get","parameters":[{"name":"code","in":"query","required":true,"schema":{"type":"string","title":"Code"}},{"name":"state","in":"query","required":true,"schema":{"type":"string","title":"State"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/social/{platform}/disconnect":{"delete":{"tags":["social"],"summary":"Disconnect","operationId":"disconnect_social__platform__disconnect_delete","parameters":[{"name":"platform","in":"path","required":true,"schema":{"type":"string","title":"Platform"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/social/{session_id}/{platform}/publish":{"post":{"tags":["social"],"summary":"Publish","operationId":"publish_social__session_id___platform__publish_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}},{"name":"platform","in":"path","required":true,"schema":{"type":"string","title":"Platform"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublishResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/social/{session_id}/{platform}/schedule":{"post":{"tags":["social"],"summary":"Schedule Post","operationId":"schedule_post_social__session_id___platform__schedule_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}},{"name":"platform","in":"path","required":true,"schema":{"type":"string","title":"Platform"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduledPostOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/social/scheduled":{"get":{"tags":["social"],"summary":"List Scheduled","operationId":"list_scheduled_social_scheduled_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ScheduledPostOut"},"title":"Response List Scheduled Social Scheduled Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/social/scheduled/{scheduled_id}":{"delete":{"tags":["social"],"summary":"Cancel Scheduled","operationId":"cancel_scheduled_social_scheduled__scheduled_id__delete","parameters":[{"name":"scheduled_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Scheduled Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/modules":{"get":{"tags":["modules"],"summary":"Get Modules","description":"Single payload the /modules page reads: full catalog + which the user\nhas, + their plan so the UI can render the Studio bypass state.","operationId":"get_modules_modules_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModulesCatalogResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/modules/{slug}/activate":{"post":{"tags":["modules"],"summary":"Activate Module","description":"Unlock a module for the current user. Free grant today; Stripe checkout\nwill sit in front of this once billing is live (the webhook will call the\nsame `grant_module` underneath so the activation path is single-sourced).","operationId":"activate_module_modules__slug__activate_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModuleActionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/modules/{slug}/deactivate":{"post":{"tags":["modules"],"summary":"Deactivate Module","description":"Cancel the user's subscription to a module. Row stays around (status\nflipped to `canceled`) so re-activation later preserves the audit trail.\nStudio users can't deactivate per-module — the whole bundle is the SKU.","operationId":"deactivate_module_modules__slug__deactivate_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModuleActionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/billing/portal":{"post":{"tags":["billing"],"summary":"Create Billing Portal","description":"Open the Stripe Billing Portal so the user can manage cards,\nview invoices, cancel subscriptions, or resolve a payment failure.\n\n409 when:\n  - Stripe billing isn't enabled (dev mode w/o Stripe key)\n  - User has no stripe_customer_id yet (hasn't subscribed)","operationId":"create_billing_portal_billing_portal_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingPortalResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/billing/checkout":{"post":{"tags":["billing"],"summary":"Create Checkout","operationId":"create_checkout_billing_checkout_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/billing/checkout/topup":{"post":{"tags":["billing"],"summary":"Create Topup Checkout","description":"One-time credit-pack checkout. Pack is small / medium / large.","operationId":"create_topup_checkout_billing_checkout_topup_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TopupRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/billing/credits":{"get":{"tags":["billing"],"summary":"Get Credits","description":"Current credit state for /settings/usage — balance, bucket\nexpirations, recent transaction history.\n\nReservation + reservation_release rows are filtered out of the\nuser-facing transaction list. They're internal accounting (hold +\nrelease of unused portion during an in-flight run); the user only\ncares about real debits + grants + refunds. The full ledger is\nstill in the DB, accessible via logs + future admin view. Cal\n2026-05-29: *\"we dont even need to show the reservation at all.\nthats inside baseball as humans say.\"*","operationId":"get_credits_billing_credits_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/billing/webhook":{"post":{"tags":["billing"],"summary":"Stripe Webhook","description":"Stripe webhook handler. Verifies signature, parses event, delegates\nto stripe_billing.handle_event. Returns 200 on every accepted event\n(including no-ops) so Stripe doesn't retry. Returns 400 on signature\nfailure — Stripe surfaces that in the dashboard.","operationId":"stripe_webhook_billing_webhook_post","parameters":[{"name":"Stripe-Signature","in":"header","required":false,"schema":{"type":"string","default":"","title":"Stripe-Signature"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/mcp":{"post":{"tags":["mcp"],"summary":"Mcp Endpoint","description":"Single JSON-RPC 2.0 endpoint. Dispatches on `method`.","operationId":"mcp_endpoint_mcp_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/oauth/register":{"post":{"tags":["oauth"],"summary":"Register Client","description":"RFC 7591 Dynamic Client Registration. Open endpoint.","operationId":"register_client_oauth_register_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientRegistrationRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/oauth/authorize":{"get":{"tags":["oauth"],"summary":"Authorize","description":"OAuth 2.1 authorize endpoint. Validates the request, then\nredirects to the web-side consent page where the user is auth'd\nvia Supabase + sees the 'Authorize this app?' prompt.","operationId":"authorize_oauth_authorize_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/oauth/authorize/complete":{"post":{"tags":["oauth"],"summary":"Authorize Complete","description":"Internal endpoint — called by the web consent page after the\nuser's decision lands. Mints the auth code on approval, returns the\nredirect URL the web side sends the user to.\n\nAuth: requires a valid Supabase JWT in the Authorization header.\nThe JWT's `sub` claim becomes the authorized user — body cannot\noverride (confused-deputy guard).","operationId":"authorize_complete_oauth_authorize_complete_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthorizeCompleteRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/oauth/token":{"post":{"tags":["oauth"],"summary":"Token","description":"Exchange an auth code + PKCE code_verifier for an access token.\nThe minted token is a niche_sk_<...> opaque bearer stored in api_keys\nwith oauth_client_id populated.","operationId":"token_oauth_token_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/.well-known/agent-skills/index.json":{"get":{"tags":["well-known"],"summary":"Agent Skills Manifest","description":"Live agent-skills manifest. Generated from `mcp_tools.TOOLS` on\nevery request so the manifest and `tools/list` can never drift.\n\nShape (loose convention — there isn't a formal standard yet; we use\nfields common to HeyNews, Glama, mcpservers.org listings):\n\n  {\n    \"name\": \"Niche\",\n    \"description\": \"...\",\n    \"category\": \"...\",\n    \"homepage\": \"...\",\n    \"transports\": [\"streamable-http\"],\n    \"endpoint\": \"https://api.nicheangle.com/mcp\",\n    \"auth_methods\": [...],\n    \"skill_count\": 22,\n    \"skills\": [{name, description, tags}]\n  }","operationId":"agent_skills_manifest__well_known_agent_skills_index_json_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/.well-known/api-catalog":{"get":{"tags":["well-known"],"summary":"Api Catalog","description":"RFC 9727 api-catalog. Linkset JSON pointing at every machine-\nreadable surface we expose: OpenAPI doc, MCP endpoint, agent-skills\nmanifest, docs site. The canonical entry point for API discovery\ncrawlers and tooling that doesn't know about Niche specifically.","operationId":"api_catalog__well_known_api_catalog_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/.well-known/oauth-authorization-server":{"get":{"tags":["well-known"],"summary":"Oauth Authorization Server","description":"RFC 8414 — authorization server metadata. Claude Desktop and\nChatGPT app directory clients read this when an MCP server requires\nOAuth, to find the authorize / token / register endpoints + the\nsupported flows.","operationId":"oauth_authorization_server__well_known_oauth_authorization_server_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/.well-known/oauth-protected-resource":{"get":{"tags":["well-known"],"summary":"Oauth Protected Resource","description":"RFC 9728 — protected resource metadata. Tells the client which\nauthorization servers can issue tokens for this MCP endpoint.","operationId":"oauth_protected_resource__well_known_oauth_protected_resource_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/health":{"get":{"summary":"Health","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/.well-known/mcp.json":{"get":{"summary":"Well Known Mcp","description":"RFC-style discovery doc for the MCP server. Mirrors the OAuth\ndiscovery pattern — agents probe `/.well-known/mcp.json` to find the\nserver URL + auth scheme without needing a pre-known path.\n\nTwo access paths:\n  1. Web tier (nicheangle.com/.well-known/mcp.json) — handled by the\n     Next.js `/api/mcp-discovery` route at web/src/app/api/...\n     Returns `{web_origin}/api/mcp` (Vercel rewrites to Fly internally).\n  2. Direct API (niche-api.fly.dev/.well-known/mcp.json) — this\n     handler. Returns the bare API endpoint `{api_origin}/mcp` (no\n     `/api/` prefix; that's a web-tier rewrite path). The\n     human-facing surfaces (token issue, docs) point at the\n     configured FRONTEND_URL so agents that arrived via the API host\n     still get correct links into the user dashboard.","operationId":"well_known_mcp__well_known_mcp_json_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"AddOutputRequest":{"properties":{"cell":{"type":"string","title":"Cell"}},"type":"object","required":["cell"],"title":"AddOutputRequest"},"AngleListResponse":{"properties":{"angles":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Angles"}},"type":"object","required":["angles"],"title":"AngleListResponse"},"AngleRegenerateRequest":{"properties":{"lens":{"type":"string","title":"Lens"},"regen_count":{"type":"integer","title":"Regen Count","default":0}},"type":"object","required":["lens"],"title":"AngleRegenerateRequest"},"AngleSelectionRequest":{"properties":{"angle_id":{"type":"string","title":"Angle Id"}},"type":"object","required":["angle_id"],"title":"AngleSelectionRequest"},"ApiKeyOut":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"prefix":{"type":"string","title":"Prefix"},"created_at":{"type":"string","title":"Created At"},"last_used_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Used At"},"disabled_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Disabled At"},"burn_24h_credits":{"type":"integer","title":"Burn 24H Credits","default":0}},"type":"object","required":["id","name","prefix","created_at","last_used_at","disabled_at"],"title":"ApiKeyOut"},"AuthorizeCompleteRequest":{"properties":{"client_id":{"type":"string","title":"Client Id"},"redirect_uri":{"type":"string","title":"Redirect Uri"},"scope":{"type":"string","title":"Scope","default":"niche:mcp"},"state":{"type":"string","title":"State","default":""},"code_challenge":{"type":"string","title":"Code Challenge"},"code_challenge_method":{"type":"string","title":"Code Challenge Method","default":"S256"},"approved":{"type":"boolean","title":"Approved"}},"type":"object","required":["client_id","redirect_uri","code_challenge","approved"],"title":"AuthorizeCompleteRequest","description":"Payload posted by the web consent page after the user clicks\nAuthorize / Deny. The authenticated Supabase user (resolved\nserver-side from the Authorization: Bearer header) is the one we\nissue the code for — the body's user_id field is IGNORED if it\ndisagrees with the JWT, to prevent confused-deputy attacks."},"BillingPortalResponse":{"properties":{"portal_url":{"type":"string","title":"Portal Url"}},"type":"object","required":["portal_url"],"title":"BillingPortalResponse"},"Body_ingest_brand_kit_brand_kit_ingest_post":{"properties":{"files":{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array","title":"Files"},"text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Text"}},"type":"object","title":"Body_ingest_brand_kit_brand_kit_ingest_post"},"Body_upload_endcard_image_brand_kit_upload_endcard_image_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_endcard_image_brand_kit_upload_endcard_image_post"},"Body_upload_endcard_video_brand_kit_upload_endcard_video_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_endcard_video_brand_kit_upload_endcard_video_post"},"Body_upload_logo_brand_kit_upload_logo_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_logo_brand_kit_upload_logo_post"},"Body_upload_product_image_brand_kit_upload_product_image_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_product_image_brand_kit_upload_product_image_post"},"BrandKitCreateRequest":{"properties":{"brand_id":{"type":"string","maxLength":64,"minLength":1,"pattern":"^[a-z0-9][a-z0-9_-]*$","title":"Brand Id"},"name":{"type":"string","maxLength":120,"minLength":1,"title":"Name"}},"type":"object","required":["brand_id","name"],"title":"BrandKitCreateRequest"},"BrandKitListEntry":{"properties":{"brand_id":{"type":"string","title":"Brand Id"},"name":{"type":"string","title":"Name"},"logo_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Logo Url"},"accent":{"type":"string","title":"Accent"},"is_default":{"type":"boolean","title":"Is Default"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["brand_id","name","accent","is_default","updated_at"],"title":"BrandKitListEntry","description":"Lightweight entry for the brand-roster surface — just the slug,\nname, and a couple of identifying glances so the multi-brand\nswitcher can render without fetching the full BrandKit body for\neach row."},"BrandKitListResponse":{"properties":{"default_brand_id":{"type":"string","title":"Default Brand Id"},"cap":{"type":"integer","title":"Cap"},"can_create_more":{"type":"boolean","title":"Can Create More"},"plan":{"type":"string","title":"Plan"},"brands":{"items":{"$ref":"#/components/schemas/BrandKitListEntry"},"type":"array","title":"Brands"}},"type":"object","required":["default_brand_id","cap","can_create_more","plan","brands"],"title":"BrandKitListResponse"},"BrandKitResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"brand_id":{"type":"string","title":"Brand Id","default":"default"},"name":{"type":"string","title":"Name","default":"Default brand"},"primary_bg":{"type":"string","title":"Primary Bg"},"secondary_bg":{"type":"string","title":"Secondary Bg"},"text_primary":{"type":"string","title":"Text Primary"},"text_secondary":{"type":"string","title":"Text Secondary"},"accent":{"type":"string","title":"Accent"},"headline_font_family":{"type":"string","title":"Headline Font Family"},"body_font_family":{"type":"string","title":"Body Font Family"},"font_size_scale":{"type":"string","title":"Font Size Scale"},"logo_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Logo Url"},"wordmark_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Wordmark Url"},"headshot_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Headshot Url"},"product_images":{"items":{},"type":"array","title":"Product Images"},"layout_style":{"type":"string","title":"Layout Style"},"corner_radius":{"type":"integer","title":"Corner Radius"},"tagline":{"type":"string","title":"Tagline"},"boilerplate":{"type":"string","title":"Boilerplate"},"voice_notes":{"type":"string","title":"Voice Notes"},"external_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"External Url"},"source_assets":{"items":{},"type":"array","title":"Source Assets"},"extraction_status":{"type":"string","title":"Extraction Status"},"forbidden_phrases":{"items":{"type":"string"},"type":"array","title":"Forbidden Phrases"},"signature_phrases":{"items":{"type":"string"},"type":"array","title":"Signature Phrases"},"endcard_mark_preference":{"type":"string","title":"Endcard Mark Preference","default":"auto"},"endcard_outro_text":{"type":"string","title":"Endcard Outro Text","default":""},"endcard_template":{"type":"string","title":"Endcard Template","default":"classic"},"endcard_image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Endcard Image Url"},"endcard_video_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Endcard Video Url"},"video_voice_preference":{"type":"string","title":"Video Voice Preference","default":"auto"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","primary_bg","secondary_bg","text_primary","text_secondary","accent","headline_font_family","body_font_family","font_size_scale","logo_url","wordmark_url","headshot_url","product_images","layout_style","corner_radius","tagline","boilerplate","voice_notes","external_url","extraction_status","updated_at"],"title":"BrandKitResponse"},"BrandKitUpdate":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"primary_bg":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Primary Bg"},"secondary_bg":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Secondary Bg"},"text_primary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Text Primary"},"text_secondary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Text Secondary"},"accent":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Accent"},"headline_font_family":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Headline Font Family"},"headline_font_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Headline Font Url"},"body_font_family":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body Font Family"},"body_font_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body Font Url"},"font_size_scale":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Font Size Scale"},"layout_style":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Layout Style"},"corner_radius":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Corner Radius"},"logo_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Logo Url"},"wordmark_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Wordmark Url"},"headshot_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Headshot Url"},"tagline":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tagline"},"boilerplate":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Boilerplate"},"voice_notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Voice Notes"},"external_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"External Url"},"forbidden_phrases":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Forbidden Phrases"},"signature_phrases":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Signature Phrases"},"endcard_mark_preference":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Endcard Mark Preference"},"endcard_outro_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Endcard Outro Text"},"endcard_template":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Endcard Template"},"endcard_image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Endcard Image Url"},"endcard_video_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Endcard Video Url"},"video_voice_preference":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Video Voice Preference"}},"type":"object","title":"BrandKitUpdate"},"CadencePrimitives":{"properties":{"avg_sentence_words":{"type":"integer","title":"Avg Sentence Words"},"fragment_frequency_pct":{"type":"integer","title":"Fragment Frequency Pct"},"single_para_ratio_pct":{"type":"integer","title":"Single Para Ratio Pct"}},"type":"object","required":["avg_sentence_words","fragment_frequency_pct","single_para_ratio_pct"],"title":"CadencePrimitives"},"CheckoutRequest":{"properties":{"kind":{"type":"string","title":"Kind"},"target":{"type":"string","title":"Target"}},"type":"object","required":["kind","target"],"title":"CheckoutRequest"},"CheckoutResponse":{"properties":{"checkout_url":{"type":"string","title":"Checkout Url"}},"type":"object","required":["checkout_url"],"title":"CheckoutResponse"},"ClientRegistrationRequest":{"properties":{"client_name":{"type":"string","maxLength":200,"minLength":1,"title":"Client Name"},"redirect_uris":{"items":{"type":"string"},"type":"array","title":"Redirect Uris"},"grant_types":{"items":{"type":"string"},"type":"array","title":"Grant Types"},"response_types":{"items":{"type":"string"},"type":"array","title":"Response Types"},"token_endpoint_auth_method":{"type":"string","title":"Token Endpoint Auth Method","default":"client_secret_basic"},"scope":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scope"},"client_uri":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Uri"},"logo_uri":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Logo Uri"},"tos_uri":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tos Uri"},"policy_uri":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Policy Uri"},"software_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Software Id"},"software_version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Software Version"}},"type":"object","required":["client_name"],"title":"ClientRegistrationRequest","description":"Subset of RFC 7591 client metadata we accept. Unknown fields are\nignored (per the spec)."},"ConnectionStatus":{"properties":{"platform":{"type":"string","title":"Platform"},"connected":{"type":"boolean","title":"Connected"},"username":{"type":"string","title":"Username","default":""},"expires_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Expires At"}},"type":"object","required":["platform","connected"],"title":"ConnectionStatus"},"CreateKeyRequest":{"properties":{"name":{"type":"string","title":"Name","default":""}},"type":"object","title":"CreateKeyRequest"},"CreateKeyResponse":{"properties":{"key":{"$ref":"#/components/schemas/ApiKeyOut"},"plaintext":{"type":"string","title":"Plaintext"}},"type":"object","required":["key","plaintext"],"title":"CreateKeyResponse"},"CreditBreakdownItem":{"properties":{"action":{"type":"string","title":"Action"},"credits":{"type":"integer","title":"Credits"}},"type":"object","required":["action","credits"],"title":"CreditBreakdownItem"},"CreditBreakdownResponse":{"properties":{"session_id":{"type":"string","format":"uuid","title":"Session Id"},"credits_spent":{"type":"integer","title":"Credits Spent"},"items":{"items":{"$ref":"#/components/schemas/CreditBreakdownItem"},"type":"array","title":"Items"},"credits_reserved":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Credits Reserved"}},"type":"object","required":["session_id","credits_spent","items"],"title":"CreditBreakdownResponse"},"CreditsResponse":{"properties":{"balance":{"type":"integer","title":"Balance"},"ledger_balance":{"type":"integer","title":"Ledger Balance","default":0},"trial_credits_remaining":{"type":"integer","title":"Trial Credits Remaining","default":0},"buckets":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Buckets"},"recent_transactions":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Recent Transactions"}},"type":"object","required":["balance","buckets","recent_transactions"],"title":"CreditsResponse","description":"Current credit state for /billing/credits."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HookVariantsRequest":{"properties":{"platform":{"type":"string","title":"Platform"},"current_caption":{"type":"string","maxLength":4000,"minLength":1,"title":"Current Caption"},"count":{"type":"integer","title":"Count","default":3}},"type":"object","required":["platform","current_caption"],"title":"HookVariantsRequest"},"HookVariantsResponse":{"properties":{"variants":{"items":{"type":"string"},"type":"array","title":"Variants"}},"type":"object","required":["variants"],"title":"HookVariantsResponse"},"ImageCardRenderRequest":{"properties":{"cell":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cell"}},"type":"object","title":"ImageCardRenderRequest"},"IngestReport":{"properties":{"kit":{"$ref":"#/components/schemas/BrandKitResponse"},"detected":{"items":{"type":"string"},"type":"array","title":"Detected"},"skipped":{"items":{"type":"string"},"type":"array","title":"Skipped"},"errors":{"items":{"type":"string"},"type":"array","title":"Errors"},"duration_sec":{"type":"number","title":"Duration Sec","default":0.0}},"type":"object","required":["kit"],"title":"IngestReport","description":"Returned alongside the BrandKit so the UI can show what the engine\ndetected, what it skipped, and what was unchanged."},"InterviewRequest":{"properties":{"archetype":{"type":"string","title":"Archetype"},"answers":{"additionalProperties":{"type":"string"},"type":"object","maxProperties":30,"title":"Answers"},"profile_urls":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":5},{"type":"null"}],"title":"Profile Urls"}},"type":"object","required":["archetype","answers"],"title":"InterviewRequest"},"JsonRpcRequest":{"properties":{"jsonrpc":{"type":"string","title":"Jsonrpc","default":"2.0"},"id":{"anyOf":[{"type":"integer"},{"type":"string"},{"type":"null"}],"title":"Id"},"method":{"type":"string","title":"Method"},"params":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Params"}},"type":"object","required":["method"],"title":"JsonRpcRequest"},"ModuleActionResponse":{"properties":{"slug":{"type":"string","title":"Slug"},"status":{"type":"string","title":"Status"}},"type":"object","required":["slug","status"],"title":"ModuleActionResponse"},"ModuleEntry":{"properties":{"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"monthly_price_usd":{"type":"integer","title":"Monthly Price Usd"},"state":{"type":"string","title":"State"},"entitled":{"type":"boolean","title":"Entitled"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"checkout_available":{"type":"boolean","title":"Checkout Available"}},"type":"object","required":["slug","name","monthly_price_usd","state","entitled","status","checkout_available"],"title":"ModuleEntry"},"ModulesCatalogResponse":{"properties":{"plan":{"type":"string","title":"Plan"},"studio_includes_all":{"type":"boolean","title":"Studio Includes All"},"stripe_billing_enabled":{"type":"boolean","title":"Stripe Billing Enabled"},"modules":{"items":{"$ref":"#/components/schemas/ModuleEntry"},"type":"array","title":"Modules"}},"type":"object","required":["plan","studio_includes_all","stripe_billing_enabled","modules"],"title":"ModulesCatalogResponse"},"NicheMergeRequest":{"properties":{"source":{"type":"string","title":"Source"},"target":{"type":"string","title":"Target"}},"type":"object","required":["source","target"],"title":"NicheMergeRequest"},"NicheRenameRequest":{"properties":{"old_niche":{"type":"string","title":"Old Niche"},"new_niche":{"type":"string","title":"New Niche"}},"type":"object","required":["old_niche","new_niche"],"title":"NicheRenameRequest"},"OutputResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"session_id":{"type":"string","format":"uuid","title":"Session Id"},"platform":{"type":"string","title":"Platform"},"script":{"additionalProperties":true,"type":"object","title":"Script"},"caption":{"type":"string","title":"Caption"},"hashtags":{"items":{"type":"string"},"type":"array","title":"Hashtags"},"static_urls":{"items":{"type":"string"},"type":"array","title":"Static Urls"},"video_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Video Url"},"bundle_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bundle Url"},"published_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Published At"},"published_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Published Url"},"published_platform_post_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Published Platform Post Id"},"scheduled_for":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Scheduled For"},"verifier_blocked_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Verifier Blocked Reason"},"verifier_blocked_claim":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Verifier Blocked Claim"},"source_faithfulness_score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Source Faithfulness Score"},"source_ungrounded_claims":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Source Ungrounded Claims"},"source_diversity_passed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Source Diversity Passed"},"source_recency_passed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Source Recency Passed"},"source_distinct_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Source Distinct Count"},"source_freshest_age_days":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Source Freshest Age Days"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","session_id","platform","script","caption","hashtags","static_urls","video_url","bundle_url","created_at"],"title":"OutputResponse"},"ProvenanceResponse":{"properties":{"niche_input":{"type":"string","title":"Niche Input"},"story_title":{"type":"string","title":"Story Title"},"story_summary":{"type":"string","title":"Story Summary"},"angle_frame":{"type":"string","title":"Angle Frame"},"angle_hook":{"type":"string","title":"Angle Hook"},"angle_tension":{"type":"string","title":"Angle Tension"},"angle_cta_direction":{"type":"string","title":"Angle Cta Direction"},"sources":{"items":{"$ref":"#/components/schemas/ProvenanceSource"},"type":"array","title":"Sources"}},"type":"object","required":["niche_input","story_title","story_summary","angle_frame","angle_hook","angle_tension","angle_cta_direction","sources"],"title":"ProvenanceResponse","description":"The 'How this was made' card surfaces the chain: niche → story → angle → sources.\nRenders in CP3 review so users can see (and quote) the reasoning behind their post."},"ProvenanceSource":{"properties":{"title":{"type":"string","title":"Title"},"url":{"type":"string","title":"Url"},"source":{"type":"string","title":"Source"},"publication":{"type":"string","title":"Publication","default":""},"published_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Published At"}},"type":"object","required":["title","url","source"],"title":"ProvenanceSource"},"PublishResult":{"properties":{"ok":{"type":"boolean","title":"Ok"},"post_url":{"type":"string","title":"Post Url","default":""},"platform_post_id":{"type":"string","title":"Platform Post Id","default":""},"error_kind":{"type":"string","title":"Error Kind","default":""},"error_message":{"type":"string","title":"Error Message","default":""},"retry_after_sec":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Retry After Sec"}},"type":"object","required":["ok"],"title":"PublishResult"},"PunctuationHabits":{"properties":{"em_dashes":{"type":"string","title":"Em Dashes"},"semicolons":{"type":"string","title":"Semicolons"},"parens":{"type":"string","title":"Parens"}},"type":"object","required":["em_dashes","semicolons","parens"],"title":"PunctuationHabits"},"ReviewSubmitRequest":{"properties":{"edits":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Edits"}},"type":"object","required":["edits"],"title":"ReviewSubmitRequest"},"ScheduleRequest":{"properties":{"scheduled_for":{"type":"string","format":"date-time","title":"Scheduled For"}},"type":"object","required":["scheduled_for"],"title":"ScheduleRequest"},"ScheduledPostOut":{"properties":{"id":{"type":"string","title":"Id"},"session_id":{"type":"string","title":"Session Id"},"platform":{"type":"string","title":"Platform"},"scheduled_for":{"type":"string","title":"Scheduled For"},"status":{"type":"string","title":"Status"},"post_url":{"type":"string","title":"Post Url","default":""},"error":{"type":"string","title":"Error","default":""},"created_at":{"type":"string","title":"Created At"},"sent_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sent At"}},"type":"object","required":["id","session_id","platform","scheduled_for","status","created_at"],"title":"ScheduledPostOut"},"SessionResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"status":{"$ref":"#/components/schemas/SessionStatus"},"niche_input":{"type":"string","title":"Niche Input"},"target_platforms":{"items":{"type":"string"},"type":"array","title":"Target Platforms"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"niche_profile":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Niche Profile"},"selected_story":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Selected Story"},"selected_story_signals":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Selected Story Signals","default":[]},"selected_story_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Selected Story Id"},"selected_angle_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Selected Angle Id"},"angles":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Angles","default":[]},"ranked_stories":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Ranked Stories","default":[]},"credits_spent":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Credits Spent"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"}},"type":"object","required":["id","status","niche_input","target_platforms","created_at","updated_at"],"title":"SessionResponse"},"SessionStatus":{"type":"string","enum":["initializing","expanding_niche","planning_search","discovering_signals","clustering","ranking","cp1_awaiting_story","extracting_signal","generating_angles","cp2_awaiting_angle","applying_voice","generating_content","rendering_static","rendering_video","cp3_awaiting_review","complete","failed"],"title":"SessionStatus"},"ShopifyImportRequest":{"properties":{"shop_url":{"type":"string","title":"Shop Url"}},"type":"object","required":["shop_url"],"title":"ShopifyImportRequest"},"StartSessionRequest":{"properties":{"niche_input":{"type":"string","maxLength":500,"minLength":2,"title":"Niche Input"},"target_outputs":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":50},{"type":"null"}],"title":"Target Outputs"},"target_platforms":{"items":{"type":"string"},"type":"array","maxItems":50,"title":"Target Platforms"},"voice_context":{"anyOf":[{"$ref":"#/components/schemas/VoiceContext"},{"type":"null"}]},"brand_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Brand Id"}},"type":"object","required":["niche_input"],"title":"StartSessionRequest"},"StoryRefineRequest":{"properties":{"instruction":{"type":"string","title":"Instruction"},"dismissed_story_ids":{"items":{"type":"string"},"type":"array","title":"Dismissed Story Ids","default":[]}},"type":"object","required":["instruction"],"title":"StoryRefineRequest"},"StorySelectionRequest":{"properties":{"story_id":{"type":"string","title":"Story Id"}},"type":"object","required":["story_id"],"title":"StorySelectionRequest"},"StoryWorkspaceResponse":{"properties":{"stories":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Stories"},"visible_limit":{"type":"integer","title":"Visible Limit","default":5},"total_candidates":{"type":"integer","title":"Total Candidates"},"has_more_candidates":{"type":"boolean","title":"Has More Candidates"}},"type":"object","required":["stories","total_candidates","has_more_candidates"],"title":"StoryWorkspaceResponse"},"TopupRequest":{"properties":{"pack":{"type":"string","title":"Pack"}},"type":"object","required":["pack"],"title":"TopupRequest","description":"Top-up checkout — one-time payment for a credit pack.\npack is one of \"small\" / \"medium\" / \"large\" per docs/PRICING.md."},"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"},"VideoRenderRequest":{"properties":{"captions_enabled":{"type":"boolean","title":"Captions Enabled","default":true},"music_enabled":{"type":"boolean","title":"Music Enabled","default":false},"tone":{"type":"string","title":"Tone","default":"default"},"cell":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cell"}},"type":"object","title":"VideoRenderRequest"},"VoiceContext":{"properties":{"tone_words":{"type":"string","title":"Tone Words","default":""},"audience_context":{"type":"string","title":"Audience Context","default":""},"avoid":{"type":"string","title":"Avoid","default":""}},"type":"object","title":"VoiceContext"},"VoiceExtractRequest":{"properties":{"posts":{"items":{"type":"string"},"type":"array","maxItems":10,"minItems":1,"title":"Posts"},"audience":{"anyOf":[{"type":"string","maxLength":400},{"type":"null"}],"title":"Audience"},"avoid":{"anyOf":[{"type":"string","maxLength":400},{"type":"null"}],"title":"Avoid"}},"type":"object","required":["posts"],"title":"VoiceExtractRequest"},"VoiceExtractResponse":{"properties":{"primitives":{"$ref":"#/components/schemas/VoicePrimitives"},"audience":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Audience"},"avoid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Avoid"}},"type":"object","required":["primitives"],"title":"VoiceExtractResponse"},"VoicePrimitives":{"properties":{"cadence":{"$ref":"#/components/schemas/CadencePrimitives"},"openers":{"items":{"type":"string"},"type":"array","title":"Openers"},"connectors":{"items":{"type":"string"},"type":"array","title":"Connectors"},"taboo_phrases":{"items":{"type":"string"},"type":"array","title":"Taboo Phrases"},"signature_moves":{"items":{"type":"string"},"type":"array","title":"Signature Moves"},"topic_gravity":{"items":{"type":"string"},"type":"array","title":"Topic Gravity"},"casing":{"type":"string","title":"Casing"},"punctuation_habits":{"$ref":"#/components/schemas/PunctuationHabits"}},"type":"object","required":["cadence","openers","connectors","taboo_phrases","signature_moves","topic_gravity","casing","punctuation_habits"],"title":"VoicePrimitives"},"VoiceProfileResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"archetype":{"type":"string","title":"Archetype"},"tone_words":{"items":{"type":"string"},"type":"array","title":"Tone Words"},"stance":{"type":"string","title":"Stance"},"audience_level":{"type":"string","title":"Audience Level"},"hook_style":{"type":"string","title":"Hook Style"},"avoid":{"items":{"type":"string"},"type":"array","title":"Avoid"},"profile_context":{"type":"string","title":"Profile Context"}},"type":"object","required":["id","archetype","tone_words","stance","audience_level","hook_style","avoid","profile_context"],"title":"VoiceProfileResponse"}}}}