{"components":{"schemas":{"AccessTokenRequest":{"properties":{"access_token":{"description":"Cognito access token","minLength":1,"title":"Access Token","type":"string"}},"required":["access_token"],"title":"AccessTokenRequest","type":"object"},"AccountAddedResponse":{"properties":{"account_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Account Id"},"ok":{"default":true,"title":"Ok","type":"boolean"},"username":{"default":"","title":"Username","type":"string"}},"title":"AccountAddedResponse","type":"object"},"AccountAnalytics":{"properties":{"account":{"additionalProperties":true,"title":"Account","type":"object"},"follower_history":{"items":{"additionalProperties":true,"type":"object"},"title":"Follower History","type":"array"},"reels":{"items":{"additionalProperties":true,"type":"object"},"title":"Reels","type":"array"},"summary":{"additionalProperties":true,"title":"Summary","type":"object"},"tracking":{"additionalProperties":true,"title":"Tracking","type":"object"}},"required":["account","summary","reels","follower_history"],"title":"AccountAnalytics","type":"object"},"AccountCategoriesOkResponse":{"additionalProperties":true,"properties":{"ok":{"default":true,"title":"Ok","type":"boolean"}},"title":"AccountCategoriesOkResponse","type":"object"},"AccountCategoryOkResponse":{"properties":{"category_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Category Id"},"ok":{"default":true,"title":"Ok","type":"boolean"}},"title":"AccountCategoryOkResponse","type":"object"},"AccountFacet":{"properties":{"id":{"title":"Id","type":"integer"},"username":{"title":"Username","type":"string"}},"required":["id","username"],"title":"AccountFacet","type":"object"},"AccountIdentitiesResponse":{"properties":{"email":{"title":"Email","type":"string"},"email_verified":{"title":"Email Verified","type":"boolean"},"has_password":{"title":"Has Password","type":"boolean"},"identities":{"items":{"$ref":"#/components/schemas/IdentitySummaryModel"},"title":"Identities","type":"array"}},"required":["email","email_verified","has_password","identities"],"title":"AccountIdentitiesResponse","type":"object"},"AccountScanHistoryResponse":{"properties":{"account_status":{"default":"active","title":"Account Status","type":"string"},"current_followers":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Current Followers"},"history":{"items":{"$ref":"#/components/schemas/ScanHistoryEntry"},"title":"History","type":"array"},"username":{"title":"Username","type":"string"}},"required":["username"],"title":"AccountScanHistoryResponse","type":"object"},"AccountTagsOkResponse":{"properties":{"ok":{"default":true,"title":"Ok","type":"boolean"},"tags":{"items":{"type":"string"},"title":"Tags","type":"array"}},"title":"AccountTagsOkResponse","type":"object"},"AccountUsernameOkResponse":{"properties":{"ok":{"default":true,"title":"Ok","type":"boolean"},"username":{"default":"","title":"Username","type":"string"}},"title":"AccountUsernameOkResponse","type":"object"},"AcquisitionPoint":{"properties":{"bucket":{"format":"date","title":"Bucket","type":"string"},"paid":{"title":"Paid","type":"integer"},"signups":{"title":"Signups","type":"integer"},"trials":{"title":"Trials","type":"integer"},"visits":{"title":"Visits","type":"integer"}},"required":["bucket","visits","signups","trials","paid"],"title":"AcquisitionPoint","type":"object"},"AcquisitionResponse":{"properties":{"compare":{"enum":["previous","yoy","none"],"title":"Compare","type":"string"},"compare_from":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"title":"Compare From"},"compare_to":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"title":"Compare To"},"currency":{"const":"USD","default":"USD","title":"Currency","type":"string"},"env":{"enum":["production","staging","local","test"],"title":"Env","type":"string"},"estimated_before":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"title":"Estimated Before"},"filters":{"items":{"$ref":"#/components/schemas/FilterEcho"},"title":"Filters","type":"array"},"freshness":{"$ref":"#/components/schemas/FreshnessSummary"},"from":{"format":"date","title":"From","type":"string"},"funnel":{"items":{"$ref":"#/components/schemas/FunnelStep"},"title":"Funnel","type":"array"},"granularity":{"enum":["day","week","month"],"title":"Granularity","type":"string"},"meta":{"$ref":"#/components/schemas/ResponseMeta"},"notes":{"items":{"type":"string"},"title":"Notes","type":"array"},"rows":{"items":{"$ref":"#/components/schemas/AcquisitionRow"},"title":"Rows","type":"array"},"series":{"items":{"$ref":"#/components/schemas/AcquisitionPoint"},"title":"Series","type":"array"},"to":{"format":"date","title":"To","type":"string"},"total_rows":{"title":"Total Rows","type":"integer"}},"required":["env","from","to","granularity","compare","compare_from","compare_to","freshness","meta","funnel","rows","total_rows","series"],"title":"AcquisitionResponse","type":"object"},"AcquisitionRow":{"properties":{"campaign":{"title":"Campaign","type":"string"},"medium":{"title":"Medium","type":"string"},"paid":{"title":"Paid","type":"integer"},"signup_rate_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Signup Rate Pct"},"signups":{"title":"Signups","type":"integer"},"source":{"title":"Source","type":"string"},"trials":{"title":"Trials","type":"integer"},"visits":{"title":"Visits","type":"integer"}},"required":["source","medium","campaign","visits","signups","trials","paid","signup_rate_pct"],"title":"AcquisitionRow","type":"object"},"ActivityItem":{"description":"One line of the activity feed, newest first.\n\n`label` is server-rendered so the SPA never has to know how to pluralize a\nclick bucket. `amount_cents` is null for the events that carry no money,\n`masked_email` for the ones that belong to no single referred user (a\npayout covers many of them).","properties":{"amount_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Amount Cents"},"at":{"format":"date-time","title":"At","type":"string"},"kind":{"enum":["clicks","referral_attributed","first_payment","commission_available","payout_paid"],"title":"Kind","type":"string"},"label":{"title":"Label","type":"string"},"masked_email":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Masked Email"}},"required":["at","kind","label"],"title":"ActivityItem","type":"object"},"ActivityItemResponse":{"properties":{"actor_id":{"title":"Actor Id","type":"integer"},"id":{"title":"Id","type":"integer"},"kind":{"title":"Kind","type":"string"},"object_id":{"title":"Object Id","type":"integer"},"object_kind":{"title":"Object Kind","type":"string"},"object_name":{"title":"Object Name","type":"string"},"preview_thumb":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Preview Thumb"},"ts":{"format":"date-time","title":"Ts","type":"string"}},"required":["id","kind","actor_id","object_kind","object_id","object_name","ts"],"title":"ActivityItemResponse","type":"object"},"ActivityListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ActivityItemResponse"},"title":"Items","type":"array"}},"title":"ActivityListResponse","type":"object"},"AddAccountRequest":{"properties":{"category_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Category Id"},"username":{"default":"","title":"Username","type":"string"}},"title":"AddAccountRequest","type":"object"},"AddSubtitlesRequest":{"properties":{"style":{"default":"viral_yellow","title":"Style","type":"string"}},"title":"AddSubtitlesRequest","type":"object"},"AddSubtitlesResponse":{"properties":{"message":{"title":"Message","type":"string"},"success":{"title":"Success","type":"boolean"}},"required":["success","message"],"title":"AddSubtitlesResponse","type":"object"},"AdminAffiliateDetailResponse":{"description":"The drawer: the row, the balances, the referred users, the payouts.","properties":{"affiliate":{"$ref":"#/components/schemas/AdminAffiliateItem"},"balances":{"$ref":"#/components/schemas/BalancesView"},"payouts":{"items":{"$ref":"#/components/schemas/PayoutItem"},"title":"Payouts","type":"array"},"referrals":{"items":{"$ref":"#/components/schemas/ReferralItem"},"title":"Referrals","type":"array"}},"required":["affiliate","balances"],"title":"AdminAffiliateDetailResponse","type":"object"},"AdminAffiliateItem":{"description":"One affiliate as the admin queue sees it.\n\nWider than the affiliate's own `AffiliateView`: it carries `user_id` and\n`decided_by_user_id` so the queue can link to the account and show who\ndecided. `payout_details` is masked here exactly as it is everywhere else.","properties":{"applied_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Applied At"},"channels":{"items":{"type":"string"},"title":"Channels","type":"array"},"code":{"title":"Code","type":"string"},"code_renamed":{"title":"Code Renamed","type":"boolean"},"commission_rate_bps":{"title":"Commission Rate Bps","type":"integer"},"decided_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Decided At"},"decided_by_user_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Decided By User Id"},"decline_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Decline Reason"},"email":{"title":"Email","type":"string"},"full_name":{"title":"Full Name","type":"string"},"id":{"title":"Id","type":"integer"},"payout_details":{"additionalProperties":{"type":"string"},"title":"Payout Details","type":"object"},"payout_method":{"title":"Payout Method","type":"string"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Phone"},"status":{"title":"Status","type":"string"},"terms_accepted_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Terms Accepted At"},"terms_version":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Terms Version"},"user_id":{"title":"User Id","type":"integer"}},"required":["id","user_id","code","code_renamed","status","full_name","email","payout_method","commission_rate_bps"],"title":"AdminAffiliateItem","type":"object"},"AdminAffiliatesResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/AdminAffiliateItem"},"title":"Items","type":"array"},"next_cursor":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Next Cursor"}},"title":"AdminAffiliatesResponse","type":"object"},"AdminAssetItem":{"description":"An asset as the admin editor sees it, `is_active` included.","properties":{"description":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Description"},"id":{"title":"Id","type":"integer"},"is_active":{"title":"Is Active","type":"boolean"},"kind":{"title":"Kind","type":"string"},"sort_order":{"title":"Sort Order","type":"integer"},"title":{"title":"Title","type":"string"},"url":{"title":"Url","type":"string"}},"required":["id","title","kind","url","sort_order","is_active"],"title":"AdminAssetItem","type":"object"},"AdminAssetRequest":{"description":"A marketing asset the admin creates or edits.","properties":{"description":{"anyOf":[{"maxLength":500,"type":"string"},{"type":"null"}],"default":null,"title":"Description"},"is_active":{"default":true,"title":"Is Active","type":"boolean"},"kind":{"maxLength":32,"minLength":1,"title":"Kind","type":"string"},"sort_order":{"default":0,"maximum":9999,"minimum":0.0,"title":"Sort Order","type":"integer"},"title":{"maxLength":120,"minLength":1,"title":"Title","type":"string"},"url":{"maxLength":500,"minLength":1,"title":"Url","type":"string"}},"required":["title","kind","url"],"title":"AdminAssetRequest","type":"object"},"AdminAssetsResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/AdminAssetItem"},"title":"Items","type":"array"}},"title":"AdminAssetsResponse","type":"object"},"AdminCleanupRequest":{"properties":{"confirm":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Confirm"}},"title":"AdminCleanupRequest","type":"object"},"AdminCleanupResponse":{"properties":{"deleted":{"additionalProperties":{"type":"integer"},"title":"Deleted","type":"object"},"dry_run":{"default":true,"title":"Dry Run","type":"boolean"},"message":{"default":"","title":"Message","type":"string"}},"title":"AdminCleanupResponse","type":"object"},"AdminCommissionItem":{"description":"One ledger row. `amount_cents` is signed: negative for a refund or\nchargeback reversal, per Task 4's ledger.","properties":{"amount_cents":{"title":"Amount Cents","type":"integer"},"available_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Available At"},"base_cents":{"title":"Base Cents","type":"integer"},"created_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Created At"},"currency":{"title":"Currency","type":"string"},"id":{"title":"Id","type":"integer"},"kind":{"title":"Kind","type":"string"},"payout_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Payout Id"},"rate_bps":{"title":"Rate Bps","type":"integer"},"source_ref":{"title":"Source Ref","type":"string"},"status":{"title":"Status","type":"string"},"stripe_invoice_id":{"title":"Stripe Invoice Id","type":"string"}},"required":["id","kind","status","stripe_invoice_id","source_ref","base_cents","rate_bps","amount_cents","currency"],"title":"AdminCommissionItem","type":"object"},"AdminCommissionsResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/AdminCommissionItem"},"title":"Items","type":"array"},"next_cursor":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Next Cursor"}},"title":"AdminCommissionsResponse","type":"object"},"AdminDeclineRequest":{"description":"A decline. The reason is required, and the service is the one that says so.\n\n`reason` accepts an empty string on purpose: the emptiness check lives in\n`admin_service.decline`, so the refusal carries the machine-readable\n`reason_required` code that the admin queue shows, rather than a generic\nvalidation blob.","properties":{"reason":{"maxLength":500,"title":"Reason","type":"string"}},"required":["reason"],"title":"AdminDeclineRequest","type":"object"},"AdminPayoutDetailsResponse":{"description":"Payout details IN THE CLEAR, for the admin who sends the money.\n\nThe only response in the whole module that is not masked. Reading it\nwrites an `audit_log` row naming the admin who asked.","properties":{"affiliate_id":{"title":"Affiliate Id","type":"integer"},"payout_details":{"additionalProperties":{"type":"string"},"title":"Payout Details","type":"object"},"payout_method":{"title":"Payout Method","type":"string"}},"required":["affiliate_id","payout_method"],"title":"AdminPayoutDetailsResponse","type":"object"},"AdminPayoutRunRequest":{"description":"One manual payout run for one affiliate (spec 4.6, R11).\n\n`reference` is required. The run records a transfer that already left the\naccount, so the PayPal or bank transfer id is the only thing that ties the\nledger row back to the statement.","properties":{"method":{"maxLength":32,"minLength":1,"title":"Method","type":"string"},"note":{"anyOf":[{"maxLength":500,"type":"string"},{"type":"null"}],"default":null,"title":"Note"},"period_end":{"format":"date","title":"Period End","type":"string"},"period_start":{"format":"date","title":"Period Start","type":"string"},"reference":{"maxLength":120,"minLength":1,"title":"Reference","type":"string"}},"required":["period_start","period_end","method","reference"],"title":"AdminPayoutRunRequest","type":"object"},"AdminRateRequest":{"description":"The per-affiliate commission rate, in whole percent (spec 3.7).\n\nDeliberately UNTYPED here. The rule (a whole number from 1 to 100) lives\nin the route and the service, so every refusal comes back as this\nmodule's `{code, error}` shape. Declared as `int` the endpoint had TWO\nerror contracts: 0 and 101 answered `invalid_rate` while 50.5 and \"abc\"\nanswered a raw Pydantic array, and only one of the two was the product's\n(round 14 walkthrough, finding 7).\n\n`json_schema_extra` still documents the real shape, so Swagger and a\ngenerated client know it is an integer from 1 to 100. Documentation, not\nvalidation: that is what keeps the refusal in the handler.\n\nThe `default=None` is what keeps a MISSING key out of Pydantic's array\ntoo, so it has to stay, but a default publishes the field as OPTIONAL and\nit is not (Task 15 review, finding 7). The `description` says so, since\nthat is the only half of \"required\" this shape can carry: omitting\n`percent` answers `invalid_rate`, the same refusal every other bad value\ngets.","properties":{"percent":{"default":null,"description":"REQUIRED. A whole percent from 1 to 100. Omitting it, or sending a fraction, a string or a boolean, answers 422 invalid_rate.","maximum":100,"minimum":1.0,"title":"Percent","type":"integer"}},"title":"AdminRateRequest","type":"object"},"AdminUserView":{"properties":{"avatar_count":{"title":"Avatar Count","type":"integer"},"credit_balance":{"description":"Remaining monthly credits","title":"Credit Balance","type":"number"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Display Name"},"email":{"title":"Email","type":"string"},"id":{"title":"Id","type":"integer"},"plan":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Active plan slug, None when unsubscribed","title":"Plan"},"video_count":{"title":"Video Count","type":"integer"}},"required":["id","email","avatar_count","video_count","credit_balance"],"title":"AdminUserView","type":"object"},"AffiliateMeResponse":{"description":"Everything the portal needs for its first paint.\n\n`code`, `link` and `payout_details` mirror the same fields on `affiliate`\nso the link card and the profile form do not have to unwrap a nullable\nobject. `affiliate` is null for a user who never applied.","properties":{"affiliate":{"anyOf":[{"$ref":"#/components/schemas/AffiliateView"},{"type":"null"}],"default":null},"balances":{"$ref":"#/components/schemas/BalancesView"},"code":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Code"},"link":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Link"},"needs_terms_acceptance":{"default":false,"title":"Needs Terms Acceptance","type":"boolean"},"payout_details":{"additionalProperties":{"type":"string"},"title":"Payout Details","type":"object"},"terms_version":{"title":"Terms Version","type":"string"}},"required":["terms_version"],"title":"AffiliateMeResponse","type":"object"},"AffiliateStatsResponse":{"description":"Everything the dashboard paints, in one call (spec 2).\n\nOpen to every status: a pending affiliate reads the same shape with every\nnumber at zero, which is what makes the day-one dashboard possible.\n`counting_since` is the approval moment (null until then) and is\ninformational, not a filter: clicks are refused before approval and a\nreferral cannot exist without one, so there is nothing earlier to exclude.\n\nAll day buckets are UTC (see the note at the top of this section).\n\nPERIOD BOUND, all of them over the one selected period: `totals`,\n`rates`, `revenue_referred_cents`, `series`, `funnel`, `activity`, and\nthe `referrals` and `payouts` previews with their two totals.\nALL TIME, whatever the filter says: `lifetime`, `balances`,\n`next_payout` and `next_steps`. The captions on the page say which is\nwhich, and `period_label` is the words they use for the first group.","properties":{"activity":{"items":{"$ref":"#/components/schemas/ActivityItem"},"title":"Activity","type":"array"},"balances":{"$ref":"#/components/schemas/BalancesView"},"counting_since":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Counting Since"},"funnel":{"$ref":"#/components/schemas/FunnelView"},"lifetime":{"$ref":"#/components/schemas/StatsLifetime"},"next_payout":{"$ref":"#/components/schemas/NextPayoutView"},"next_steps":{"items":{"$ref":"#/components/schemas/NextStepItem"},"title":"Next Steps","type":"array"},"payouts":{"items":{"$ref":"#/components/schemas/PayoutItem"},"title":"Payouts","type":"array"},"payouts_total":{"default":0,"title":"Payouts Total","type":"integer"},"period_label":{"title":"Period Label","type":"string"},"range":{"enum":["today","24h","7d","30d","ytd","365d"],"title":"Range","type":"string"},"rates":{"$ref":"#/components/schemas/StatsRates"},"referrals":{"items":{"$ref":"#/components/schemas/ReferralItem"},"title":"Referrals","type":"array"},"referrals_total":{"default":0,"title":"Referrals Total","type":"integer"},"revenue_referred_cents":{"default":0,"title":"Revenue Referred Cents","type":"integer"},"series":{"items":{"$ref":"#/components/schemas/SeriesPoint"},"title":"Series","type":"array"},"since":{"format":"date-time","title":"Since","type":"string"},"status":{"title":"Status","type":"string"},"totals":{"$ref":"#/components/schemas/StatsTotals"}},"required":["range","period_label","since","status","next_payout"],"title":"AffiliateStatsResponse","type":"object"},"AffiliateView":{"description":"The caller's own affiliate row. Payout details are masked here too.","properties":{"applied_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Applied At"},"channels":{"items":{"type":"string"},"title":"Channels","type":"array"},"code":{"title":"Code","type":"string"},"code_renamed":{"title":"Code Renamed","type":"boolean"},"commission_rate_bps":{"title":"Commission Rate Bps","type":"integer"},"decided_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Decided At"},"decline_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Decline Reason"},"email":{"title":"Email","type":"string"},"full_name":{"title":"Full Name","type":"string"},"id":{"title":"Id","type":"integer"},"payout_details":{"additionalProperties":{"type":"string"},"title":"Payout Details","type":"object"},"payout_method":{"title":"Payout Method","type":"string"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Phone"},"status":{"title":"Status","type":"string"},"terms_accepted_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Terms Accepted At"},"terms_version":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Terms Version"}},"required":["id","code","code_renamed","status","full_name","email","payout_method","commission_rate_bps"],"title":"AffiliateView","type":"object"},"AllChecksResponse":{"additionalProperties":true,"properties":{"checks":{"additionalProperties":true,"title":"Checks","type":"object"},"healthy":{"title":"Healthy","type":"boolean"}},"required":["healthy"],"title":"AllChecksResponse","type":"object"},"ApplyRequest":{"description":"The affiliate application form (spec 4.1).\n\n`accept_terms` must be true: applying is the moment the current terms\nversion is recorded, so an application without it is refused.","properties":{"accept_terms":{"default":false,"title":"Accept Terms","type":"boolean"},"channels":{"items":{"type":"string"},"maxItems":50,"minItems":1,"title":"Channels","type":"array"},"email":{"maxLength":254,"pattern":"^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$","title":"Email","type":"string"},"full_name":{"maxLength":120,"minLength":2,"title":"Full Name","type":"string"},"payout_details":{"additionalProperties":{"type":"string"},"title":"Payout Details","type":"object"},"payout_method":{"maxLength":32,"minLength":1,"title":"Payout Method","type":"string"},"phone":{"anyOf":[{"pattern":"^\\+[1-9]\\d{7,14}$","type":"string"},{"type":"null"}],"default":null,"title":"Phone"}},"required":["full_name","email","channels","payout_method"],"title":"ApplyRequest","type":"object"},"ApprovalQueueResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ApprovalVideoCard"},"title":"Items","type":"array"}},"title":"ApprovalQueueResponse","type":"object"},"ApprovalVideoCard":{"additionalProperties":true,"properties":{"approval_status":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Approval Status"},"avatar_face":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Avatar Face"},"avatar_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Avatar Id"},"avatar_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Avatar Name"},"completed_at":{"default":null,"title":"Completed At"},"created_at":{"default":null,"title":"Created At"},"duration_seconds":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Duration Seconds"},"final_video_file":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Final Video File"},"id":{"title":"Id","type":"integer"},"raw_video_file":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Raw Video File"},"run_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Run Id"},"script_text":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Script Text"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Title"}},"required":["id"],"title":"ApprovalVideoCard","type":"object"},"ArchiveAccountRequest":{"properties":{"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Reason"}},"title":"ArchiveAccountRequest","type":"object"},"AssetItem":{"properties":{"description":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Description"},"id":{"title":"Id","type":"integer"},"kind":{"title":"Kind","type":"string"},"sort_order":{"title":"Sort Order","type":"integer"},"title":{"title":"Title","type":"string"},"url":{"title":"Url","type":"string"}},"required":["id","title","kind","url","sort_order"],"title":"AssetItem","type":"object"},"AssetUploadResponse":{"properties":{"ok":{"title":"Ok","type":"boolean"},"path":{"title":"Path","type":"string"},"url":{"title":"Url","type":"string"}},"required":["ok","path","url"],"title":"AssetUploadResponse","type":"object"},"AssetsResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/AssetItem"},"title":"Items","type":"array"}},"title":"AssetsResponse","type":"object"},"AssignTemplateBody":{"properties":{"template_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Template Id"}},"title":"AssignTemplateBody","type":"object"},"AttributeRequest":{"description":"The code the SPA read from the `af_ref` cookie or from `?ref=`.","properties":{"code":{"maxLength":64,"minLength":1,"title":"Code","type":"string"},"source":{"maxLength":32,"minLength":1,"title":"Source","type":"string"}},"required":["code","source"],"title":"AttributeRequest","type":"object"},"AttributeResponse":{"description":"Always 200. `reason` names why a refusal happened, or is null on success.\n\nThe reasons stay coarse on purpose: `not_eligible` covers an unknown code,\nan unapproved affiliate, a self-referral and an account past the\nattribution window, so the endpoint never tells an anonymous caller\nwhether a given code exists.","properties":{"attributed":{"title":"Attributed","type":"boolean"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Reason"}},"required":["attributed"],"title":"AttributeResponse","type":"object"},"AuthIdentityRow":{"description":"One row from `user_identities`, i.e. one linked Cognito sub.","properties":{"email_at_provider":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Email At Provider"},"linked_at":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Linked At"},"provider":{"title":"Provider","type":"string"},"provider_sub":{"title":"Provider Sub","type":"string"}},"required":["provider","provider_sub"],"title":"AuthIdentityRow","type":"object"},"AuthWhoamiResponse":{"description":"The shape `/api/v1/diagnostics/whoami` returns.\n\nExposes everything the auth gate decided about *this* request so\na developer (or future admin debug UI) can diagnose \"why am I\nbeing asked to log in\" / \"why does my admin badge not show\" without\ngrepping logs. Authenticated callers only: anonymous requests get\na 401 from `@login_required`.\n\nWhile an admin impersonation grant is active (`X-Impersonation-Grant`)\nevery identity field describes the TARGET user; `impersonating` +\n`real_admin_email` carry the server's truth about the view session so\nthe SPA renders the banner from whoami, not client state (spec \u00a73.6).","properties":{"bearer_token_present":{"default":false,"title":"Bearer Token Present","type":"boolean"},"cognito_client_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Cognito Client Id"},"cognito_configured":{"default":false,"title":"Cognito Configured","type":"boolean"},"cognito_region":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Cognito Region"},"cognito_user_pool_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Cognito User Pool Id"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"groups":{"items":{"type":"string"},"title":"Groups","type":"array"},"has_subscription":{"default":false,"title":"Has Subscription","type":"boolean"},"identities":{"items":{"$ref":"#/components/schemas/AuthIdentityRow"},"title":"Identities","type":"array"},"impersonating":{"anyOf":[{"$ref":"#/components/schemas/ImpersonatedIdentity"},{"type":"null"}],"default":null},"is_admin":{"title":"Is Admin","type":"boolean"},"is_affiliate":{"default":false,"title":"Is Affiliate","type":"boolean"},"is_internal":{"default":false,"title":"Is Internal","type":"boolean"},"is_onboarded":{"default":false,"title":"Is Onboarded","type":"boolean"},"meta_registration_event_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Meta Registration Event Id"},"meta_registration_pending":{"default":false,"title":"Meta Registration Pending","type":"boolean"},"niche":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Niche"},"real_admin_email":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Real Admin Email"},"role":{"title":"Role","type":"string"},"session_present":{"default":false,"title":"Session Present","type":"boolean"},"user_id":{"title":"User Id","type":"integer"}},"required":["user_id","email","display_name","role","is_admin"],"title":"AuthWhoamiResponse","type":"object"},"AutoDeliveryNotesBody":{"properties":{"apply":{"default":false,"title":"Apply","type":"boolean"},"avatar_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Avatar Id"}},"title":"AutoDeliveryNotesBody","type":"object"},"AvatarCategoriesResponse":{"properties":{"archived_count":{"default":0,"title":"Archived Count","type":"integer"},"cat_counts":{"additionalProperties":{"type":"integer"},"default":{},"title":"Cat Counts","type":"object"},"categories":{"items":{"$ref":"#/components/schemas/CategoryRow"},"title":"Categories","type":"array"}},"required":["categories"],"title":"AvatarCategoriesResponse","type":"object"},"AvatarChoice":{"properties":{"id":{"title":"Id","type":"integer"},"name":{"title":"Name","type":"string"}},"required":["id","name"],"title":"AvatarChoice","type":"object"},"AvatarDefaultsResponse":{"description":"Static defaults used by the create/edit forms.","properties":{"default_scene_guidelines":{"title":"Default Scene Guidelines","type":"string"},"default_target_audience":{"title":"Default Target Audience","type":"string"}},"required":["default_target_audience","default_scene_guidelines"],"title":"AvatarDefaultsResponse","type":"object"},"AvatarDetailResponse":{"additionalProperties":true,"description":"Full bundle the avatar detail page needs.\n\nCombines the avatar row, its scenes/images split, recent videos,\nsocial accounts, the reference-pack summary, and the integration\nhealth flags the page used to receive via ``render_template`` kwargs.","properties":{"age_band":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Age Band"},"archived":{"default":0,"title":"Archived","type":"integer"},"auto_publish":{"default":0,"title":"Auto Publish","type":"integer"},"bio":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Bio"},"category":{"anyOf":[{"$ref":"#/components/schemas/CategoryRow"},{"type":"null"}],"default":null},"category_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Category Id"},"content_pillars":{"default":[],"items":{"$ref":"#/components/schemas/AvatarPillar"},"title":"Content Pillars","type":"array"},"controversy_level":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Controversy Level"},"created_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Created At"},"currently_lives_in":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Currently Lives In"},"default_engine":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Default Engine"},"default_text_style":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Default Text Style"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Description"},"face_focus":{"anyOf":[{"$ref":"#/components/schemas/FaceFocusPoint"},{"type":"null"}],"default":null},"face_image":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Face Image"},"first_outfit_status":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"First Outfit Status"},"forbidden_topics":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Forbidden Topics"},"gemini_ready":{"default":false,"title":"Gemini Ready","type":"boolean"},"gender":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Gender"},"heygen_avatar_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Heygen Avatar Id"},"heygen_expression":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Heygen Expression"},"heygen_sync_error":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Heygen Sync Error"},"heygen_sync_status":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Heygen Sync Status"},"heygen_talking_style":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Heygen Talking Style"},"id":{"title":"Id","type":"integer"},"image_prompt":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Image Prompt"},"images":{"default":[],"items":{"$ref":"#/components/schemas/AvatarSceneItem"},"title":"Images","type":"array"},"instagram_display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Instagram Display Name"},"instagram_handle":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Instagram Handle"},"is_template":{"default":false,"title":"Is Template","type":"boolean"},"motion_prompt":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Motion Prompt"},"name":{"title":"Name","type":"string"},"native_language":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Native Language"},"origin":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Origin"},"outfit_count":{"default":0,"title":"Outfit Count","type":"integer"},"posting_frequency":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Posting Frequency"},"posting_times":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Posting Times"},"profession":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profession"},"reference_summary":{"$ref":"#/components/schemas/AvatarReferenceSummary","default":{"canonical_count":0,"filled_count":0,"has_any":false}},"scene_guidelines":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Scene Guidelines"},"scenes":{"default":[],"items":{"$ref":"#/components/schemas/AvatarSceneItem"},"title":"Scenes","type":"array"},"signature_phrases":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Signature Phrases"},"social_accounts":{"default":[],"items":{"$ref":"#/components/schemas/AvatarSocialAccount"},"title":"Social Accounts","type":"array"},"speaking_style":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Speaking Style"},"story":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Story"},"target_audience":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Target Audience"},"tiktok_handle":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Tiktok Handle"},"timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Timezone"},"updated_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Updated At"},"videos":{"default":[],"items":{"$ref":"#/components/schemas/AvatarVideoSummary"},"title":"Videos","type":"array"},"voice_description":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Voice Description"},"voice_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Voice Id"},"voice_integration_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Voice Integration Id"},"voice_model":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Voice Model"},"voice_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Voice Name"},"voice_similarity":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Voice Similarity"},"voice_speed":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Voice Speed"},"voice_stability":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Voice Stability"},"voice_style":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Voice Style"}},"required":["id","name"],"title":"AvatarDetailResponse","type":"object"},"AvatarHealth":{"properties":{"auto_publish":{"default":0,"title":"Auto Publish","type":"integer"},"default_engine":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Default Engine"},"default_text_style":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Default Text Style"},"face_image":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Face Image"},"heygen_avatar_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Heygen Avatar Id"},"id":{"title":"Id","type":"integer"},"ig_connected":{"default":0,"title":"Ig Connected","type":"integer"},"name":{"title":"Name","type":"string"},"pending_approvals":{"default":0,"title":"Pending Approvals","type":"integer"},"pillar_count":{"default":0,"title":"Pillar Count","type":"integer"},"posting_frequency":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Posting Frequency"},"posting_times":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Posting Times"},"timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Timezone"},"today_runs":{"default":0,"title":"Today Runs","type":"integer"},"total_completed":{"default":0,"title":"Total Completed","type":"integer"},"total_failed":{"default":0,"title":"Total Failed","type":"integer"},"voice_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Voice Id"}},"required":["id","name"],"title":"AvatarHealth","type":"object"},"AvatarListItem":{"properties":{"archived":{"default":0,"title":"Archived","type":"integer"},"category":{"anyOf":[{"$ref":"#/components/schemas/CategoryRow"},{"type":"null"}],"default":null},"category_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Category Id"},"created_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Created At"},"default_engine":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Default Engine"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Description"},"display_order":{"default":0,"title":"Display Order","type":"integer"},"face_focus":{"anyOf":[{"$ref":"#/components/schemas/FaceFocusPoint"},{"type":"null"}],"default":null},"face_image":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Face Image"},"heygen_avatar_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Heygen Avatar Id"},"heygen_sync_status":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Heygen Sync Status"},"id":{"title":"Id","type":"integer"},"image_count":{"default":0,"title":"Image Count","type":"integer"},"name":{"title":"Name","type":"string"},"scene_count":{"default":0,"title":"Scene Count","type":"integer"},"story":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Story"},"video_count":{"default":0,"title":"Video Count","type":"integer"},"voice_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Voice Id"}},"required":["id","name"],"title":"AvatarListItem","type":"object"},"AvatarListResponse":{"properties":{"archived_count":{"default":0,"title":"Archived Count","type":"integer"},"cat_counts":{"additionalProperties":{"type":"integer"},"default":{},"title":"Cat Counts","type":"object"},"categories":{"default":[],"items":{"$ref":"#/components/schemas/CategoryRow"},"title":"Categories","type":"array"},"items":{"items":{"$ref":"#/components/schemas/AvatarListItem"},"title":"Items","type":"array"}},"required":["items"],"title":"AvatarListResponse","type":"object"},"AvatarOption":{"properties":{"description":{"title":"Description","type":"string"},"id":{"title":"Id","type":"integer"},"name":{"title":"Name","type":"string"},"story":{"title":"Story","type":"string"}},"required":["id","name","description","story"],"title":"AvatarOption","type":"object"},"AvatarOutfitItem":{"description":"One saved outfit: the sheet the copy pipeline attaches and the dressed preview.","properties":{"created_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Created At"},"id":{"title":"Id","type":"integer"},"name":{"title":"Name","type":"string"},"preview_url":{"title":"Preview Url","type":"string"},"sheet_url":{"title":"Sheet Url","type":"string"},"source":{"title":"Source","type":"string"}},"required":["id","name","sheet_url","preview_url","source"],"title":"AvatarOutfitItem","type":"object"},"AvatarOutfitsPage":{"description":"The Videos gallery shape: one page plus `has_more` for the infinite scroll.","properties":{"first_outfit_pending":{"default":false,"title":"First Outfit Pending","type":"boolean"},"has_more":{"title":"Has More","type":"boolean"},"items":{"items":{"$ref":"#/components/schemas/AvatarOutfitItem"},"title":"Items","type":"array"},"page":{"title":"Page","type":"integer"},"page_size":{"title":"Page Size","type":"integer"},"total":{"title":"Total","type":"integer"}},"required":["items","total","page","page_size","has_more"],"title":"AvatarOutfitsPage","type":"object"},"AvatarPillar":{"properties":{"description":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Description"},"id":{"title":"Id","type":"integer"},"name":{"title":"Name","type":"string"},"weight":{"default":50,"title":"Weight","type":"integer"}},"required":["id","name"],"title":"AvatarPillar","type":"object"},"AvatarPillarsResponse":{"properties":{"avatar":{"additionalProperties":true,"default":{},"title":"Avatar","type":"object"},"pillars":{"default":[],"items":{"$ref":"#/components/schemas/AvatarPillar"},"title":"Pillars","type":"array"}},"title":"AvatarPillarsResponse","type":"object"},"AvatarReferenceSummary":{"properties":{"canonical_count":{"default":0,"title":"Canonical Count","type":"integer"},"filled_count":{"default":0,"title":"Filled Count","type":"integer"},"has_any":{"default":false,"title":"Has Any","type":"boolean"}},"title":"AvatarReferenceSummary","type":"object"},"AvatarSceneItem":{"properties":{"auto_saved":{"default":0,"title":"Auto Saved","type":"integer"},"created_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Created At"},"filename":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Filename"},"heygen_photo_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Heygen Photo Id"},"id":{"title":"Id","type":"integer"},"is_primary":{"default":0,"title":"Is Primary","type":"integer"},"kind":{"default":"scene","title":"Kind","type":"string"},"scene_title":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Scene Title"}},"required":["id"],"title":"AvatarSceneItem","type":"object"},"AvatarScenesResponse":{"properties":{"avatar":{"additionalProperties":true,"title":"Avatar","type":"object"},"scenes":{"items":{"additionalProperties":true,"type":"object"},"title":"Scenes","type":"array"}},"required":["avatar"],"title":"AvatarScenesResponse","type":"object"},"AvatarSocialAccount":{"additionalProperties":true,"properties":{"account_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Account Name"},"connected_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Connected At"},"id":{"title":"Id","type":"integer"},"platform":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Platform"}},"required":["id"],"title":"AvatarSocialAccount","type":"object"},"AvatarSocialAccountsResponse":{"properties":{"items":{"default":[],"items":{"$ref":"#/components/schemas/AvatarSocialAccount"},"title":"Items","type":"array"}},"title":"AvatarSocialAccountsResponse","type":"object"},"AvatarTemplateItem":{"properties":{"age_range":{"default":"","title":"Age Range","type":"string"},"content_niche":{"default":"","title":"Content Niche","type":"string"},"description_text":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Description Text"},"gender":{"default":"","title":"Gender","type":"string"},"id":{"title":"Id","type":"integer"},"image_prompt":{"default":"","title":"Image Prompt","type":"string"},"name":{"title":"Name","type":"string"},"niche":{"title":"Niche","type":"string"},"origin":{"default":"","title":"Origin","type":"string"},"preview_image_key":{"default":"","title":"Preview Image Key","type":"string"},"reference_image_urls":{"default":[],"items":{"type":"string"},"title":"Reference Image Urls","type":"array"},"slug":{"default":"","title":"Slug","type":"string"},"speaking_style":{"default":"","title":"Speaking Style","type":"string"},"story":{"default":"","title":"Story","type":"string"},"suggested_forbidden_topics":{"default":"","title":"Suggested Forbidden Topics","type":"string"},"suggested_signature_phrases":{"default":"","title":"Suggested Signature Phrases","type":"string"},"target_audience":{"default":"","title":"Target Audience","type":"string"}},"required":["id","name","niche"],"title":"AvatarTemplateItem","type":"object"},"AvatarTemplatesResponse":{"properties":{"counts":{"additionalProperties":{"type":"integer"},"title":"Counts","type":"object"},"niches":{"items":{"type":"string"},"title":"Niches","type":"array"},"templates":{"items":{"$ref":"#/components/schemas/AvatarTemplateItem"},"title":"Templates","type":"array"}},"required":["templates","niches","counts"],"title":"AvatarTemplatesResponse","type":"object"},"AvatarVideoSummary":{"properties":{"background_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Background Id"},"background_image":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Background Image"},"background_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Background Name"},"created_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Created At"},"duration_seconds":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Duration Seconds"},"final_video_file":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Final Video File"},"id":{"title":"Id","type":"integer"},"raw_video_file":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Raw Video File"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Status"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Title"}},"required":["id"],"title":"AvatarVideoSummary","type":"object"},"BackgroundCard":{"properties":{"category":{"title":"Category","type":"string"},"id":{"title":"Id","type":"integer"},"image_file":{"title":"Image File","type":"string"},"is_preset":{"default":0,"title":"Is Preset","type":"integer"},"name":{"title":"Name","type":"string"},"owner_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Owner Id"}},"required":["id","name","category","image_file"],"title":"BackgroundCard","type":"object"},"BackgroundsListResponse":{"properties":{"categories":{"default":[],"items":{"type":"string"},"title":"Categories","type":"array"},"items":{"items":{"$ref":"#/components/schemas/BackgroundCard"},"title":"Items","type":"array"},"selected_category":{"default":"","title":"Selected Category","type":"string"}},"required":["items"],"title":"BackgroundsListResponse","type":"object"},"BalancesView":{"properties":{"available_cents":{"default":0,"title":"Available Cents","type":"integer"},"lifetime_cents":{"default":0,"title":"Lifetime Cents","type":"integer"},"paid_cents":{"default":0,"title":"Paid Cents","type":"integer"},"pending_cents":{"default":0,"title":"Pending Cents","type":"integer"}},"title":"BalancesView","type":"object"},"BrokenFaceAvatar":{"description":"One avatar pointing at a face object that is not in storage.","properties":{"face_image":{"title":"Face Image","type":"string"},"id":{"title":"Id","type":"integer"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Name"},"thumb_1080":{"title":"Thumb 1080","type":"boolean"}},"required":["id","face_image","thumb_1080"],"title":"BrokenFaceAvatar","type":"object"},"BulkUpdateProfilesRequest":{"properties":{"profiles":{"items":{"additionalProperties":true,"type":"object"},"title":"Profiles","type":"array"}},"title":"BulkUpdateProfilesRequest","type":"object"},"BulkUpdateResponse":{"additionalProperties":true,"properties":{},"title":"BulkUpdateResponse","type":"object"},"BusinessLeadRequest":{"description":"One business lead from `/ai-influencers-for-business`.\n\nPublic and anonymous: a business that has never signed up is the whole\naudience. `website` is the honeypot (`company` is a real field here, the\nbusiness name, unlike on the support form).","properties":{"anonymous_id":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"title":"Anonymous Id"},"company":{"maxLength":160,"minLength":1,"title":"Company","type":"string"},"email":{"maxLength":254,"title":"Email","type":"string"},"fbc":{"anyOf":[{"maxLength":255,"type":"string"},{"type":"null"}],"default":null,"title":"Fbc"},"fbp":{"anyOf":[{"maxLength":255,"type":"string"},{"type":"null"}],"default":null,"title":"Fbp"},"industry":{"$ref":"#/components/schemas/IndustrySlug"},"intent":{"$ref":"#/components/schemas/IntentSlug"},"message":{"anyOf":[{"maxLength":2000,"type":"string"},{"type":"null"}],"default":null,"title":"Message"},"name":{"maxLength":120,"minLength":1,"title":"Name","type":"string"},"page_url":{"anyOf":[{"maxLength":500,"type":"string"},{"type":"null"}],"default":null,"title":"Page Url"},"turnstile_token":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Turnstile Token"},"website":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Website"}},"required":["name","email","company","industry","intent"],"title":"BusinessLeadRequest","type":"object"},"BusinessLeadResponse":{"description":"The reference the business is shown, and quotes back if they write again.","properties":{"meta_lead_event_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Meta Lead Event Id"},"reference":{"title":"Reference","type":"string"}},"required":["reference"],"title":"BusinessLeadResponse","type":"object"},"CampaignsListResponse":{"properties":{"items":{"items":{},"title":"Items","type":"array"}},"required":["items"],"title":"CampaignsListResponse","type":"object"},"CancelSubscriptionRequest":{"description":"Body for `POST /api/v1/billing/cancel` (the retention flow's final\naction). The survey answer is REQUIRED: no cancellation without a\nrecorded reason (product decision, 2026-08-21).","properties":{"details":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Details"},"reason":{"title":"Reason","type":"string"}},"required":["reason"],"title":"CancelSubscriptionRequest","type":"object"},"CaptionCut":{"description":"One burned caption-style cut available for download.\n\n`position` is the named height the cut was burned at (top / middle /\nbottom) or None for the style's own height. Stored as the asset label\n`<style>@<position>`; split here so the client matches on the two\nfields instead of parsing a label.","properties":{"position":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Position"},"style":{"title":"Style","type":"string"},"video_file":{"title":"Video File","type":"string"}},"required":["style","video_file"],"title":"CaptionCut","type":"object"},"CaptionStyleCatalogResponse":{"description":"`GET /api/v1/videos/caption-styles` \u2014 the presets, from the one place\nthat defines them. The SPA used to keep its own hand-maintained copy of\nthe names and descriptions, whose comment admitted a new preset meant\nediting both. This is that list, served.","properties":{"styles":{"items":{"$ref":"#/components/schemas/CaptionStyleItem"},"title":"Styles","type":"array"}},"required":["styles"],"title":"CaptionStyleCatalogResponse","type":"object"},"CaptionStyleItem":{"description":"One user-facing caption preset, with where its captions really land.\n\nThe geometry is parsed from the style's own ASS line, so a preview drawn\nfrom it cannot disagree with the burn. Fractions of the frame, not\npixels: the client renders at whatever size its card happens to be.","properties":{"bottom":{"title":"Bottom","type":"number"},"desc":{"title":"Desc","type":"string"},"font_scale":{"title":"Font Scale","type":"number"},"mono":{"title":"Mono","type":"boolean"},"name":{"title":"Name","type":"string"},"positions":{"additionalProperties":{"type":"number"},"title":"Positions","type":"object"},"side":{"title":"Side","type":"number"},"slug":{"title":"Slug","type":"string"}},"required":["slug","name","desc","bottom","side","font_scale","mono","positions"],"title":"CaptionStyleItem","type":"object"},"CaptionWordItem":{"description":"One burn-time word timing (seconds).","properties":{"end":{"title":"End","type":"number"},"start":{"title":"Start","type":"number"},"text":{"title":"Text","type":"string"}},"required":["text","start","end"],"title":"CaptionWordItem","type":"object"},"CarouselAdminResponse":{"description":"Admin-only prompt inspector block (present only for admins).","properties":{"director":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"title":"Director"},"slides":{"additionalProperties":{"items":{"additionalProperties":true,"type":"object"},"type":"array"},"title":"Slides","type":"object"}},"title":"CarouselAdminResponse","type":"object"},"CarouselListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/CarouselResponse"},"title":"Items","type":"array"}},"title":"CarouselListResponse","type":"object"},"CarouselResponse":{"properties":{"admin":{"anyOf":[{"$ref":"#/components/schemas/CarouselAdminResponse"},{"type":"null"}],"default":null},"aspect_ratio":{"title":"Aspect Ratio","type":"string"},"avatar_face":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Avatar Face"},"avatar_face_focus":{"anyOf":[{"$ref":"#/components/schemas/FaceFocusPoint"},{"type":"null"}],"default":null},"avatar_id":{"title":"Avatar Id","type":"integer"},"avatar_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Avatar Name"},"completed_at":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Completed At"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Created At"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Error Message"},"id":{"title":"Id","type":"integer"},"slide_count":{"title":"Slide Count","type":"integer"},"slides":{"items":{"$ref":"#/components/schemas/SlideResponse"},"title":"Slides","type":"array"},"status":{"title":"Status","type":"string"},"template_key":{"title":"Template Key","type":"string"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Title"},"topic":{"title":"Topic","type":"string"}},"required":["id","topic","avatar_id","template_key","slide_count","aspect_ratio","status"],"title":"CarouselResponse","type":"object"},"CarouselStatusResponse":{"properties":{"failed_count":{"title":"Failed Count","type":"integer"},"id":{"title":"Id","type":"integer"},"ready_count":{"title":"Ready Count","type":"integer"},"slides":{"items":{"$ref":"#/components/schemas/SlideResponse"},"title":"Slides","type":"array"},"status":{"title":"Status","type":"string"},"total":{"title":"Total","type":"integer"}},"required":["id","status","ready_count","failed_count","total"],"title":"CarouselStatusResponse","type":"object"},"CategoriesResponse":{"properties":{"categories":{"items":{},"title":"Categories","type":"array"}},"title":"CategoriesResponse","type":"object"},"CategoryCountsResponse":{"description":"Where the taxonomy stands: the before and after of a backfill run.","properties":{"candidates":{"default":0,"title":"Candidates","type":"integer"},"categorised":{"default":0,"title":"Categorised","type":"integer"},"other":{"default":0,"title":"Other","type":"integer"},"total":{"default":0,"title":"Total","type":"integer"},"uncategorised":{"default":0,"title":"Uncategorised","type":"integer"}},"title":"CategoryCountsResponse","type":"object"},"CategoryCreateRequest":{"properties":{"color":{"default":"#d4a843","title":"Color","type":"string"},"name":{"default":"","title":"Name","type":"string"}},"title":"CategoryCreateRequest","type":"object"},"CategoryResponse":{"properties":{"color":{"default":"#d4a843","title":"Color","type":"string"},"id":{"title":"Id","type":"integer"},"name":{"title":"Name","type":"string"}},"required":["id","name"],"title":"CategoryResponse","type":"object"},"CategoryRow":{"properties":{"color":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Color"},"id":{"title":"Id","type":"integer"},"name":{"title":"Name","type":"string"}},"required":["id","name"],"title":"CategoryRow","type":"object"},"CategoryScenesOkResponse":{"properties":{"ok":{"default":true,"title":"Ok","type":"boolean"},"scene_categories":{"items":{"type":"string"},"title":"Scene Categories","type":"array"}},"title":"CategoryScenesOkResponse","type":"object"},"CategoryScenesRequest":{"properties":{"scene_categories":{"items":{"type":"string"},"title":"Scene Categories","type":"array"}},"title":"CategoryScenesRequest","type":"object"},"CategorySlug":{"description":"The wire value. Anything outside this set is a 422, never a guess.","enum":["how-do-i","video-render-failed","avatar-face-voice","credits-limits-plan","billing-invoices-card","sign-in-account","refund","custom-plan-partnership","something-else"],"title":"CategorySlug","type":"string"},"ChangePlanPreviewResponse":{"properties":{"amount_due_cents":{"title":"Amount Due Cents","type":"integer"},"balance_applied_cents":{"default":0,"title":"Balance Applied Cents","type":"integer"},"change_kind":{"title":"Change Kind","type":"string"},"credits_granted_now":{"default":0,"title":"Credits Granted Now","type":"integer"},"currency":{"title":"Currency","type":"string"},"discount_cents":{"default":0,"title":"Discount Cents","type":"integer"},"discount_label":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Discount Label"},"effective_at":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Effective At"},"interval":{"title":"Interval","type":"string"},"is_trial_giveup":{"title":"Is Trial Giveup","type":"boolean"},"list_amount_cents":{"default":0,"title":"List Amount Cents","type":"integer"},"payment_method":{"anyOf":[{"$ref":"#/components/schemas/PaymentMethodResponse"},{"type":"null"}],"default":null},"plan_name":{"title":"Plan Name","type":"string"},"plan_slug":{"title":"Plan Slug","type":"string"}},"required":["plan_slug","plan_name","interval","amount_due_cents","currency","is_trial_giveup","change_kind"],"title":"ChangePlanPreviewResponse","type":"object"},"ChangePlanRequest":{"description":"Body for `POST /api/v1/billing/change-plan` (switch a live subscription).","properties":{"interval":{"default":"monthly","title":"Interval","type":"string"},"plan":{"title":"Plan","type":"string"}},"required":["plan"],"title":"ChangePlanRequest","type":"object"},"ChargeItemResponse":{"properties":{"amount":{"title":"Amount","type":"integer"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Created At"},"currency":{"title":"Currency","type":"string"},"kind":{"title":"Kind","type":"string"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Reason"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Status"},"stripe_id":{"title":"Stripe Id","type":"string"}},"required":["stripe_id","amount","currency","kind"],"title":"ChargeItemResponse","type":"object"},"ChargesResponse":{"properties":{"charges":{"items":{"$ref":"#/components/schemas/ChargeItemResponse"},"title":"Charges","type":"array"}},"required":["charges"],"title":"ChargesResponse","type":"object"},"CheckoutIntentResponse":{"properties":{"amount":{"title":"Amount","type":"integer"},"client_secret":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Client Secret"},"currency":{"title":"Currency","type":"string"},"discount_amount_off":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Discount Amount Off"},"discount_duration":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Discount Duration"},"discount_label":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Discount Label"},"discount_percent_off":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Discount Percent Off"},"finalized":{"default":false,"title":"Finalized","type":"boolean"},"intent_id":{"title":"Intent Id","type":"string"},"interval":{"title":"Interval","type":"string"},"meta_checkout_event_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Meta Checkout Event Id"},"mode":{"title":"Mode","type":"string"},"plan_slug":{"title":"Plan Slug","type":"string"}},"required":["intent_id","mode","amount","currency","plan_slug","interval"],"title":"CheckoutIntentResponse","type":"object"},"CheckoutPaymentIntentRequest":{"description":"Body for `POST /api/v1/billing/checkout/payment-intent`.","properties":{"interval":{"default":"monthly","title":"Interval","type":"string"},"plan":{"title":"Plan","type":"string"},"promotion_code":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Promotion Code"}},"required":["plan"],"title":"CheckoutPaymentIntentRequest","type":"object"},"ChurnReasonRow":{"properties":{"mrr_cents":{"title":"Mrr Cents","type":"integer"},"reason":{"enum":["canceled","payment_failed","other","unknown","plan_switch"],"title":"Reason","type":"string"},"subscriptions":{"title":"Subscriptions","type":"integer"}},"required":["reason","subscriptions","mrr_cents"],"title":"ChurnReasonRow","type":"object"},"ClassifyBackfillCountsResponse":{"properties":{"counts":{"$ref":"#/components/schemas/CategoryCountsResponse"},"ok":{"default":true,"title":"Ok","type":"boolean"}},"required":["counts"],"title":"ClassifyBackfillCountsResponse","type":"object"},"ClassifyBackfillQueuedResponse":{"properties":{"before":{"$ref":"#/components/schemas/CategoryCountsResponse"},"ok":{"default":true,"title":"Ok","type":"boolean"},"queued":{"default":true,"title":"Queued","type":"boolean"},"task_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Task Id"}},"required":["before"],"title":"ClassifyBackfillQueuedResponse","type":"object"},"ClassifyBackfillRequest":{"description":"Start the retro classification pass. Every field optional.\n\n``limit`` runs it in slices, ``dry_run`` reports the plan without spending\nanything, ``only_missing`` narrows to accounts with no category at all.","properties":{"dry_run":{"default":false,"title":"Dry Run","type":"boolean"},"limit":{"anyOf":[{"exclusiveMinimum":0.0,"type":"integer"},{"type":"null"}],"default":null,"title":"Limit"},"only_missing":{"default":false,"title":"Only Missing","type":"boolean"}},"title":"ClassifyBackfillRequest","type":"object"},"ClassifySuggestRequest":{"properties":{"username":{"default":"","title":"Username","type":"string"}},"title":"ClassifySuggestRequest","type":"object"},"ClassifySuggestResponse":{"additionalProperties":true,"properties":{},"title":"ClassifySuggestResponse","type":"object"},"CodeConfirmRequest":{"properties":{"access_token":{"description":"Cognito access token","minLength":1,"title":"Access Token","type":"string"},"code":{"description":"Cognito verification code","maxLength":8,"minLength":4,"title":"Code","type":"string"}},"required":["access_token","code"],"title":"CodeConfirmRequest","type":"object"},"CodeRequest":{"description":"The one-time referral-code rename. The service validates the format.","properties":{"code":{"maxLength":64,"minLength":1,"title":"Code","type":"string"}},"required":["code"],"title":"CodeRequest","type":"object"},"CodeValidResponse":{"description":"The public code check. The verdict and the code the caller sent, nothing else.","properties":{"code":{"title":"Code","type":"string"},"valid":{"title":"Valid","type":"boolean"}},"required":["code","valid"],"title":"CodeValidResponse","type":"object"},"Cohort":{"properties":{"cohort_size":{"title":"Cohort Size","type":"integer"},"cohort_week":{"format":"date","title":"Cohort Week","type":"string"},"weeks":{"items":{"$ref":"#/components/schemas/CohortWeek"},"title":"Weeks","type":"array"}},"required":["cohort_week","cohort_size","weeks"],"title":"Cohort","type":"object"},"CohortWeek":{"properties":{"active_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Active Pct"},"active_users":{"title":"Active Users","type":"integer"},"activity_week":{"format":"date","title":"Activity Week","type":"string"},"cumulative_revenue_cents":{"title":"Cumulative Revenue Cents","type":"integer"},"paid_share_of_cohort_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Paid Share Of Cohort Pct"},"paid_users":{"title":"Paid Users","type":"integer"},"revenue_cents":{"title":"Revenue Cents","type":"integer"},"week_offset":{"title":"Week Offset","type":"integer"}},"required":["week_offset","activity_week","active_users","active_pct","paid_users","paid_share_of_cohort_pct","revenue_cents","cumulative_revenue_cents"],"title":"CohortWeek","type":"object"},"ConfigResponse":{"properties":{"publishable_key":{"title":"Publishable Key","type":"string"}},"required":["publishable_key"],"title":"ConfigResponse","type":"object"},"ConnectRequest":{"properties":{"api_key":{"maxLength":256,"minLength":8,"title":"Api Key","type":"string"}},"required":["api_key"],"title":"ConnectRequest","type":"object"},"ContactRequest":{"description":"One submission, from either surface.\n\n`email` is optional in the schema and required by the route for an\nanonymous caller: the schema cannot see the session, and a signed-in\ncaller's address comes from their account, never from the body.","properties":{"anonymous_id":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"title":"Anonymous Id"},"category":{"$ref":"#/components/schemas/CategorySlug"},"company":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Company"},"device":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"title":"Device"},"email":{"anyOf":[{"maxLength":254,"type":"string"},{"type":"null"}],"default":null,"title":"Email"},"happened":{"maxLength":4000,"minLength":1,"title":"Happened","type":"string"},"page_url":{"anyOf":[{"maxLength":500,"type":"string"},{"type":"null"}],"default":null,"title":"Page Url"},"screenshot_base64":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Screenshot Base64"},"screenshot_key":{"anyOf":[{"maxLength":300,"type":"string"},{"type":"null"}],"default":null,"title":"Screenshot Key"},"screenshot_name":{"anyOf":[{"maxLength":120,"type":"string"},{"type":"null"}],"default":null,"title":"Screenshot Name"},"surface":{"$ref":"#/components/schemas/Surface","default":"marketing"},"tried":{"maxLength":2000,"minLength":1,"title":"Tried","type":"string"},"turnstile_token":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Turnstile Token"},"video_or_job_id":{"anyOf":[{"maxLength":120,"type":"string"},{"type":"null"}],"default":null,"title":"Video Or Job Id"}},"required":["category","tried","happened"],"title":"ContactRequest","type":"object"},"ContactResponse":{"description":"What the customer is shown, and quotes back if they write again.","properties":{"reference":{"title":"Reference","type":"string"}},"required":["reference"],"title":"ContactResponse","type":"object"},"CopiedVideoItem":{"properties":{"app_path":{"description":"The video page in the app","title":"App Path","type":"string"},"created_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Created At"},"id":{"title":"Id","type":"integer"},"method":{"description":"The copy method as the wizard names it","title":"Method","type":"string"},"models":{"description":"Distinct models per shot or part, in order","items":{"type":"string"},"title":"Models","type":"array"},"owner_email":{"title":"Owner Email","type":"string"},"source_reel_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The original reel","title":"Source Reel Url"},"status":{"title":"Status","type":"string"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Title"},"video_file":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The result's stored file, resolved by the SPA exactly like the video page","title":"Video File"}},"required":["id","owner_email","status","method","app_path"],"title":"CopiedVideoItem","type":"object"},"CopiedVideosResponse":{"properties":{"has_more":{"title":"Has More","type":"boolean"},"items":{"items":{"$ref":"#/components/schemas/CopiedVideoItem"},"title":"Items","type":"array"},"limit":{"title":"Limit","type":"integer"},"offset":{"title":"Offset","type":"integer"}},"required":["items","limit","offset","has_more"],"title":"CopiedVideosResponse","type":"object"},"CreateAvatarRequest":{"properties":{"description":{"default":"","title":"Description","type":"string"},"draft_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Draft Id"},"face_image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Face Image Url"},"name":{"default":"","title":"Name","type":"string"},"story":{"default":"","title":"Story","type":"string"},"voice_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Voice Id"}},"title":"CreateAvatarRequest","type":"object"},"CreateAvatarResponse":{"properties":{"avatar_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Avatar Id"},"ok":{"default":true,"title":"Ok","type":"boolean"}},"title":"CreateAvatarResponse","type":"object"},"CreateCampaignBody":{"additionalProperties":true,"properties":{},"title":"CreateCampaignBody","type":"object"},"CreateCarouselBody":{"description":"POST /api/v1/carousels: create a carousel from wizard picks.","properties":{"aspect_ratio":{"default":"4:5","title":"Aspect Ratio","type":"string"},"avatar_id":{"title":"Avatar Id","type":"integer"},"draft_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Draft Id"},"slide_count":{"maximum":10,"minimum":3.0,"title":"Slide Count","type":"integer"},"template_key":{"title":"Template Key","type":"string"},"title":{"anyOf":[{"maxLength":120,"type":"string"},{"type":"null"}],"default":null,"title":"Title"},"topic":{"maxLength":500,"minLength":1,"title":"Topic","type":"string"}},"required":["topic","avatar_id","template_key","slide_count"],"title":"CreateCarouselBody","type":"object"},"CreateCarouselResponse":{"properties":{"carousel_id":{"title":"Carousel Id","type":"integer"}},"required":["carousel_id"],"title":"CreateCarouselResponse","type":"object"},"CreateDraftResponse":{"properties":{"draft_id":{"title":"Draft Id","type":"integer"}},"required":["draft_id"],"title":"CreateDraftResponse","type":"object"},"CreateGlobalAccountRequest":{"description":"Request body for POST /api/v1/followed-accounts/global (admin only).\n\nCreates an AvatarFactory Verified account visible to all users.","properties":{"handle":{"default":"","title":"Handle","type":"string"},"platform":{"default":"instagram","title":"Platform","type":"string"}},"title":"CreateGlobalAccountRequest","type":"object"},"CreateSubmitRequest":{"properties":{"avatar_id":{"title":"Avatar Id","type":"integer"},"script_text":{"title":"Script Text","type":"string"}},"required":["avatar_id","script_text"],"title":"CreateSubmitRequest","type":"object"},"CreateSubmitResponse":{"properties":{"run_id":{"title":"Run Id","type":"integer"},"success":{"title":"Success","type":"boolean"}},"required":["success","run_id"],"title":"CreateSubmitResponse","type":"object"},"CreditCostsResponse":{"description":"Public credit charges per action, for the on-button cost badges.\n\nCredit amounts only. Our internal provider USD cost (``PROVIDER_USD_RATES``)\nis never exposed here.","properties":{"avatar_finalize":{"title":"Avatar Finalize","type":"number"},"image":{"title":"Image","type":"number"},"refine":{"title":"Refine","type":"number"},"video_models":{"items":{"additionalProperties":true,"type":"object"},"title":"Video Models","type":"array"},"video_per_second":{"additionalProperties":{"type":"number"},"title":"Video Per Second","type":"object"},"voice":{"title":"Voice","type":"number"},"voice_refine":{"title":"Voice Refine","type":"number"}},"required":["image","refine","avatar_finalize","voice","voice_refine","video_per_second","video_models"],"title":"CreditCostsResponse","type":"object"},"CreditHistoryItemResponse":{"description":"One credit spend-history row. Credit amounts only (no internal cost).","properties":{"balance_after":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Balance After"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Created At"},"credits":{"title":"Credits","type":"number"},"operation_kind":{"title":"Operation Kind","type":"string"},"operation_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Operation Ref"},"status":{"title":"Status","type":"string"}},"required":["operation_kind","status","credits"],"title":"CreditHistoryItemResponse","type":"object"},"CreditHistoryResponse":{"properties":{"history":{"items":{"$ref":"#/components/schemas/CreditHistoryItemResponse"},"title":"History","type":"array"}},"required":["history"],"title":"CreditHistoryResponse","type":"object"},"CreditSummaryResponse":{"properties":{"monthly_included":{"title":"Monthly Included","type":"number"},"monthly_remaining":{"title":"Monthly Remaining","type":"number"},"period_end":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Period End"}},"required":["monthly_included","monthly_remaining"],"title":"CreditSummaryResponse","type":"object"},"DashboardResponse":{"properties":{"avatars":{"items":{"$ref":"#/components/schemas/AvatarHealth"},"title":"Avatars","type":"array"},"pending_count":{"title":"Pending Count","type":"integer"},"recent_runs":{"items":{"$ref":"#/components/schemas/RecentRunRow"},"title":"Recent Runs","type":"array"},"today_stats":{"$ref":"#/components/schemas/TodayStats"}},"required":["avatars","pending_count","today_stats"],"title":"DashboardResponse","type":"object"},"DashboardSummaryResponse":{"properties":{"avatar_count":{"default":0,"title":"Avatar Count","type":"integer"},"recent_videos":{"items":{"$ref":"#/components/schemas/DashboardVideoCardResponse"},"title":"Recent Videos","type":"array"},"video_count":{"default":0,"title":"Video Count","type":"integer"}},"title":"DashboardSummaryResponse","type":"object"},"DashboardVideoCardResponse":{"additionalProperties":true,"properties":{"approval_status":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Approval Status"},"avatar_face_image":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Avatar Face Image"},"avatar_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Avatar Id"},"avatar_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Avatar Name"},"background_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Background Id"},"completed_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Completed At"},"created_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Created At"},"duration_seconds":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Duration Seconds"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Error Message"},"final_video_file":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Final Video File"},"id":{"title":"Id","type":"integer"},"ig_caption":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Ig Caption"},"original_video_file":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Original Video File"},"raw_video_file":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Raw Video File"},"script_text":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Script Text"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Status"},"text_style":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Text Style"},"thumbnail_file":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Thumbnail File"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Title"}},"required":["id"],"title":"DashboardVideoCardResponse","type":"object"},"DeleteDraftResponse":{"properties":{"ok":{"default":true,"title":"Ok","type":"boolean"}},"title":"DeleteDraftResponse","type":"object"},"DeleteVideoResponse":{"description":"Response payload for `DELETE /api/v1/videos/:id` (plan \u00a76.4).","properties":{"message":{"title":"Message","type":"string"},"success":{"title":"Success","type":"boolean"}},"required":["success","message"],"title":"DeleteVideoResponse","type":"object"},"DiagnosticCheckResponse":{"additionalProperties":true,"description":"Generic response for a single diagnostic check.","properties":{"backend":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Backend"},"configured":{"anyOf":[{"type":"boolean"},{"type":"null"}],"default":null,"title":"Configured"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Error"},"latency_ms":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Latency Ms"},"response":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Response"},"status":{"title":"Status","type":"string"}},"required":["status"],"title":"DiagnosticCheckResponse","type":"object"},"DiscoveredAccountRow":{"description":"One account a Copy From Reel paste surfaced, as the Discovered tab shows it.\n\nShared by both views (2026-09-30). The admin list fills `discovery_count`\n(the Interest column: how many DISTINCT users pasted this creator); a user's\nown list fills `your_reels` (how many of that creator's reels are theirs) and\nleaves `discovery_count` at 0, because how many strangers also pasted a\ncreator is not a user's business.","properties":{"archived":{"default":false,"title":"Archived","type":"boolean"},"bio":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Bio"},"category":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Category"},"category_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Category Id"},"discovered_at":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Discovered At"},"discovered_by_user_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Discovered By User Id"},"discovery_count":{"default":0,"title":"Discovery Count","type":"integer"},"discovery_source":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Discovery Source"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Display Name"},"followers":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Followers"},"id":{"title":"Id","type":"integer"},"is_global":{"default":false,"title":"Is Global","type":"boolean"},"last_scanned_at":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Last Scanned At"},"profile_picture_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Picture Url"},"reels_indexed":{"default":0,"title":"Reels Indexed","type":"integer"},"username":{"title":"Username","type":"string"},"your_reels":{"default":0,"title":"Your Reels","type":"integer"}},"required":["id","username"],"title":"DiscoveredAccountRow","type":"object"},"DiscoveredAccountsResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/DiscoveredAccountRow"},"title":"Items","type":"array"},"ok":{"default":true,"title":"Ok","type":"boolean"}},"title":"DiscoveredAccountsResponse","type":"object"},"DisputePackCounts":{"description":"Totals a dispute response leads with.","properties":{"downloads":{"default":0,"title":"Downloads","type":"integer"},"images_generated":{"default":0,"title":"Images Generated","type":"integer"},"logins":{"default":0,"title":"Logins","type":"integer"},"videos_generated":{"default":0,"title":"Videos Generated","type":"integer"}},"title":"DisputePackCounts","type":"object"},"DisputePackIdentity":{"description":"Who the account is, as of the moment the pack was pulled.","properties":{"created_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Created At"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Display Name"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Email"},"plan_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Plan Slug"},"stripe_customer_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Stripe Customer Id"},"stripe_subscription_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Stripe Subscription Id"},"subscription_status":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Subscription Status"},"user_id":{"title":"User Id","type":"integer"}},"required":["user_id"],"title":"DisputePackIdentity","type":"object"},"DisputePackResponse":{"description":"The full pack: identity, the headline facts, the counts, the trail.","properties":{"checkout":{"anyOf":[{"$ref":"#/components/schemas/EvidenceEventItem"},{"type":"null"}],"default":null},"counts":{"$ref":"#/components/schemas/DisputePackCounts"},"events":{"items":{"$ref":"#/components/schemas/EvidenceEventItem"},"title":"Events","type":"array"},"first_activity":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"First Activity"},"identity":{"$ref":"#/components/schemas/DisputePackIdentity"},"last_activity":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Last Activity"},"terms_accepted":{"anyOf":[{"$ref":"#/components/schemas/EvidenceEventItem"},{"type":"null"}],"default":null}},"required":["identity","counts"],"title":"DisputePackResponse","type":"object"},"DraftBody":{"description":"POST /api/v1/carousels/drafts and PATCH .../drafts/<id>.","properties":{"current_step":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Current Step"},"draft_data":{"additionalProperties":true,"title":"Draft Data","type":"object"}},"title":"DraftBody","type":"object"},"DraftListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/DraftSummary"},"title":"Items","type":"array"}},"title":"DraftListResponse","type":"object"},"DraftResponse":{"properties":{"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Created At"},"current_step":{"title":"Current Step","type":"integer"},"draft_data":{"additionalProperties":true,"title":"Draft Data","type":"object"},"id":{"title":"Id","type":"integer"},"status":{"title":"Status","type":"string"},"updated_at":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Updated At"}},"required":["id","current_step","status"],"title":"DraftResponse","type":"object"},"DraftSummary":{"properties":{"current_step":{"default":1,"title":"Current Step","type":"integer"},"id":{"title":"Id","type":"integer"},"preview":{"default":"","title":"Preview","type":"string"},"status":{"default":"in_progress","title":"Status","type":"string"},"updated_at":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Updated At"}},"required":["id"],"title":"DraftSummary","type":"object"},"DraftsListResponse":{"properties":{"drafts":{"default":[],"items":{"$ref":"#/components/schemas/DraftResponse"},"title":"Drafts","type":"array"}},"title":"DraftsListResponse","type":"object"},"DrillPeopleResponse":{"properties":{"limit":{"title":"Limit","type":"integer"},"meta":{"$ref":"#/components/schemas/ResponseMeta"},"notes":{"items":{"type":"string"},"title":"Notes","type":"array"},"offset":{"title":"Offset","type":"integer"},"people":{"items":{"$ref":"#/components/schemas/Person"},"title":"People","type":"array"},"total":{"title":"Total","type":"integer"},"truncated":{"title":"Truncated","type":"boolean"}},"required":["offset","limit","total","truncated","people","meta"],"title":"DrillPeopleResponse","type":"object"},"DrillResponse":{"properties":{"base":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Base"},"by":{"enum":["country","device","source","medium","campaign","plan","billing","reason"],"title":"By","type":"string"},"env":{"enum":["production","staging","local","test"],"title":"Env","type":"string"},"filters":{"items":{"$ref":"#/components/schemas/FilterEcho"},"title":"Filters","type":"array"},"from":{"format":"date","title":"From","type":"string"},"meta":{"$ref":"#/components/schemas/ResponseMeta"},"mrr_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Mrr Cents"},"notes":{"items":{"type":"string"},"title":"Notes","type":"array"},"page_size":{"title":"Page Size","type":"integer"},"people_total":{"title":"People Total","type":"integer"},"people_truncated":{"title":"People Truncated","type":"boolean"},"rate_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Rate Pct"},"segments":{"items":{"$ref":"#/components/schemas/DrillSegment"},"title":"Segments","type":"array"},"subject":{"$ref":"#/components/schemas/DrillSubject"},"to":{"format":"date","title":"To","type":"string"},"total":{"title":"Total","type":"integer"}},"required":["env","from","to","filters","by","subject","total","base","rate_pct","mrr_cents","segments","people_total","people_truncated","page_size","meta"],"title":"DrillResponse","type":"object"},"DrillSegment":{"properties":{"base":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Base"},"count":{"title":"Count","type":"integer"},"gap_pts":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Gap Pts"},"mrr_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Mrr Cents"},"rate_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Rate Pct"},"share_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Share Pct"},"value":{"title":"Value","type":"string"}},"required":["value","count","base","share_pct","rate_pct","gap_pts","mrr_cents"],"title":"DrillSegment","type":"object"},"DrillSubject":{"properties":{"kind":{"enum":["funnel_dropoff","metric","churn"],"title":"Kind","type":"string"},"metric":{"anyOf":[{"enum":["signups","trials","new_paid"],"type":"string"},{"type":"null"}],"title":"Metric"},"next_step_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Step Id"},"step_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Step Id"},"step_index":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Step Index"},"window_days":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Window Days"}},"required":["kind","metric","step_index","step_id","next_step_id","window_days"],"title":"DrillSubject","type":"object"},"EditDraftDeleteResponse":{"properties":{"deleted":{"title":"Deleted","type":"boolean"}},"required":["deleted"],"title":"EditDraftDeleteResponse","type":"object"},"EditDraftPutRequest":{"description":"Upsert payload for a video's editor draft (debounced autosave).","properties":{"base_updated_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Base Updated At"},"composition_json":{"minLength":2,"title":"Composition Json","type":"string"},"schema_version":{"default":1,"minimum":1.0,"title":"Schema Version","type":"integer"}},"required":["composition_json"],"title":"EditDraftPutRequest","type":"object"},"EditDraftResponse":{"description":"A video's editor draft as the client loads it.","properties":{"composition_json":{"title":"Composition Json","type":"string"},"exported_asset_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Exported Asset Id"},"schema_version":{"title":"Schema Version","type":"integer"},"status":{"title":"Status","type":"string"},"updated_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Updated At"},"video_id":{"title":"Video Id","type":"integer"}},"required":["video_id","composition_json","schema_version","status","exported_asset_id","updated_at"],"title":"EditDraftResponse","type":"object"},"EgressIpResponse":{"additionalProperties":true,"properties":{"country":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Country"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Error"},"ip":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Ip"},"status":{"title":"Status","type":"string"}},"required":["status"],"title":"EgressIpResponse","type":"object"},"EmailChangeConfirmResponse":{"properties":{"email":{"description":"The account's new email address","title":"Email","type":"string"},"ok":{"description":"True when the change was confirmed","title":"Ok","type":"boolean"}},"required":["ok","email"],"title":"EmailChangeConfirmResponse","type":"object"},"EmailChangeStartRequest":{"properties":{"access_token":{"description":"Cognito access token","minLength":1,"title":"Access Token","type":"string"},"new_email":{"maxLength":320,"minLength":3,"title":"New Email","type":"string"}},"required":["access_token","new_email"],"title":"EmailChangeStartRequest","type":"object"},"EmailExistsRequest":{"properties":{"email":{"description":"Email to look up","maxLength":320,"minLength":3,"title":"Email","type":"string"}},"required":["email"],"title":"EmailExistsRequest","type":"object"},"EmailExistsResponse":{"properties":{"exists":{"description":"True if a user row with that email exists locally","title":"Exists","type":"boolean"}},"required":["exists"],"title":"EmailExistsResponse","type":"object"},"EntitlementsResponse":{"properties":{"active_avatar_count":{"default":0,"title":"Active Avatar Count","type":"integer"},"can_create_avatar":{"default":false,"title":"Can Create Avatar","type":"boolean"},"can_generate_video":{"default":false,"title":"Can Generate Video","type":"boolean"},"followed_accounts":{"default":false,"title":"Followed Accounts","type":"boolean"},"max_active_avatars":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Max Active Avatars"},"max_video_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Max Video Seconds"},"outperformers":{"default":false,"title":"Outperformers","type":"boolean"},"reel_analytics":{"default":false,"title":"Reel Analytics","type":"boolean"},"viral_radar_limit":{"default":0,"title":"Viral Radar Limit","type":"integer"}},"title":"EntitlementsResponse","type":"object"},"EnvCheckResponse":{"additionalProperties":true,"properties":{"missing_recommended":{"items":{"type":"string"},"title":"Missing Recommended","type":"array"},"missing_required":{"items":{"type":"string"},"title":"Missing Required","type":"array"},"status":{"title":"Status","type":"string"}},"required":["status"],"title":"EnvCheckResponse","type":"object"},"ErrorResponse":{"properties":{"code":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Code"},"error":{"title":"Error","type":"string"}},"required":["error"],"title":"ErrorResponse","type":"object"},"EvidenceEventItem":{"description":"One row of the trail as the dispute pack renders it.","properties":{"accept_language":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Accept Language"},"amount_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Amount Cents"},"client_context":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"title":"Client Context"},"currency":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Currency"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Email"},"event":{"title":"Event","type":"string"},"id":{"title":"Id","type":"integer"},"ip":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Ip"},"ip_city":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Ip City"},"ip_country":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Ip Country"},"ip_region":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Ip Region"},"meta":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"title":"Meta"},"occurred_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Occurred At"},"referer":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Referer"},"request_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Request Id"},"resource":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Resource"},"stripe_customer_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Stripe Customer Id"},"stripe_payment_intent_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Stripe Payment Intent Id"},"stripe_subscription_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Stripe Subscription Id"},"terms_version":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Terms Version"},"user_agent":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"User Agent"}},"required":["id","event"],"title":"EvidenceEventItem","type":"object"},"ExpandStoryRequest":{"properties":{"avatar_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Avatar Id"},"story":{"default":"","title":"Story","type":"string"}},"title":"ExpandStoryRequest","type":"object"},"ExpandStoryResponse":{"properties":{"expanded":{"default":"","title":"Expanded","type":"string"}},"title":"ExpandStoryResponse","type":"object"},"ExportPayloadResponse":{"additionalProperties":true,"properties":{},"title":"ExportPayloadResponse","type":"object"},"ExportResponse":{"description":"The persisted edited cut.","properties":{"asset_id":{"title":"Asset Id","type":"integer"},"duration_seconds":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Duration Seconds"},"file_size_bytes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"File Size Bytes"},"label":{"title":"Label","type":"string"},"video_filename":{"title":"Video Filename","type":"string"}},"required":["asset_id","video_filename","label","duration_seconds","file_size_bytes"],"title":"ExportResponse","type":"object"},"ExportRow":{"properties":{"admin_user_id":{"title":"Admin User Id","type":"integer"},"at":{"format":"date-time","title":"At","type":"string"},"id":{"title":"Id","type":"integer"},"kind":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kind"},"params":{"additionalProperties":true,"title":"Params","type":"object"},"row_count":{"title":"Row Count","type":"integer"},"truncated":{"title":"Truncated","type":"boolean"}},"required":["id","at","admin_user_id","kind","row_count","truncated","params"],"title":"ExportRow","type":"object"},"ExportsResponse":{"properties":{"exports":{"items":{"$ref":"#/components/schemas/ExportRow"},"title":"Exports","type":"array"},"meta":{"$ref":"#/components/schemas/ResponseMeta"}},"required":["exports","meta"],"title":"ExportsResponse","type":"object"},"ExtractBody":{"properties":{"force":{"default":false,"title":"Force","type":"boolean"},"level":{"default":"transcript","title":"Level","type":"string"},"url":{"default":"","title":"Url","type":"string"}},"title":"ExtractBody","type":"object"},"FaceFocusPoint":{"description":"Where a square or circular crop of a face image has to look.\n\nPercentages of the FULL stored frame, so the SPA can hand them\nstraight to a CSS ``object-position``. Written by\n``app.modules.avatars.face_focus``; absent (``None``) when no face\nwas detected, and the shared `AvatarFace` component then falls back\nto its upper-third default.","properties":{"x":{"title":"X","type":"number"},"y":{"title":"Y","type":"number"}},"required":["x","y"],"title":"FaceFocusPoint","type":"object"},"FailureItem":{"description":"One logged failure, as served to the admin dashboard.","properties":{"attempts":{"title":"Attempts","type":"integer"},"created_at":{"format":"date-time","title":"Created At","type":"string"},"error":{"title":"Error","type":"string"},"id":{"title":"Id","type":"integer"},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Model"},"operation_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Operation Ref"},"prompt_text":{"title":"Prompt Text","type":"string"},"surface":{"title":"Surface","type":"string"},"user_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"User Id"}},"required":["id","created_at","surface","prompt_text","error","attempts"],"title":"FailureItem","type":"object"},"FailureListResponse":{"description":"Paged failure listing plus the filter vocabularies.","properties":{"items":{"items":{"$ref":"#/components/schemas/FailureItem"},"title":"Items","type":"array"},"models":{"items":{"type":"string"},"title":"Models","type":"array"},"page":{"minimum":1.0,"title":"Page","type":"integer"},"page_size":{"minimum":1.0,"title":"Page Size","type":"integer"},"surfaces":{"items":{"type":"string"},"title":"Surfaces","type":"array"},"total":{"title":"Total","type":"integer"}},"required":["items","total","page","page_size","surfaces","models"],"title":"FailureListResponse","type":"object"},"FavoritesListResponse":{"properties":{"kind":{"title":"Kind","type":"string"},"ref_ids":{"items":{"type":"integer"},"title":"Ref Ids","type":"array"}},"required":["kind"],"title":"FavoritesListResponse","type":"object"},"FilterEcho":{"properties":{"dimension":{"title":"Dimension","type":"string"},"op":{"enum":["is","not"],"title":"Op","type":"string"},"values":{"items":{"type":"string"},"title":"Values","type":"array"}},"required":["dimension","op","values"],"title":"FilterEcho","type":"object"},"FilterValue":{"properties":{"count":{"title":"Count","type":"integer"},"value":{"title":"Value","type":"string"}},"required":["value","count"],"title":"FilterValue","type":"object"},"FilterValuesResponse":{"properties":{"count_unit":{"enum":["customers","signups","visits"],"title":"Count Unit","type":"string"},"dimension":{"enum":["plan","billing","country","device","source","medium","campaign"],"title":"Dimension","type":"string"},"from":{"format":"date","title":"From","type":"string"},"meta":{"$ref":"#/components/schemas/ResponseMeta"},"to":{"format":"date","title":"To","type":"string"},"total_values":{"title":"Total Values","type":"integer"},"truncated":{"title":"Truncated","type":"boolean"},"values":{"items":{"$ref":"#/components/schemas/FilterValue"},"title":"Values","type":"array"}},"required":["dimension","count_unit","from","to","values","total_values","truncated","meta"],"title":"FilterValuesResponse","type":"object"},"FinalizeCheckoutRequest":{"description":"Body for `POST /api/v1/billing/checkout/finalize`.","properties":{"intent_id":{"title":"Intent Id","type":"string"},"interval":{"default":"monthly","title":"Interval","type":"string"},"mode":{"default":"payment","title":"Mode","type":"string"},"plan":{"title":"Plan","type":"string"},"promotion_code":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Promotion Code"},"source":{"anyOf":[{"const":"ads_funnel","type":"string"},{"type":"null"}],"default":null,"title":"Source"},"terms_accepted":{"default":false,"title":"Terms Accepted","type":"boolean"}},"required":["intent_id","plan"],"title":"FinalizeCheckoutRequest","type":"object"},"FollowedAccountListItem":{"additionalProperties":true,"properties":{"account_kind":{"default":"ai","title":"Account Kind","type":"string"},"account_status":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Account Status"},"archive_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Archive Reason"},"archived":{"default":0,"title":"Archived","type":"integer"},"bio":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Bio"},"categories":{"items":{"additionalProperties":true,"type":"object"},"title":"Categories","type":"array"},"category":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"title":"Category"},"category_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Category Id"},"channel":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Channel"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Created At"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Display Name"},"followers":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Followers"},"following":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Following"},"growth_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Growth Pct"},"id":{"title":"Id","type":"integer"},"is_favorite":{"default":false,"title":"Is Favorite","type":"boolean"},"is_global":{"default":false,"title":"Is Global","type":"boolean"},"is_shared":{"default":false,"title":"Is Shared","type":"boolean"},"last_posted_at":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Last Posted At"},"last_scan_attempt_at":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Last Scan Attempt At"},"last_scan_depth":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Last Scan Depth"},"last_scan_error":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Last Scan Error"},"last_scanned_at":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Last Scanned At"},"next_scan_at":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Next Scan At"},"posts_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Posts Count"},"profile_picture_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Picture Url"},"scan_cadence":{"default":"active","title":"Scan Cadence","type":"string"},"script_count":{"default":0,"title":"Script Count","type":"integer"},"tags":{"items":{"type":"string"},"title":"Tags","type":"array"},"total_scraped":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Total Scraped"},"username":{"title":"Username","type":"string"}},"required":["id","username"],"title":"FollowedAccountListItem","type":"object"},"FollowedAccountsCategory":{"properties":{"color":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Color"},"id":{"title":"Id","type":"integer"},"name":{"title":"Name","type":"string"},"scene_categories":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Scene Categories"}},"required":["id","name"],"title":"FollowedAccountsCategory","type":"object"},"FollowedAccountsListResponse":{"properties":{"archived_count":{"default":0,"title":"Archived Count","type":"integer"},"cat_counts":{"additionalProperties":{"type":"integer"},"title":"Cat Counts","type":"object"},"categories":{"items":{"$ref":"#/components/schemas/FollowedAccountsCategory"},"title":"Categories","type":"array"},"items":{"items":{"$ref":"#/components/schemas/FollowedAccountListItem"},"title":"Items","type":"array"},"reels_indexed_total":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Reels Indexed Total"},"total_accounts":{"default":0,"title":"Total Accounts","type":"integer"},"total_categories":{"default":0,"title":"Total Categories","type":"integer"},"uncategorized_count":{"default":0,"title":"Uncategorized Count","type":"integer"},"viewer_is_admin":{"default":false,"title":"Viewer Is Admin","type":"boolean"},"viral_radar":{"anyOf":[{"$ref":"#/components/schemas/ViralRadarUsage"},{"type":"null"}],"default":null}},"required":["items","categories"],"title":"FollowedAccountsListResponse","type":"object"},"FreeQuotaResponse":{"description":"Free-tier allowance (null counts mean unlimited: a paid user).\n\nCarries both used and remaining so the MCP connector can report, after a\nconsuming call, exactly what was spent and what is left.","properties":{"images_remaining":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Images Remaining"},"images_used":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Images Used"},"is_free":{"title":"Is Free","type":"boolean"},"scripts_remaining":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Scripts Remaining"},"scripts_used":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Scripts Used"}},"required":["is_free"],"title":"FreeQuotaResponse","type":"object"},"FreshnessResponse":{"properties":{"env":{"enum":["production","staging","local","test"],"title":"Env","type":"string"},"generated_at":{"format":"date-time","title":"Generated At","type":"string"},"is_stale":{"title":"Is Stale","type":"boolean"},"last_run":{"anyOf":[{"$ref":"#/components/schemas/LastRun"},{"type":"null"}]},"meta":{"$ref":"#/components/schemas/ResponseMeta"},"models":{"items":{"$ref":"#/components/schemas/ModelFreshness"},"title":"Models","type":"array"}},"required":["env","generated_at","is_stale","last_run","models","meta"],"title":"FreshnessResponse","type":"object"},"FreshnessSummary":{"properties":{"is_mrr_carried":{"title":"Is Mrr Carried","type":"boolean"},"is_stale":{"title":"Is Stale","type":"boolean"},"last_success_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Last Success At"},"subscription_state_day":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"title":"Subscription State Day"}},"required":["is_stale","last_success_at","subscription_state_day","is_mrr_carried"],"title":"FreshnessSummary","type":"object"},"FunnelMeta":{"properties":{"definition":{"title":"Definition","type":"string"},"tz":{"title":"Tz","type":"string"},"tz_applied":{"default":true,"title":"Tz Applied","type":"boolean"}},"required":["tz","definition"],"title":"FunnelMeta","type":"object"},"FunnelResponse":{"properties":{"breakdown":{"enum":["none","device","country","source","plan"],"title":"Breakdown","type":"string"},"compare":{"enum":["previous","yoy","none"],"title":"Compare","type":"string"},"compare_from":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"title":"Compare From"},"compare_to":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"title":"Compare To"},"currency":{"const":"USD","default":"USD","title":"Currency","type":"string"},"env":{"enum":["production","staging","local","test"],"title":"Env","type":"string"},"estimated_before":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"title":"Estimated Before"},"filters":{"items":{"$ref":"#/components/schemas/FilterEcho"},"title":"Filters","type":"array"},"freshness":{"$ref":"#/components/schemas/FreshnessSummary"},"from":{"format":"date","title":"From","type":"string"},"granularity":{"enum":["day","week","month"],"title":"Granularity","type":"string"},"meta":{"$ref":"#/components/schemas/FunnelMeta"},"notes":{"items":{"type":"string"},"title":"Notes","type":"array"},"segments":{"items":{"$ref":"#/components/schemas/FunnelSegment"},"title":"Segments","type":"array"},"steps":{"items":{"$ref":"#/components/schemas/FunnelStepResult"},"title":"Steps","type":"array"},"steps_requested":{"items":{"type":"string"},"title":"Steps Requested","type":"array"},"summary":{"$ref":"#/components/schemas/FunnelSummary"},"to":{"format":"date","title":"To","type":"string"},"window_days":{"title":"Window Days","type":"integer"}},"required":["env","from","to","granularity","compare","compare_from","compare_to","freshness","meta","steps_requested","window_days","breakdown","summary","steps","segments"],"title":"FunnelResponse","type":"object"},"FunnelSegment":{"properties":{"is_other":{"title":"Is Other","type":"boolean"},"steps":{"items":{"$ref":"#/components/schemas/FunnelStepResult"},"title":"Steps","type":"array"},"value":{"title":"Value","type":"string"}},"required":["value","is_other","steps"],"title":"FunnelSegment","type":"object"},"FunnelStep":{"properties":{"conversion_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Conversion Pct"},"count":{"$ref":"#/components/schemas/KpiValue"},"step":{"enum":["visit","signup","trial","paid"],"title":"Step","type":"string"}},"required":["step","count","conversion_pct"],"title":"FunnelStep","type":"object"},"FunnelStepCount":{"properties":{"count":{"title":"Count","type":"integer"},"label":{"title":"Label","type":"string"},"step_id":{"title":"Step Id","type":"string"}},"required":["step_id","label","count"],"title":"FunnelStepCount","type":"object"},"FunnelStepGroup":{"properties":{"group":{"enum":["acquisition","product","billing"],"title":"Group","type":"string"},"steps":{"items":{"$ref":"#/components/schemas/FunnelStepCount"},"title":"Steps","type":"array"}},"required":["group","steps"],"title":"FunnelStepGroup","type":"object"},"FunnelStepResult":{"properties":{"count":{"title":"Count","type":"integer"},"dropped":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Dropped"},"index":{"title":"Index","type":"integer"},"label":{"title":"Label","type":"string"},"median_seconds_from_previous":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Median Seconds From Previous"},"pct_of_first":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Pct Of First"},"pct_of_previous":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Pct Of Previous"},"step_id":{"title":"Step Id","type":"string"}},"required":["index","step_id","label","count","pct_of_first","pct_of_previous","dropped","median_seconds_from_previous"],"title":"FunnelStepResult","type":"object"},"FunnelStepsResponse":{"properties":{"filters":{"items":{"$ref":"#/components/schemas/FilterEcho"},"title":"Filters","type":"array"},"from":{"format":"date","title":"From","type":"string"},"groups":{"items":{"$ref":"#/components/schemas/FunnelStepGroup"},"title":"Groups","type":"array"},"meta":{"$ref":"#/components/schemas/ResponseMeta"},"notes":{"items":{"type":"string"},"title":"Notes","type":"array"},"to":{"format":"date","title":"To","type":"string"}},"required":["from","to","filters","groups","notes","meta"],"title":"FunnelStepsResponse","type":"object"},"FunnelSummary":{"properties":{"first_to_last_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"First To Last Pct"},"signups":{"title":"Signups","type":"integer"},"visit_to_signup_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Visit To Signup Pct"},"visits":{"title":"Visits","type":"integer"}},"required":["visits","signups","visit_to_signup_pct","first_to_last_pct"],"title":"FunnelSummary","type":"object"},"FunnelView":{"description":"Clicks to signups to trials to paying, for the range. Same numbers as\n`totals`, carried separately so the funnel component takes one object.","properties":{"clicks":{"default":0,"title":"Clicks","type":"integer"},"paying":{"default":0,"title":"Paying","type":"integer"},"signups":{"default":0,"title":"Signups","type":"integer"},"trials":{"default":0,"title":"Trials","type":"integer"}},"title":"FunnelView","type":"object"},"GalleryAvatar":{"properties":{"face_focus":{"anyOf":[{"$ref":"#/components/schemas/FaceFocusPoint"},{"type":"null"}],"default":null},"face_image":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Face Image"},"id":{"title":"Id","type":"integer"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Name"}},"required":["id"],"title":"GalleryAvatar","type":"object"},"GalleryBackground":{"properties":{"id":{"title":"Id","type":"integer"},"image_file":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Image File"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Name"}},"required":["id"],"title":"GalleryBackground","type":"object"},"GalleryVideoCard":{"additionalProperties":true,"properties":{"approval_status":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Approval Status"},"avatar":{"anyOf":[{"$ref":"#/components/schemas/GalleryAvatar"},{"type":"null"}],"default":null},"avatar_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Avatar Id"},"background":{"anyOf":[{"$ref":"#/components/schemas/GalleryBackground"},{"type":"null"}],"default":null},"background_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Background Id"},"completed_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Completed At"},"created_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Created At"},"duration_seconds":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Duration Seconds"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Error Message"},"final_video_file":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Final Video File"},"has_post":{"default":false,"title":"Has Post","type":"boolean"},"id":{"title":"Id","type":"integer"},"ig_account_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Ig Account Name"},"is_ig_avatar":{"default":false,"title":"Is Ig Avatar","type":"boolean"},"original_video_file":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Original Video File"},"post_status":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Post Status"},"progress_label":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Progress Label"},"raw_video_file":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Raw Video File"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Status"},"text_style":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Text Style"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Title"}},"required":["id"],"title":"GalleryVideoCard","type":"object"},"GeminiConfigResponse":{"properties":{"creds_json_length":{"title":"Creds Json Length","type":"integer"},"creds_path_set":{"title":"Creds Path Set","type":"boolean"},"gemini_configured":{"title":"Gemini Configured","type":"boolean"},"project_len":{"title":"Project Len","type":"integer"},"project_set":{"title":"Project Set","type":"boolean"}},"required":["gemini_configured","project_set","project_len","creds_json_length","creds_path_set"],"title":"GeminiConfigResponse","type":"object"},"GenerateBackgroundRequest":{"properties":{"category":{"default":"custom","title":"Category","type":"string"},"prompt":{"title":"Prompt","type":"string"}},"required":["prompt"],"title":"GenerateBackgroundRequest","type":"object"},"GenerateBackgroundResponse":{"properties":{"filename":{"title":"Filename","type":"string"},"name":{"title":"Name","type":"string"},"success":{"title":"Success","type":"boolean"}},"required":["success","name","filename"],"title":"GenerateBackgroundResponse","type":"object"},"GenerateCaptionResponse":{"properties":{"caption":{"title":"Caption","type":"string"},"success":{"title":"Success","type":"boolean"}},"required":["success","caption"],"title":"GenerateCaptionResponse","type":"object"},"GenerateFaceRequest":{"properties":{"age":{"default":"","title":"Age","type":"string"},"avatar_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Avatar Id"},"description":{"default":"","title":"Description","type":"string"},"gender":{"default":"","title":"Gender","type":"string"},"name":{"default":"","title":"Name","type":"string"},"origin":{"default":"","title":"Origin","type":"string"},"outfit":{"default":"","title":"Outfit","type":"string"},"religion":{"default":"","title":"Religion","type":"string"}},"title":"GenerateFaceRequest","type":"object"},"GenerateFaceResponse":{"properties":{"face_image":{"default":"","title":"Face Image","type":"string"},"image_url":{"default":"","title":"Image Url","type":"string"}},"title":"GenerateFaceResponse","type":"object"},"GenerateOutfitRequest":{"description":"`POST /avatars/<id>/outfits`: describe the clothes; the drawer's composer adds\nreference images through the scene routes; this JSON lane is text only, or notes on\nthe avatar's current outfit when ``use_current_outfit`` is set.","properties":{"image_model":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Image Model"},"prompt":{"default":"","title":"Prompt","type":"string"},"use_current_outfit":{"default":false,"title":"Use Current Outfit","type":"boolean"}},"title":"GenerateOutfitRequest","type":"object"},"GenerateScriptBody":{"properties":{"avatar_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Avatar Id"},"length_seconds":{"default":45,"title":"Length Seconds","type":"integer"},"pillar_name":{"default":"","title":"Pillar Name","type":"string"},"topic":{"default":"","title":"Topic","type":"string"}},"title":"GenerateScriptBody","type":"object"},"GenerateThumbnailResponse":{"description":"Response for `POST /api/v1/videos/:id/generate-thumbnail`. Returns the\nstored `faces/<filename>` key of the freshly generated cover image.","properties":{"success":{"title":"Success","type":"boolean"},"thumbnail_file":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Thumbnail File"}},"required":["success"],"title":"GenerateThumbnailResponse","type":"object"},"GuestAddonResponse":{"properties":{"influencer_addon":{"title":"Influencer Addon","type":"boolean"},"status":{"title":"Status","type":"string"}},"required":["status","influencer_addon"],"title":"GuestAddonResponse","type":"object"},"GuestCheckoutRequest":{"properties":{"checkout_id":{"anyOf":[{"maxLength":32,"type":"string"},{"type":"null"}],"default":null,"title":"Checkout Id"},"claim_token":{"anyOf":[{"maxLength":128,"type":"string"},{"type":"null"}],"default":null,"title":"Claim Token"},"email":{"maxLength":320,"title":"Email","type":"string"},"name":{"default":"","maxLength":200,"title":"Name","type":"string"},"plan":{"maxLength":32,"title":"Plan","type":"string"},"prefill":{"anyOf":[{"maxLength":2048,"type":"string"},{"type":"null"}],"default":null,"title":"Prefill"},"ref":{"anyOf":[{"maxLength":64,"type":"string"},{"type":"null"}],"default":null,"title":"Ref"}},"required":["plan","email"],"title":"GuestCheckoutRequest","type":"object"},"GuestCheckoutResponse":{"properties":{"account":{"title":"Account","type":"string"},"amount":{"title":"Amount","type":"integer"},"checkout_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Checkout Id"},"claim_token":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Claim Token"},"client_secret":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Client Secret"},"currency":{"title":"Currency","type":"string"},"email":{"title":"Email","type":"string"},"plan_slug":{"title":"Plan Slug","type":"string"},"publishable_key":{"title":"Publishable Key","type":"string"},"sign_in":{"items":{"type":"string"},"title":"Sign In","type":"array"},"status":{"title":"Status","type":"string"}},"required":["status","amount","currency","plan_slug","email","account","sign_in","publishable_key"],"title":"GuestCheckoutResponse","type":"object"},"GuestClaimRequest":{"properties":{"checkout_id":{"maxLength":32,"title":"Checkout Id","type":"string"},"claim_token":{"maxLength":128,"minLength":10,"title":"Claim Token","type":"string"}},"required":["checkout_id","claim_token"],"title":"GuestClaimRequest","type":"object"},"GuestClaimResponse":{"properties":{"avatar_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Avatar Id"},"email_mismatch":{"title":"Email Mismatch","type":"boolean"},"plan_slug":{"title":"Plan Slug","type":"string"},"prefill":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Prefill"},"status":{"title":"Status","type":"string"}},"required":["status","plan_slug","email_mismatch"],"title":"GuestClaimResponse","type":"object"},"GuestConfirmRequest":{"properties":{"claim_token":{"anyOf":[{"maxLength":128,"type":"string"},{"type":"null"}],"default":null,"title":"Claim Token"}},"title":"GuestConfirmRequest","type":"object"},"GuestPrefillResponse":{"properties":{"avatar_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Avatar Id"},"prefill":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Prefill"}},"title":"GuestPrefillResponse","type":"object"},"GuestResendRequest":{"properties":{"email":{"maxLength":320,"title":"Email","type":"string"}},"required":["email"],"title":"GuestResendRequest","type":"object"},"GuestResendResponse":{"properties":{"ok":{"title":"Ok","type":"boolean"}},"required":["ok"],"title":"GuestResendResponse","type":"object"},"GuestStatusResponse":{"properties":{"account":{"title":"Account","type":"string"},"amount_paid":{"title":"Amount Paid","type":"integer"},"attached":{"title":"Attached","type":"boolean"},"checkout_id":{"title":"Checkout Id","type":"string"},"email":{"title":"Email","type":"string"},"has_account":{"title":"Has Account","type":"boolean"},"influencer_addon":{"default":false,"title":"Influencer Addon","type":"boolean"},"name":{"title":"Name","type":"string"},"payment":{"title":"Payment","type":"string"},"plan_slug":{"title":"Plan Slug","type":"string"},"prefill":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Prefill"},"sign_in":{"items":{"type":"string"},"title":"Sign In","type":"array"},"status":{"title":"Status","type":"string"}},"required":["status","checkout_id","email","name","plan_slug","has_account","account","attached","sign_in","payment","amount_paid"],"title":"GuestStatusResponse","type":"object"},"GuestTokenRequest":{"properties":{"claim_token":{"maxLength":128,"minLength":10,"title":"Claim Token","type":"string"}},"required":["claim_token"],"title":"GuestTokenRequest","type":"object"},"GuideFaq":{"properties":{"a":{"title":"A","type":"string"},"q":{"title":"Q","type":"string"}},"required":["q","a"],"title":"GuideFaq","type":"object"},"GuideListResponse":{"properties":{"guides":{"items":{"$ref":"#/components/schemas/GuideResponse"},"title":"Guides","type":"array"}},"required":["guides"],"title":"GuideListResponse","type":"object"},"GuidePublicItem":{"description":"Build-facing payload; aliases match the zod field names 1:1.","properties":{"author":{"title":"Author","type":"string"},"bodyMarkdown":{"title":"Bodymarkdown","type":"string"},"canonicalTo":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Canonicalto"},"description":{"title":"Description","type":"string"},"faqs":{"items":{"$ref":"#/components/schemas/GuideFaq"},"title":"Faqs","type":"array"},"featured":{"title":"Featured","type":"boolean"},"headline":{"title":"Headline","type":"string"},"heroAlt":{"title":"Heroalt","type":"string"},"heroImage":{"title":"Heroimage","type":"string"},"noindex":{"title":"Noindex","type":"boolean"},"ogImage":{"title":"Ogimage","type":"string"},"pillar":{"title":"Pillar","type":"string"},"popularRank":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Popularrank"},"publishDate":{"format":"date","title":"Publishdate","type":"string"},"quotableAnswer":{"title":"Quotableanswer","type":"string"},"related":{"items":{"type":"string"},"title":"Related","type":"array"},"section":{"title":"Section","type":"string"},"slug":{"title":"Slug","type":"string"},"stat":{"title":"Stat","type":"string"},"title":{"title":"Title","type":"string"},"updatedDate":{"format":"date","title":"Updateddate","type":"string"}},"required":["slug","title","description","headline","pillar","author","heroImage","heroAlt","ogImage","publishDate","updatedDate","quotableAnswer","stat","faqs","related","bodyMarkdown","section","featured","noindex"],"title":"GuidePublicItem","type":"object"},"GuidePublicListResponse":{"properties":{"drafts":{"default":[],"items":{"$ref":"#/components/schemas/PublicDraftItem"},"title":"Drafts","type":"array"},"guides":{"items":{"$ref":"#/components/schemas/GuidePublicItem"},"title":"Guides","type":"array"}},"required":["guides"],"title":"GuidePublicListResponse","type":"object"},"GuideResponse":{"description":"Admin-facing row view (snake_case, includes status).","properties":{"author":{"title":"Author","type":"string"},"body_markdown":{"title":"Body Markdown","type":"string"},"canonical_to":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Canonical To"},"description":{"title":"Description","type":"string"},"faqs":{"items":{"$ref":"#/components/schemas/GuideFaq"},"title":"Faqs","type":"array"},"featured":{"title":"Featured","type":"boolean"},"headline":{"title":"Headline","type":"string"},"hero_alt":{"title":"Hero Alt","type":"string"},"hero_image":{"title":"Hero Image","type":"string"},"id":{"title":"Id","type":"integer"},"noindex":{"title":"Noindex","type":"boolean"},"og_image":{"title":"Og Image","type":"string"},"pillar":{"title":"Pillar","type":"string"},"popular_rank":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Popular Rank"},"preview_token":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Preview Token"},"publish_date":{"format":"date","title":"Publish Date","type":"string"},"quotable_answer":{"title":"Quotable Answer","type":"string"},"related":{"items":{"type":"string"},"title":"Related","type":"array"},"section":{"title":"Section","type":"string"},"slug":{"title":"Slug","type":"string"},"stat":{"title":"Stat","type":"string"},"status":{"title":"Status","type":"string"},"title":{"title":"Title","type":"string"},"updated_date":{"format":"date","title":"Updated Date","type":"string"}},"required":["id","slug","title","description","headline","pillar","author","hero_image","hero_alt","og_image","publish_date","updated_date","quotable_answer","stat","faqs","related","body_markdown","section","featured","noindex","status"],"title":"GuideResponse","type":"object"},"GuideUpsertRequest":{"properties":{"author":{"default":"AvatarFactory Team","title":"Author","type":"string"},"body_markdown":{"title":"Body Markdown","type":"string"},"canonical_to":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Canonical To"},"description":{"title":"Description","type":"string"},"faqs":{"items":{"$ref":"#/components/schemas/GuideFaq"},"minItems":3,"title":"Faqs","type":"array"},"featured":{"default":false,"title":"Featured","type":"boolean"},"headline":{"title":"Headline","type":"string"},"hero_alt":{"title":"Hero Alt","type":"string"},"hero_image":{"title":"Hero Image","type":"string"},"noindex":{"default":false,"title":"Noindex","type":"boolean"},"og_image":{"title":"Og Image","type":"string"},"pillar":{"default":"money","title":"Pillar","type":"string"},"popular_rank":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Popular Rank"},"publish_date":{"format":"date","title":"Publish Date","type":"string"},"quotable_answer":{"title":"Quotable Answer","type":"string"},"related":{"default":[],"items":{"type":"string"},"title":"Related","type":"array"},"section":{"default":"money","title":"Section","type":"string"},"slug":{"title":"Slug","type":"string"},"stat":{"title":"Stat","type":"string"},"title":{"title":"Title","type":"string"},"updated_date":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"title":"Updated Date"}},"required":["slug","title","description","headline","hero_image","hero_alt","og_image","publish_date","quotable_answer","stat","faqs","body_markdown"],"title":"GuideUpsertRequest","type":"object"},"HistoryItem":{"properties":{"created_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Created At"},"duration":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Duration"},"extraction_level":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Extraction Level"},"id":{"title":"Id","type":"integer"},"script":{"title":"Script","type":"string"},"source_url":{"title":"Source Url","type":"string"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Status"},"thumb_frame":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Thumb Frame"},"word_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Word Count"}},"required":["id","source_url","script"],"title":"HistoryItem","type":"object"},"HistoryListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/HistoryItem"},"title":"Items","type":"array"}},"required":["items"],"title":"HistoryListResponse","type":"object"},"HooksRequest":{"properties":{"niche":{"default":"","title":"Niche","type":"string"},"topic":{"default":"","title":"Topic","type":"string"}},"title":"HooksRequest","type":"object"},"HooksResponse":{"properties":{"hooks":{"default":[],"items":{"type":"string"},"title":"Hooks","type":"array"}},"title":"HooksResponse","type":"object"},"IdeationAccountRow":{"properties":{"count":{"title":"Count","type":"integer"},"username":{"title":"Username","type":"string"}},"required":["username","count"],"title":"IdeationAccountRow","type":"object"},"IdeationDashboardResponse":{"properties":{"accounts":{"items":{"$ref":"#/components/schemas/IdeationAccountRow"},"title":"Accounts","type":"array"},"avatars":{"items":{"$ref":"#/components/schemas/AvatarOption"},"title":"Avatars","type":"array"},"avg_views":{"title":"Avg Views","type":"integer"},"scripts":{"items":{"$ref":"#/components/schemas/ScriptCard"},"title":"Scripts","type":"array"},"total_scripts":{"title":"Total Scripts","type":"integer"},"tracked":{"items":{"$ref":"#/components/schemas/TrackedAccountRow"},"title":"Tracked","type":"array"}},"required":["scripts","accounts","avatars","tracked","total_scripts","avg_views"],"title":"IdeationDashboardResponse","type":"object"},"IdentitySummaryModel":{"properties":{"email_at_provider":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Email At Provider"},"linked_at":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Linked At"},"provider":{"title":"Provider","type":"string"},"provider_sub":{"title":"Provider Sub","type":"string"}},"required":["provider","provider_sub"],"title":"IdentitySummaryModel","type":"object"},"ImpersonatedIdentity":{"description":"Who the caller is currently viewing as (spec \u00a73.6).\n\nMirrors the identity fields the SPA banner renders; the id is\nalready exposed as the response's `user_id` (the swap makes the\ntarget the request's current user).","properties":{"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Display Name"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Email"}},"title":"ImpersonatedIdentity","type":"object"},"ImpersonationStartRequest":{"properties":{"email":{"description":"Email of the user to view","minLength":1,"title":"Email","type":"string"}},"required":["email"],"title":"ImpersonationStartRequest","type":"object"},"ImpersonationStartResponse":{"properties":{"token":{"description":"Signed grant for the X-Impersonation-Grant header","title":"Token","type":"string"},"user":{"$ref":"#/components/schemas/AdminUserView"}},"required":["token","user"],"title":"ImpersonationStartResponse","type":"object"},"IndustrySlug":{"description":"The wire value. Anything outside this set is a 422.","enum":["dental","travel","legal","real-estate","med-spa","hotels","gyms","financial-advisors","ecommerce","restaurants","beauty","coaches","other"],"title":"IndustrySlug","type":"string"},"InfluencerAddonResponse":{"properties":{"status":{"title":"Status","type":"string"},"subscription":{"$ref":"#/components/schemas/SubscriptionStatusResponse"}},"required":["status","subscription"],"title":"InfluencerAddonResponse","type":"object"},"InfluencerConfigItem":{"description":"Build-facing payload: order and visibility, nothing else.\n\nThis response is anonymous, so the regen flag and note (internal\nnotes about a portrait) never appear here.\n\nBoth fields are nullable and both nulls mean different things, which\nthe Astro loader mirrors exactly:\n\n  - `railPriority: null` is an explicit unpin, it CLEARS a\n    railPriority set in the YAML\n  - `hideFromRail: null` is \"no override\", the YAML hideFromRail\n    stands. The key is always present and carries null rather than\n    being omitted, so a missing key and a null read the same.","properties":{"hideFromRail":{"anyOf":[{"type":"boolean"},{"type":"null"}],"default":null,"title":"Hidefromrail"},"railPriority":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Railpriority"},"slug":{"title":"Slug","type":"string"}},"required":["slug"],"title":"InfluencerConfigItem","type":"object"},"IngestBody":{"description":"Body for the canonical queued-ingest endpoint.\n\nPhase 2B (2026-05-25). The Copy From Reel page POSTs a URL here;\nthe row is created with status='queued' and the worker picks it up\nasynchronously. `level` (2026-07-10, Clone-a-Reel) picks the\nextraction tier; 'replica' adds the per-shot source breakdown.","properties":{"level":{"default":"scene","title":"Level","type":"string"},"url":{"default":"","title":"Url","type":"string"}},"title":"IngestBody","type":"object"},"IngestDetail":{"description":"Full record for one ingest, including the replica breakdown.\n\n`replica_breakdown` is the parsed JSON blob (shot list with resolved\nsource-frame URLs) or a small {\"error\": ...} payload naming why the\nreplica analysis degraded, so the client can alert the user instead\nof failing silently.","properties":{"copy_error":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Copy Error"},"copy_ready":{"default":false,"title":"Copy Ready","type":"boolean"},"copy_status":{"default":"pending","title":"Copy Status","type":"string"},"created_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Created At"},"credit_cost":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Credit Cost"},"duration":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Duration"},"extraction_level":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Extraction Level"},"id":{"title":"Id","type":"integer"},"people":{"default":null,"title":"People"},"replica_breakdown":{"default":null,"title":"Replica Breakdown"},"script":{"title":"Script","type":"string"},"shots_status":{"default":"none","title":"Shots Status","type":"string"},"sound_admin":{"default":null,"title":"Sound Admin"},"sound_kind":{"default":"speech","title":"Sound Kind","type":"string"},"source_seconds":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Source Seconds"},"source_url":{"title":"Source Url","type":"string"},"source_video_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Source Video Url"},"speech_turns":{"default":null,"title":"Speech Turns"},"speech_voices":{"default":null,"title":"Speech Voices"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Status"},"subtitles_present":{"default":false,"title":"Subtitles Present","type":"boolean"},"timeline_version":{"default":0,"title":"Timeline Version","type":"integer"},"visual_breakdown":{"default":null,"title":"Visual Breakdown"},"word_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Word Count"}},"required":["id","source_url","script"],"title":"IngestDetail","type":"object"},"IngestQueuedResponse":{"description":"202 payload for POST /api/v1/copy-ingest.","properties":{"ingest_id":{"title":"Ingest Id","type":"integer"},"status":{"title":"Status","type":"string"}},"required":["ingest_id","status"],"title":"IngestQueuedResponse","type":"object"},"IntegrationStatusResponse":{"properties":{"account_label":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Account Label"},"connected":{"title":"Connected","type":"boolean"},"integration_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Integration Id"},"provider":{"default":"elevenlabs","title":"Provider","type":"string"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Status"}},"required":["connected"],"title":"IntegrationStatusResponse","type":"object"},"IntentSlug":{"description":"What the business wants from us.","enum":["collab","build"],"title":"IntentSlug","type":"string"},"InvoiceItemResponse":{"properties":{"amount_paid":{"title":"Amount Paid","type":"integer"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Created At"},"currency":{"title":"Currency","type":"string"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Description"},"hosted_invoice_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Hosted Invoice Url"},"pdf_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Pdf Url"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Status"},"stripe_invoice_id":{"title":"Stripe Invoice Id","type":"string"}},"required":["stripe_invoice_id","amount_paid","currency"],"title":"InvoiceItemResponse","type":"object"},"InvoicesResponse":{"properties":{"invoices":{"items":{"$ref":"#/components/schemas/InvoiceItemResponse"},"title":"Invoices","type":"array"}},"required":["invoices"],"title":"InvoicesResponse","type":"object"},"KpiFloat":{"properties":{"compare_value":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Compare Value"},"delta_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Delta Pct"},"value":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Value"}},"required":["value","compare_value","delta_pct"],"title":"KpiFloat","type":"object"},"KpiValue":{"properties":{"compare_value":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Compare Value"},"delta_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Delta Pct"},"value":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Value"}},"required":["value","compare_value","delta_pct"],"title":"KpiValue","type":"object"},"LastRun":{"properties":{"built_by_env":{"title":"Built By Env","type":"string"},"finished_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Finished At"},"run_id":{"title":"Run Id","type":"string"},"status":{"title":"Status","type":"string"}},"required":["run_id","status","finished_at","built_by_env"],"title":"LastRun","type":"object"},"LicenseAssetsRequest":{"properties":{"refs":{"items":{"$ref":"#/components/schemas/StockAssetRef"},"maxItems":50,"minItems":1,"title":"Refs","type":"array"}},"required":["refs"],"title":"LicenseAssetsRequest","type":"object"},"LicenseJobAssetOut":{"properties":{"error":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Error"},"provider_asset_id":{"title":"Provider Asset Id","type":"string"},"status":{"enum":["pending","ok","failed"],"title":"Status","type":"string"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Url"}},"required":["provider_asset_id","status"],"title":"LicenseJobAssetOut","type":"object"},"LicenseJobStartResponse":{"properties":{"job_id":{"title":"Job Id","type":"string"}},"required":["job_id"],"title":"LicenseJobStartResponse","type":"object"},"LicenseJobStatusResponse":{"properties":{"assets":{"items":{"$ref":"#/components/schemas/LicenseJobAssetOut"},"title":"Assets","type":"array"},"job_id":{"title":"Job Id","type":"string"},"status":{"enum":["pending","running","completed","failed"],"title":"Status","type":"string"}},"required":["job_id","status","assets"],"title":"LicenseJobStatusResponse","type":"object"},"MarkSeenRequest":{"description":"Ids the SPA displayed; capped so a rogue client can't bulk-scan.","properties":{"ids":{"items":{"type":"integer"},"maxItems":50,"minItems":1,"title":"Ids","type":"array"}},"required":["ids"],"title":"MarkSeenRequest","type":"object"},"MarkSeenResponse":{"properties":{"marked":{"title":"Marked","type":"integer"}},"required":["marked"],"title":"MarkSeenResponse","type":"object"},"MarketingEmailsRequest":{"properties":{"enabled":{"title":"Enabled","type":"boolean"}},"required":["enabled"],"title":"MarketingEmailsRequest","type":"object"},"MarketingEmailsResponse":{"properties":{"enabled":{"title":"Enabled","type":"boolean"}},"required":["enabled"],"title":"MarketingEmailsResponse","type":"object"},"MetaDimension":{"properties":{"count_unit":{"enum":["customers","signups","visits"],"title":"Count Unit","type":"string"},"group":{"enum":["customer","first_touch"],"title":"Group","type":"string"},"key":{"title":"Key","type":"string"},"label":{"title":"Label","type":"string"},"paying_only":{"title":"Paying Only","type":"boolean"}},"required":["key","label","group","paying_only","count_unit"],"title":"MetaDimension","type":"object"},"MetaDrill":{"properties":{"by":{"additionalProperties":{"items":{"type":"string"},"type":"array"},"title":"By","type":"object"},"default_by":{"additionalProperties":{"type":"string"},"title":"Default By","type":"object"},"export_row_cap":{"title":"Export Row Cap","type":"integer"},"kinds":{"items":{"type":"string"},"title":"Kinds","type":"array"},"metrics":{"items":{"type":"string"},"title":"Metrics","type":"array"},"page_size":{"title":"Page Size","type":"integer"}},"required":["kinds","metrics","by","default_by","page_size","export_row_cap"],"title":"MetaDrill","type":"object"},"MetaFunnel":{"properties":{"breakdowns":{"items":{"type":"string"},"title":"Breakdowns","type":"array"},"default_steps":{"items":{"type":"string"},"title":"Default Steps","type":"array"},"default_window_days":{"title":"Default Window Days","type":"integer"},"max_steps":{"title":"Max Steps","type":"integer"},"min_steps":{"title":"Min Steps","type":"integer"},"steps":{"items":{"$ref":"#/components/schemas/MetaFunnelStep"},"title":"Steps","type":"array"},"window_days":{"items":{"type":"integer"},"title":"Window Days","type":"array"}},"required":["steps","default_steps","window_days","default_window_days","breakdowns","min_steps","max_steps"],"title":"MetaFunnel","type":"object"},"MetaFunnelStep":{"properties":{"group":{"enum":["acquisition","product","billing"],"title":"Group","type":"string"},"label":{"title":"Label","type":"string"},"step_id":{"title":"Step Id","type":"string"}},"required":["step_id","label","group"],"title":"MetaFunnelStep","type":"object"},"MetaResponse":{"properties":{"dimensions":{"items":{"$ref":"#/components/schemas/MetaDimension"},"title":"Dimensions","type":"array"},"drill":{"$ref":"#/components/schemas/MetaDrill"},"env":{"enum":["production","staging","local","test"],"title":"Env","type":"string"},"estimated_before":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"title":"Estimated Before"},"funnel":{"$ref":"#/components/schemas/MetaFunnel"},"go_live_date":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"title":"Go Live Date"},"refresh_cooldown_seconds":{"title":"Refresh Cooldown Seconds","type":"integer"},"stale_after_hours":{"title":"Stale After Hours","type":"integer"},"state_stale_after_hours":{"title":"State Stale After Hours","type":"integer"},"today":{"format":"date","title":"Today","type":"string"},"tz":{"title":"Tz","type":"string"}},"required":["env","tz","today","go_live_date","estimated_before","stale_after_hours","state_stale_after_hours","refresh_cooldown_seconds","dimensions","funnel","drill"],"title":"MetaResponse","type":"object"},"MilestoneRequest":{"description":"A onboarding milestone the portal reports (spec 1.2).\n\n`event` is a plain bounded string rather than a pattern or an enum so the\nrefusal comes back as this module's `ErrorResponse` with\n`code: invalid_event`, the shape every other affiliate route answers\nwith, instead of the validator's generic blob.","properties":{"event":{"maxLength":32,"minLength":1,"title":"Event","type":"string"}},"required":["event"],"title":"MilestoneRequest","type":"object"},"MissingFaceImagesResponse":{"description":"`ok` only when every avatar's main picture is still in storage.","properties":{"avatars":{"items":{"$ref":"#/components/schemas/BrokenFaceAvatar"},"title":"Avatars","type":"array"},"checked":{"default":0,"title":"Checked","type":"integer"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Error"},"missing":{"default":0,"title":"Missing","type":"integer"},"status":{"title":"Status","type":"string"}},"required":["status"],"title":"MissingFaceImagesResponse","type":"object"},"ModelFreshness":{"properties":{"built_by_env":{"title":"Built By Env","type":"string"},"finished_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Finished At"},"is_stale":{"title":"Is Stale","type":"boolean"},"last_success_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Last Success At"},"max_business_day":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"title":"Max Business Day"},"max_event_ts":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Max Event Ts"},"model":{"title":"Model","type":"string"},"run_id":{"title":"Run Id","type":"string"},"stale_after_hours":{"enum":[2,26],"title":"Stale After Hours","type":"integer"},"status":{"title":"Status","type":"string"}},"required":["model","run_id","status","built_by_env","finished_at","last_success_at","max_event_ts","max_business_day","stale_after_hours","is_stale"],"title":"ModelFreshness","type":"object"},"ModelListResponse":{"properties":{"models":{"items":{"$ref":"#/components/schemas/ModelVoteItem"},"title":"Models","type":"array"}},"required":["models"],"title":"ModelListResponse","type":"object"},"ModelVoteItem":{"properties":{"blurb":{"title":"Blurb","type":"string"},"key":{"title":"Key","type":"string"},"name":{"title":"Name","type":"string"},"voted":{"title":"Voted","type":"boolean"},"votes":{"title":"Votes","type":"integer"}},"required":["key","name","blurb","votes","voted"],"title":"ModelVoteItem","type":"object"},"NamesRequest":{"properties":{"gender":{"default":"","title":"Gender","type":"string"},"origin":{"default":"","title":"Origin","type":"string"},"religion":{"default":"","title":"Religion","type":"string"}},"title":"NamesRequest","type":"object"},"NamesResponse":{"properties":{"names":{"default":[],"items":{"type":"string"},"title":"Names","type":"array"}},"title":"NamesResponse","type":"object"},"NextPayoutView":{"description":"The next manual payout run (spec 2, R11).\n\n`date` is the first day of the next month in UTC. `estimated_cents` is\nwhat would be paid if the run happened on that date: everything already\navailable plus every pending commission that matures before it. Below\n`minimum_cents` the balance rolls into the following run instead.","properties":{"below_minimum":{"default":false,"title":"Below Minimum","type":"boolean"},"date":{"format":"date","title":"Date","type":"string"},"estimated_cents":{"default":0,"title":"Estimated Cents","type":"integer"},"minimum_cents":{"default":0,"title":"Minimum Cents","type":"integer"}},"required":["date"],"title":"NextPayoutView","type":"object"},"NextStepItem":{"description":"One row of the onboarding checklist (spec 2).\n\n`disabled` is not `not done`: it means the step cannot be taken YET, which\ntoday is only \"copy your link\" before approval. Such a row carries a null\n`href` as well, so a client that ignores the flag still cannot navigate\ninto a dead end. `detail` carries the one line that varies per affiliate,\nwhich today is the decline reason.","properties":{"detail":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Detail"},"disabled":{"default":false,"title":"Disabled","type":"boolean"},"done":{"default":false,"title":"Done","type":"boolean"},"href":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Href"},"key":{"title":"Key","type":"string"},"label":{"title":"Label","type":"string"}},"required":["key","label"],"title":"NextStepItem","type":"object"},"NotificationItem":{"description":"One unseen notification, shaped for the SPA toast.","properties":{"created_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Created At"},"id":{"title":"Id","type":"integer"},"kind":{"title":"Kind","type":"string"},"link_path":{"title":"Link Path","type":"string"},"message":{"title":"Message","type":"string"},"seen":{"default":false,"title":"Seen","type":"boolean"},"thumbnail_file":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Thumbnail File"},"video_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Video Id"},"video_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Video Title"}},"required":["id","kind","video_id","video_title","message","link_path","thumbnail_file","created_at"],"title":"NotificationItem","type":"object"},"OkResponse":{"properties":{"ok":{"title":"Ok","type":"boolean"}},"required":["ok"],"title":"OkResponse","type":"object"},"OnboardingSaveRequest":{"description":"Body for `POST /api/v1/onboarding`.\n\nAll fields are optional so a \"Skip\" still produces a valid request\n(it just carries no answers). `skipped` records that the user chose\nto skip rather than answer; completion happens either way.","properties":{"existing_avatar_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Existing Avatar Url"},"goal_skipped":{"default":false,"title":"Goal Skipped","type":"boolean"},"has_existing_avatar":{"anyOf":[{"type":"boolean"},{"type":"null"}],"default":null,"title":"Has Existing Avatar"},"how_heard":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"How Heard"},"how_heard_detail":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"How Heard Detail"},"landed_on":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Landed On"},"looking_for":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Looking For"},"looking_for_detail":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Looking For Detail"},"looking_for_link":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Looking For Link"},"niche":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Niche"},"niche_detail":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Niche Detail"},"skipped":{"default":false,"title":"Skipped","type":"boolean"}},"title":"OnboardingSaveRequest","type":"object"},"OnboardingStatusResponse":{"properties":{"has_existing_avatar":{"anyOf":[{"type":"boolean"},{"type":"null"}],"default":null,"title":"Has Existing Avatar"},"how_heard":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"How Heard"},"how_heard_detail":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"How Heard Detail"},"is_onboarded":{"title":"Is Onboarded","type":"boolean"},"looking_for":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Looking For"},"looking_for_detail":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Looking For Detail"},"looking_for_link":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Looking For Link"},"niche":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Niche"},"niche_detail":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Niche Detail"}},"required":["is_onboarded"],"title":"OnboardingStatusResponse","type":"object"},"OutfitJobResponse":{"properties":{"job_id":{"title":"Job Id","type":"integer"},"status":{"title":"Status","type":"string"}},"required":["job_id","status"],"title":"OutfitJobResponse","type":"object"},"OverviewKpis":{"properties":{"active_subscriptions":{"$ref":"#/components/schemas/KpiValue"},"arpu_cents":{"$ref":"#/components/schemas/KpiValue"},"canceled_pending":{"$ref":"#/components/schemas/KpiValue"},"cancellations":{"$ref":"#/components/schemas/KpiValue"},"churned_mrr_cents":{"$ref":"#/components/schemas/KpiValue"},"churned_subscriptions":{"$ref":"#/components/schemas/KpiValue"},"contraction_mrr_cents":{"$ref":"#/components/schemas/KpiValue"},"expansion_mrr_cents":{"$ref":"#/components/schemas/KpiValue"},"logo_churn_pct":{"$ref":"#/components/schemas/KpiFloat"},"mrr_cents":{"$ref":"#/components/schemas/KpiValue"},"mrr_start_cents":{"$ref":"#/components/schemas/KpiValue"},"new_mrr_cents":{"$ref":"#/components/schemas/KpiValue"},"new_paid":{"$ref":"#/components/schemas/KpiValue"},"refunds_cents":{"$ref":"#/components/schemas/KpiValue"},"signups":{"$ref":"#/components/schemas/KpiValue"},"trials":{"$ref":"#/components/schemas/KpiValue"}},"required":["mrr_cents","new_paid","trials","signups","churned_mrr_cents","arpu_cents","active_subscriptions","canceled_pending","refunds_cents","new_mrr_cents","expansion_mrr_cents","contraction_mrr_cents","cancellations","mrr_start_cents","churned_subscriptions","logo_churn_pct"],"title":"OverviewKpis","type":"object"},"OverviewPoint":{"properties":{"active_subscriptions":{"title":"Active Subscriptions","type":"integer"},"arpu_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Arpu Cents"},"bucket":{"format":"date","title":"Bucket","type":"string"},"canceled_pending":{"title":"Canceled Pending","type":"integer"},"cancellations":{"title":"Cancellations","type":"integer"},"churned_mrr_cents":{"title":"Churned Mrr Cents","type":"integer"},"churned_subscriptions":{"title":"Churned Subscriptions","type":"integer"},"contraction_mrr_cents":{"title":"Contraction Mrr Cents","type":"integer"},"expansion_mrr_cents":{"title":"Expansion Mrr Cents","type":"integer"},"is_estimated":{"title":"Is Estimated","type":"boolean"},"logo_churn_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Logo Churn Pct"},"mrr_cents":{"title":"Mrr Cents","type":"integer"},"mrr_start_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Mrr Start Cents"},"new_mrr_cents":{"title":"New Mrr Cents","type":"integer"},"new_paid":{"title":"New Paid","type":"integer"},"refunds_cents":{"title":"Refunds Cents","type":"integer"},"signups":{"title":"Signups","type":"integer"},"trials":{"title":"Trials","type":"integer"}},"required":["bucket","signups","trials","new_paid","mrr_cents","new_mrr_cents","expansion_mrr_cents","contraction_mrr_cents","churned_mrr_cents","active_subscriptions","arpu_cents","refunds_cents","canceled_pending","cancellations","mrr_start_cents","churned_subscriptions","logo_churn_pct","is_estimated"],"title":"OverviewPoint","type":"object"},"OverviewResponse":{"properties":{"churn_by_reason":{"items":{"$ref":"#/components/schemas/ChurnReasonRow"},"title":"Churn By Reason","type":"array"},"compare":{"enum":["previous","yoy","none"],"title":"Compare","type":"string"},"compare_from":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"title":"Compare From"},"compare_series":{"anyOf":[{"items":{"$ref":"#/components/schemas/OverviewPoint"},"type":"array"},{"type":"null"}],"title":"Compare Series"},"compare_to":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"title":"Compare To"},"currency":{"const":"USD","default":"USD","title":"Currency","type":"string"},"env":{"enum":["production","staging","local","test"],"title":"Env","type":"string"},"estimated_before":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"title":"Estimated Before"},"filters":{"items":{"$ref":"#/components/schemas/FilterEcho"},"title":"Filters","type":"array"},"freshness":{"$ref":"#/components/schemas/FreshnessSummary"},"from":{"format":"date","title":"From","type":"string"},"granularity":{"enum":["day","week","month"],"title":"Granularity","type":"string"},"kpis":{"$ref":"#/components/schemas/OverviewKpis"},"meta":{"$ref":"#/components/schemas/ResponseMeta"},"notes":{"items":{"type":"string"},"title":"Notes","type":"array"},"series":{"items":{"$ref":"#/components/schemas/OverviewPoint"},"title":"Series","type":"array"},"to":{"format":"date","title":"To","type":"string"}},"required":["env","from","to","granularity","compare","compare_from","compare_to","freshness","meta","kpis","series","compare_series","churn_by_reason"],"title":"OverviewResponse","type":"object"},"PaidCohort":{"properties":{"cohort_week":{"format":"date","title":"Cohort Week","type":"string"},"payers":{"title":"Payers","type":"integer"},"weeks":{"items":{"$ref":"#/components/schemas/PaidCohortWeek"},"title":"Weeks","type":"array"}},"required":["cohort_week","payers","weeks"],"title":"PaidCohort","type":"object"},"PaidCohortWeek":{"properties":{"activity_week":{"format":"date","title":"Activity Week","type":"string"},"paid_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Paid Pct"},"still_paying":{"title":"Still Paying","type":"integer"},"week_offset":{"title":"Week Offset","type":"integer"}},"required":["week_offset","activity_week","still_paying","paid_pct"],"title":"PaidCohortWeek","type":"object"},"PaymentIssueResponse":{"description":"Why the charge behind the caller's latest invoice has not unlocked anything.\n\n``state`` is ``none`` (nothing billed), ``settled``, ``pending``, ``failed``\nor ``unknown``. The decline fields are Stripe's own message and code, passed\nthrough verbatim, and are null in every state but ``failed``.","properties":{"decline_code":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Decline Code"},"decline_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Decline Reason"},"hosted_invoice_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Hosted Invoice Url"},"invoice_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Invoice Id"},"state":{"title":"State","type":"string"}},"required":["state"],"title":"PaymentIssueResponse","type":"object"},"PaymentMethodEnvelope":{"properties":{"payment_method":{"anyOf":[{"$ref":"#/components/schemas/PaymentMethodResponse"},{"type":"null"}],"default":null}},"title":"PaymentMethodEnvelope","type":"object"},"PaymentMethodResponse":{"properties":{"brand":{"title":"Brand","type":"string"},"exp_month":{"title":"Exp Month","type":"integer"},"exp_year":{"title":"Exp Year","type":"integer"},"last4":{"title":"Last4","type":"string"}},"required":["brand","last4","exp_month","exp_year"],"title":"PaymentMethodResponse","type":"object"},"PayoutItem":{"properties":{"amount_cents":{"title":"Amount Cents","type":"integer"},"currency":{"title":"Currency","type":"string"},"id":{"title":"Id","type":"integer"},"method":{"title":"Method","type":"string"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Note"},"paid_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Paid At"},"period_end":{"format":"date","title":"Period End","type":"string"},"period_start":{"format":"date","title":"Period Start","type":"string"},"reference":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Reference"},"status":{"title":"Status","type":"string"}},"required":["id","period_start","period_end","amount_cents","currency","method","status"],"title":"PayoutItem","type":"object"},"PayoutsResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/PayoutItem"},"title":"Items","type":"array"}},"title":"PayoutsResponse","type":"object"},"Person":{"properties":{"billing_interval":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Billing Interval"},"cancel_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cancel Reason"},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country"},"device":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device"},"event_date":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"title":"Event Date"},"last_activity_date":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"title":"Last Activity Date"},"last_step_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Step Id"},"links":{"$ref":"#/components/schemas/PersonLinks"},"masked_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Masked Email"},"mrr_lost_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Mrr Lost Cents"},"person_type":{"enum":["user","visitor","customer"],"title":"Person Type","type":"string"},"plan_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Plan Slug"},"platform_user_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Platform User Id"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"},"signup_date":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"title":"Signup Date"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"},"stripe_customer_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stripe Customer Id"},"subscription_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subscription Id"},"tenure_days":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Tenure Days"},"user_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Id"}},"required":["person_type","user_id","platform_user_id","masked_email","signup_date","event_date","last_activity_date","plan_slug","billing_interval","country","device","source","last_step_id","subscription_id","mrr_lost_cents","reason","cancel_reason","tenure_days","stripe_customer_id","links"],"title":"Person","type":"object"},"PersonLinks":{"properties":{"stripe_customer":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stripe Customer"}},"required":["stripe_customer"],"title":"PersonLinks","type":"object"},"PipelineStartedResponse":{"properties":{"message":{"default":"","title":"Message","type":"string"},"run_id":{"title":"Run Id","type":"integer"},"success":{"default":true,"title":"Success","type":"boolean"}},"required":["run_id"],"title":"PipelineStartedResponse","type":"object"},"PipelineStatusResponse":{"properties":{"avatar_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Avatar Name"},"current_step":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Current Step"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Error Message"},"run_id":{"title":"Run Id","type":"integer"},"script_title":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Script Title"},"status":{"title":"Status","type":"string"},"step_label":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Step Label"},"video_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Video Id"}},"required":["run_id","status"],"title":"PipelineStatusResponse","type":"object"},"PlanResponse":{"properties":{"blurb":{"title":"Blurb","type":"string"},"credits":{"title":"Credits","type":"integer"},"featured":{"title":"Featured","type":"boolean"},"funnel_only":{"default":false,"title":"Funnel Only","type":"boolean"},"group":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Group"},"monthly_cents":{"title":"Monthly Cents","type":"integer"},"name":{"title":"Name","type":"string"},"slug":{"title":"Slug","type":"string"},"yearly_cents":{"title":"Yearly Cents","type":"integer"},"yearly_monthly_cents":{"title":"Yearly Monthly Cents","type":"integer"}},"required":["slug","name","blurb","monthly_cents","yearly_cents","yearly_monthly_cents","credits","featured"],"title":"PlanResponse","type":"object"},"PlansResponse":{"properties":{"plans":{"items":{"$ref":"#/components/schemas/PlanResponse"},"title":"Plans","type":"array"}},"required":["plans"],"title":"PlansResponse","type":"object"},"PlatformPublishState":{"additionalProperties":true,"description":"Per-platform publish state for the Publishing card.\n\n`connected` is true only when the avatar has a matching row in\n`social_accounts` for the platform. `posted` is true only when a\n`Post` exists for this video AND its status is \"published\" AND\nthe avatar is connected \u00b7 all three must hold so the UI never\nrenders a green \"Published\" badge when one of the underlying\nfacts is missing (the bug Piece C fixes).","properties":{"account_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Account Name"},"connected":{"default":false,"title":"Connected","type":"boolean"},"posted":{"default":false,"title":"Posted","type":"boolean"}},"title":"PlatformPublishState","type":"object"},"PolishBody":{"properties":{"apply":{"default":false,"title":"Apply","type":"boolean"},"style":{"default":"measured","title":"Style","type":"string"}},"title":"PolishBody","type":"object"},"PostCard":{"properties":{"avatar_desc":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Avatar Desc"},"avatar_face":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Avatar Face"},"avatar_face_focus":{"anyOf":[{"$ref":"#/components/schemas/FaceFocusPoint"},{"type":"null"}],"default":null},"avatar_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Avatar Id"},"avatar_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Avatar Name"},"duration_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Duration Seconds"},"final_video_file":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Final Video File"},"id":{"title":"Id","type":"integer"},"ig_caption":{"title":"Ig Caption","type":"string"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Notes"},"script_text":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Script Text"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Status"},"status_changed_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Status Changed At"},"thumbnail_file":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Thumbnail File"},"video_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Video Id"},"video_title":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Video Title"}},"required":["id","ig_caption"],"title":"PostCard","type":"object"},"PostListView":{"properties":{"avatars":{"items":{"$ref":"#/components/schemas/AvatarChoice"},"title":"Avatars","type":"array"},"posts":{"items":{"$ref":"#/components/schemas/PostCard"},"title":"Posts","type":"array"},"social_accounts":{"additionalProperties":true,"title":"Social Accounts","type":"object"}},"required":["posts","avatars","social_accounts"],"title":"PostListView","type":"object"},"PrewarmResponse":{"description":"POST /api/v1/copy-ingest/prewarm: whether this call sent a GPU ping (False when\nthe user pinged in the last 15 s or Modal is not configured).","properties":{"pinged":{"title":"Pinged","type":"boolean"}},"required":["pinged"],"title":"PrewarmResponse","type":"object"},"ProfileRequest":{"description":"A profile edit.\n\n`payout_details` missing, null, or an empty object means UNCHANGED. Reads\nreturn the details masked (R7), so a portal form that echoed what it read\nwould otherwise write `****9999` over the real IBAN. Send a populated\nobject only when the affiliate actually retyped the details.\n\n`channels` is APPEND-ONLY once the affiliate is approved or suspended:\nthe list must start with the stored one, entry for entry and in order,\nand may only grow. Anything else comes back 422 `channels_locked`. The\nshape stays a plain list here because the rule needs the stored row to\njudge it, which only the service has: see\n`channel_lock.violates_lock` for why the lock exists.","properties":{"channels":{"items":{"type":"string"},"maxItems":50,"minItems":1,"title":"Channels","type":"array"},"full_name":{"maxLength":120,"minLength":2,"title":"Full Name","type":"string"},"payout_details":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"default":null,"title":"Payout Details"},"payout_method":{"maxLength":32,"minLength":1,"title":"Payout Method","type":"string"},"phone":{"anyOf":[{"pattern":"^\\+[1-9]\\d{7,14}$","type":"string"},{"type":"null"}],"default":null,"title":"Phone"}},"required":["full_name","channels","payout_method"],"title":"ProfileRequest","type":"object"},"PromoteAccountResponse":{"properties":{"account":{"$ref":"#/components/schemas/PromotedAccountSummary"},"ok":{"default":true,"title":"Ok","type":"boolean"}},"required":["account"],"title":"PromoteAccountResponse","type":"object"},"PromotedAccountSummary":{"properties":{"discovery_count":{"default":0,"title":"Discovery Count","type":"integer"},"discovery_source":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Discovery Source"},"id":{"title":"Id","type":"integer"},"is_global":{"default":true,"title":"Is Global","type":"boolean"},"username":{"title":"Username","type":"string"}},"required":["id","username"],"title":"PromotedAccountSummary","type":"object"},"PublicConfigResponse":{"properties":{"influencers":{"items":{"$ref":"#/components/schemas/InfluencerConfigItem"},"title":"Influencers","type":"array"}},"required":["influencers"],"title":"PublicConfigResponse","type":"object"},"PublicDraftItem":{"description":"A draft guide's full build payload plus its preview token.\n\nDrafts are exposed ONLY through the include_drafts=1 query param and\nfeed the public-at-unguessable-URL noindexed preview pages; they are\nnever placed in the published `guides` array.","properties":{"author":{"title":"Author","type":"string"},"bodyMarkdown":{"title":"Bodymarkdown","type":"string"},"canonicalTo":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Canonicalto"},"description":{"title":"Description","type":"string"},"faqs":{"items":{"$ref":"#/components/schemas/GuideFaq"},"title":"Faqs","type":"array"},"featured":{"title":"Featured","type":"boolean"},"headline":{"title":"Headline","type":"string"},"heroAlt":{"title":"Heroalt","type":"string"},"heroImage":{"title":"Heroimage","type":"string"},"noindex":{"title":"Noindex","type":"boolean"},"ogImage":{"title":"Ogimage","type":"string"},"pillar":{"title":"Pillar","type":"string"},"popularRank":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Popularrank"},"previewToken":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Previewtoken"},"publishDate":{"format":"date","title":"Publishdate","type":"string"},"quotableAnswer":{"title":"Quotableanswer","type":"string"},"related":{"items":{"type":"string"},"title":"Related","type":"array"},"section":{"title":"Section","type":"string"},"slug":{"title":"Slug","type":"string"},"stat":{"title":"Stat","type":"string"},"title":{"title":"Title","type":"string"},"updatedDate":{"format":"date","title":"Updateddate","type":"string"}},"required":["slug","title","description","headline","pillar","author","heroImage","heroAlt","ogImage","publishDate","updatedDate","quotableAnswer","stat","faqs","related","bodyMarkdown","section","featured","noindex"],"title":"PublicDraftItem","type":"object"},"PublishCampaignBody":{"properties":{"stagger_minutes":{"default":45,"title":"Stagger Minutes","type":"integer"}},"title":"PublishCampaignBody","type":"object"},"PublishResponse":{"properties":{"success":{"title":"Success","type":"boolean"}},"required":["success"],"title":"PublishResponse","type":"object"},"PublishStatusResponse":{"properties":{"endedAt":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Endedat"},"lastBuildId":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Lastbuildid"},"publishedBy":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Publishedby"},"startedAt":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Startedat"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Status"}},"title":"PublishStatusResponse","type":"object"},"PublishVideoRequest":{"properties":{"caption":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Caption"},"platform":{"title":"Platform","type":"string"},"video_id":{"title":"Video Id","type":"integer"}},"required":["video_id","platform"],"title":"PublishVideoRequest","type":"object"},"PublishVideoResponse":{"properties":{"caption":{"default":"","title":"Caption","type":"string"},"message":{"default":"","title":"Message","type":"string"},"platform":{"title":"Platform","type":"string"},"success":{"title":"Success","type":"boolean"}},"required":["success","platform"],"title":"PublishVideoResponse","type":"object"},"QaCheckResponse":{"additionalProperties":true,"properties":{"avatar":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Avatar"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Title"}},"title":"QaCheckResponse","type":"object"},"QaHistoryResponse":{"properties":{"runs":{"items":{"additionalProperties":true,"type":"object"},"title":"Runs","type":"array"}},"title":"QaHistoryResponse","type":"object"},"QaReportResponse":{"additionalProperties":true,"properties":{"avatar":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Avatar"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Title"}},"title":"QaReportResponse","type":"object"},"QaRunDetailResponse":{"additionalProperties":true,"properties":{"id":{"title":"Id","type":"integer"}},"required":["id"],"title":"QaRunDetailResponse","type":"object"},"QaRunStartResponse":{"properties":{"message":{"title":"Message","type":"string"},"ok":{"title":"Ok","type":"boolean"}},"required":["ok","message"],"title":"QaRunStartResponse","type":"object"},"QaRunSyncResponse":{"additionalProperties":true,"properties":{"ok":{"anyOf":[{"type":"boolean"},{"type":"null"}],"default":null,"title":"Ok"}},"title":"QaRunSyncResponse","type":"object"},"RateVideoRequest":{"description":"Body for `PUT /api/v1/videos/:id/rating` (a star click).","properties":{"rating":{"maximum":5,"minimum":1.0,"title":"Rating","type":"integer"}},"required":["rating"],"title":"RateVideoRequest","type":"object"},"ReadySceneItem":{"additionalProperties":true,"description":"One per-shot scene clip that has finished mid-render (Phase 3,\nprogressive reveal). The render-in-progress UI shows these as they land\nso the user can preview/edit before the final stitch.\n\n`video_file` is the BARE durable filename under the videos/ prefix (the\nshot's persisted clip), resolved client-side by `resolveVideoFileUrl`\nexactly like the detail page's `assets[]` \u2014 never a hand-built URL.\n`scene_index` is the 0-based scene position; `asset_id` is the\n`VideoAsset` row id (stable key for the UI list).","properties":{"asset_id":{"title":"Asset Id","type":"integer"},"scene_index":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Scene Index"},"video_file":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Video File"}},"required":["asset_id"],"title":"ReadySceneItem","type":"object"},"RebuildRequest":{"additionalProperties":false,"properties":{"rebuild_from":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"title":"Rebuild From"}},"title":"RebuildRequest","type":"object"},"RebuildResponse":{"properties":{"env":{"title":"Env","type":"string"},"run_id":{"title":"Run Id","type":"string"},"status":{"const":"queued","title":"Status","type":"string"}},"required":["run_id","env","status"],"title":"RebuildResponse","type":"object"},"RebuildVideoResponse":{"description":"Response for `POST /api/v1/videos/:id/rebuild`. The rebuild runs async\n(stitch + caption), so the new `final_video_file` arrives via the\nstatus/detail poll once `needs_rebuild` clears; `message` is the toast.","properties":{"message":{"title":"Message","type":"string"},"success":{"title":"Success","type":"boolean"},"video_id":{"title":"Video Id","type":"integer"}},"required":["success","message","video_id"],"title":"RebuildVideoResponse","type":"object"},"RecentNotificationsResponse":{"description":"GET /recent payload: newest first, plus the live unseen count for\nthe sidebar dot.","properties":{"notifications":{"items":{"$ref":"#/components/schemas/NotificationItem"},"title":"Notifications","type":"array"},"unseen_count":{"title":"Unseen Count","type":"integer"}},"required":["notifications","unseen_count"],"title":"RecentNotificationsResponse","type":"object"},"RecentRunRow":{"additionalProperties":true,"properties":{"avatar_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Avatar Id"},"avatar_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Avatar Name"},"completed_at":{"default":null,"title":"Completed At"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Error Message"},"id":{"title":"Id","type":"integer"},"started_at":{"default":null,"title":"Started At"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Status"}},"required":["id"],"title":"RecentRunRow","type":"object"},"RedeemCodeRequest":{"description":"A partner code typed on the packages step or arriving as ?code=.","properties":{"code":{"title":"Code","type":"string"}},"required":["code"],"title":"RedeemCodeRequest","type":"object"},"RedeemCodeResponse":{"description":"Whether the code granted anything, and what.\n\n``promo`` is the third answer, alongside granted and rejected: the string\nis not one of our minted codes but IS a live Stripe promotion code, so the\ncheckout page applies it exactly as the promo field would.","properties":{"error":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Error"},"granted":{"title":"Granted","type":"boolean"},"kind":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Kind"},"plan_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Plan Slug"},"promo":{"anyOf":[{"$ref":"#/components/schemas/RedeemPromoOffer"},{"type":"null"}],"default":null}},"required":["granted"],"title":"RedeemCodeResponse","type":"object"},"RedeemPromoOffer":{"description":"A Stripe promotion code the partner box found instead of a grant.","properties":{"code":{"title":"Code","type":"string"},"fully_discounts":{"title":"Fully Discounts","type":"boolean"},"label":{"title":"Label","type":"string"}},"required":["code","label","fully_discounts"],"title":"RedeemPromoOffer","type":"object"},"ReelDashboardResponse":{"additionalProperties":true,"properties":{"accounts":{"items":{"type":"string"},"title":"Accounts","type":"array"},"active_accounts_count":{"default":0,"title":"Active Accounts Count","type":"integer"},"all_tags":{"items":{"$ref":"#/components/schemas/TagCount"},"title":"All Tags","type":"array"},"categories":{"items":{"$ref":"#/components/schemas/CategoryRow"},"title":"Categories","type":"array"},"reels":{"items":{"$ref":"#/components/schemas/ReelRow"},"title":"Reels","type":"array"},"stats":{"$ref":"#/components/schemas/ReelStatsView"}},"title":"ReelDashboardResponse","type":"object"},"ReelRefreshResponse":{"properties":{"comments":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Comments"},"engagement_rate":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Engagement Rate"},"likes":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Likes"},"new_views":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"New Views"},"ok":{"title":"Ok","type":"boolean"},"old_views":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Old Views"},"views_per_hour":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Views Per Hour"}},"required":["ok"],"title":"ReelRefreshResponse","type":"object"},"ReelRow":{"properties":{"account_followers":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Account Followers"},"account_username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account Username"},"caption":{"title":"Caption","type":"string"},"comments":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Comments"},"engagement_rate":{"title":"Engagement Rate","type":"number"},"has_script":{"title":"Has Script","type":"boolean"},"id":{"title":"Id","type":"integer"},"is_favorite":{"title":"Is Favorite","type":"boolean"},"last_scanned_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Last Scanned At"},"likes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Likes"},"posted_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Posted At"},"reel_shortcode":{"title":"Reel Shortcode","type":"string"},"reel_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reel Url"},"scan_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Scan Count"},"views":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Views"},"views_per_hour":{"title":"Views Per Hour","type":"number"}},"required":["id","reel_url","reel_shortcode","caption","posted_at","views","likes","comments","engagement_rate","views_per_hour","account_username","account_followers","is_favorite","scan_count","last_scanned_at","has_script"],"title":"ReelRow","type":"object"},"ReelStatsView":{"properties":{"avg_engagement":{"default":0.0,"title":"Avg Engagement","type":"number"},"top_reel":{"anyOf":[{"$ref":"#/components/schemas/TopReel"},{"type":"null"}],"default":null},"total_reels":{"default":0,"title":"Total Reels","type":"integer"},"total_views":{"default":0,"title":"Total Views","type":"integer"}},"title":"ReelStatsView","type":"object"},"ReelTableFacets":{"properties":{"accounts":{"items":{"$ref":"#/components/schemas/AccountFacet"},"title":"Accounts","type":"array"},"categories":{"items":{"$ref":"#/components/schemas/CategoryRow"},"title":"Categories","type":"array"}},"title":"ReelTableFacets","type":"object"},"ReelTableResponse":{"properties":{"facets":{"$ref":"#/components/schemas/ReelTableFacets"},"page":{"default":1,"title":"Page","type":"integer"},"page_size":{"default":50,"title":"Page Size","type":"integer"},"rows":{"items":{"$ref":"#/components/schemas/ReelTableRow"},"title":"Rows","type":"array"},"total_count":{"default":0,"title":"Total Count","type":"integer"}},"title":"ReelTableResponse","type":"object"},"ReelTableRow":{"properties":{"account_followers":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Account Followers"},"account_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Account Id"},"account_is_real":{"default":false,"title":"Account Is Real","type":"boolean"},"account_picture_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Account Picture Url"},"account_username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account Username"},"af_components":{"anyOf":[{"additionalProperties":{"type":"number"},"type":"object"},{"type":"null"}],"default":null,"title":"Af Components"},"af_score":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Af Score"},"caption":{"title":"Caption","type":"string"},"category_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category Name"},"comments":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Comments"},"engagement_rate":{"title":"Engagement Rate","type":"number"},"has_transcript":{"default":false,"title":"Has Transcript","type":"boolean"},"id":{"title":"Id","type":"integer"},"is_favorite":{"default":false,"title":"Is Favorite","type":"boolean"},"is_outperformer":{"default":false,"title":"Is Outperformer","type":"boolean"},"likes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Likes"},"outperform_ratio":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Outperform Ratio"},"posted_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Posted At"},"reel_shortcode":{"title":"Reel Shortcode","type":"string"},"reel_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reel Url"},"thumbnail_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Thumbnail Url"},"video_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Video Url"},"views":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Views"},"views_per_hour":{"title":"Views Per Hour","type":"number"}},"required":["id","reel_url","reel_shortcode","thumbnail_url","caption","posted_at","views","likes","comments","engagement_rate","views_per_hour","account_id","account_username","account_followers","category_name"],"title":"ReelTableRow","type":"object"},"ReelToVideoRequest":{"properties":{"avatar_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Avatar Id"},"caption_style":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Caption Style"},"forced_scene_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Forced Scene Id"},"script_text":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Script Text"},"script_title":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Script Title"},"source_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Source Url"},"telegram_chat_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Telegram Chat Id"}},"title":"ReelToVideoRequest","type":"object"},"ReelToVideoStartedResponse":{"properties":{"avatar_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Avatar Id"},"overrides":{"additionalProperties":true,"title":"Overrides","type":"object"},"run_id":{"title":"Run Id","type":"integer"},"script_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Script Id"},"success":{"default":true,"title":"Success","type":"boolean"}},"required":["run_id"],"title":"ReelToVideoStartedResponse","type":"object"},"ReelTranscriptResponse":{"properties":{"created_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Created At"},"script":{"title":"Script","type":"string"},"word_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Word Count"}},"required":["script","word_count","created_at"],"title":"ReelTranscriptResponse","type":"object"},"ReferralItem":{"description":"One referred user. The email is masked; the raw address never ships.\n\n`status` is the six-word vocabulary, so the SPA renders a label per known\nvalue instead of guessing at whatever Stripe called it this quarter. A\nreferred user who never subscribed reads `signed_up` with a null\n`plan_slug`, never an empty string.","properties":{"first_paid_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"First Paid At"},"gross_revenue_cents":{"title":"Gross Revenue Cents","type":"integer"},"interval":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Interval"},"last_paid_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Last Paid At"},"masked_email":{"title":"Masked Email","type":"string"},"net_commission_cents":{"title":"Net Commission Cents","type":"integer"},"plan_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Plan Slug"},"signed_up_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Signed Up At"},"status":{"enum":["signed_up","trial","paying","past_due","churned","refunded"],"title":"Status","type":"string"}},"required":["masked_email","status","gross_revenue_cents","net_commission_cents"],"title":"ReferralItem","type":"object"},"ReferralsResponse":{"description":"One page of referrals, plus how many there are in total.\n\n`total` counts every referral this affiliate has, not the page, so the\nheading can say \"12 referrals\" while the table shows the newest 25.","properties":{"items":{"items":{"$ref":"#/components/schemas/ReferralItem"},"title":"Items","type":"array"},"next_cursor":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Next Cursor"},"total":{"default":0,"title":"Total","type":"integer"}},"title":"ReferralsResponse","type":"object"},"RefineSlideBody":{"description":"POST .../slides/<id>/refine: transform the image with change notes.","properties":{"notes":{"maxLength":500,"minLength":1,"title":"Notes","type":"string"}},"required":["notes"],"title":"RefineSlideBody","type":"object"},"RegenFlag":{"description":"One portrait flag as the admin page sends it.","properties":{"flagged":{"default":false,"title":"Flagged","type":"boolean"},"note":{"anyOf":[{"maxLength":500,"type":"string"},{"type":"null"}],"default":null,"title":"Note"}},"title":"RegenFlag","type":"object"},"RegenItem":{"properties":{"flaggedAt":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Flaggedat"},"flaggedBy":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Flaggedby"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Note"},"slug":{"title":"Slug","type":"string"}},"required":["slug"],"title":"RegenItem","type":"object"},"RegenListResponse":{"properties":{"flagged":{"default":[],"items":{"$ref":"#/components/schemas/RegenItem"},"title":"Flagged","type":"array"}},"title":"RegenListResponse","type":"object"},"RegenerateVideoResponse":{"description":"Response payload for `POST /api/v1/videos/:id/regenerate` (plan \u00a76.4).\n\nThe detail page surfaces `message` as a transient toast so the user\nsees a real \"Render queued\" confirmation rather than guessing the\nrequest landed. `video_id` is the same id the request was made\nagainst \u00b7 regenerate re-uses the existing row instead of forking\na new one (see `service.regenerate_video`).","properties":{"message":{"title":"Message","type":"string"},"success":{"title":"Success","type":"boolean"},"video_id":{"title":"Video Id","type":"integer"}},"required":["success","message","video_id"],"title":"RegenerateVideoResponse","type":"object"},"RejectItemBody":{"properties":{"reason":{"default":"","title":"Reason","type":"string"}},"title":"RejectItemBody","type":"object"},"ReorderAvatarsRequest":{"additionalProperties":false,"description":"Payload for ``POST /api/v1/avatars/reorder``.\n\n``ids`` is the caller's avatars in their new left-to-right / top-to-\nbottom order. The endpoint writes ``display_order`` = position in this\nlist for every id the caller actually owns; unknown or foreign ids are\nsilently skipped so a stale client can never reorder another user's\nrows. Unknown fields are rejected so the SPA can't drift the contract.","properties":{"ids":{"items":{"type":"integer"},"title":"Ids","type":"array"}},"required":["ids"],"title":"ReorderAvatarsRequest","type":"object"},"ReorderAvatarsResponse":{"description":"The persisted order after a reorder.\n\n``ids`` echoes only the owned avatars that were reordered, in their new\norder, so the SPA can confirm which rows the write actually touched.","properties":{"ids":{"items":{"type":"integer"},"title":"Ids","type":"array"},"success":{"title":"Success","type":"boolean"}},"required":["success","ids"],"title":"ReorderAvatarsResponse","type":"object"},"RerollShotRequest":{"description":"Body for `POST /api/v1/videos/:id/shot/:index/reroll` (Loop A).\n\n`artifact_tags` are the fixed-vocabulary flags the user picked (spec \u00a72);\n`note` is optional free text. The backend validates the tags against the\ntaxonomy and maps them to the \u00a73 steering phrases for the shot's model.\n`edits` carries the optional input fixes; with edits or without, the\nregeneration charges credits upfront and lands as a candidate take.","properties":{"artifact_tags":{"items":{"type":"string"},"title":"Artifact Tags","type":"array"},"edits":{"anyOf":[{"$ref":"#/components/schemas/ShotEditsPayload"},{"type":"null"}],"default":null},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Note"}},"title":"RerollShotRequest","type":"object"},"RerollShotResponse":{"description":"Response for a per-shot re-roll. `message` is a transient toast; the\nshot's new clip and the `needs_rebuild` flag arrive via the status/detail\npoll once the async re-render completes.","properties":{"message":{"title":"Message","type":"string"},"shot_index":{"title":"Shot Index","type":"integer"},"success":{"title":"Success","type":"boolean"},"video_id":{"title":"Video Id","type":"integer"}},"required":["success","message","video_id","shot_index"],"title":"RerollShotResponse","type":"object"},"RescanAllResponse":{"properties":{"message":{"default":"","title":"Message","type":"string"},"ok":{"title":"Ok","type":"boolean"},"run_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Run Id"}},"required":["ok"],"title":"RescanAllResponse","type":"object"},"RescanFailedResponse":{"properties":{"ok":{"title":"Ok","type":"boolean"},"queued":{"default":0,"title":"Queued","type":"integer"}},"required":["ok"],"title":"RescanFailedResponse","type":"object"},"RescanResponse":{"additionalProperties":true,"properties":{},"title":"RescanResponse","type":"object"},"ResolveShotTakeRequest":{"description":"Body for `POST /api/v1/videos/:id/shot/:index/resolve`.\n\n`keep=\"new\"` promotes the waiting candidate take (and marks the final\ncut stale); `keep=\"old\"` discards it and keeps the current take.","properties":{"keep":{"enum":["new","old"],"title":"Keep","type":"string"}},"required":["keep"],"title":"ResolveShotTakeRequest","type":"object"},"ResolveShotTakeResponse":{"description":"Response for a take resolution; `kept` echoes the choice.","properties":{"kept":{"title":"Kept","type":"string"},"message":{"title":"Message","type":"string"},"shot_index":{"title":"Shot Index","type":"integer"},"success":{"title":"Success","type":"boolean"},"video_id":{"title":"Video Id","type":"integer"}},"required":["success","message","video_id","shot_index","kept"],"title":"ResolveShotTakeResponse","type":"object"},"ResponseMeta":{"description":"The zone the answer's dates are in (ruling 11). tz_applied is false where\nthe data is UTC by nature (/freshness, /exports).","properties":{"tz":{"title":"Tz","type":"string"},"tz_applied":{"default":true,"title":"Tz Applied","type":"boolean"}},"required":["tz"],"title":"ResponseMeta","type":"object"},"RetentionOfferRequest":{"description":"Body for `POST /api/v1/billing/retention-offer` (a keep-the-account\ncard on the flow's last screen).","properties":{"details":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Details"},"offer":{"title":"Offer","type":"string"},"reason":{"title":"Reason","type":"string"}},"required":["offer","reason"],"title":"RetentionOfferRequest","type":"object"},"RetentionResponse":{"properties":{"cohorts":{"items":{"$ref":"#/components/schemas/Cohort"},"title":"Cohorts","type":"array"},"compare":{"enum":["previous","yoy","none"],"title":"Compare","type":"string"},"compare_from":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"title":"Compare From"},"compare_to":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"title":"Compare To"},"currency":{"const":"USD","default":"USD","title":"Currency","type":"string"},"env":{"enum":["production","staging","local","test"],"title":"Env","type":"string"},"estimated_before":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"title":"Estimated Before"},"filters":{"items":{"$ref":"#/components/schemas/FilterEcho"},"title":"Filters","type":"array"},"freshness":{"$ref":"#/components/schemas/FreshnessSummary"},"from":{"format":"date","title":"From","type":"string"},"granularity":{"enum":["day","week","month"],"title":"Granularity","type":"string"},"max_week_offset":{"title":"Max Week Offset","type":"integer"},"meta":{"$ref":"#/components/schemas/ResponseMeta"},"notes":{"items":{"type":"string"},"title":"Notes","type":"array"},"paid_cohorts":{"items":{"$ref":"#/components/schemas/PaidCohort"},"title":"Paid Cohorts","type":"array"},"to":{"format":"date","title":"To","type":"string"}},"required":["env","from","to","granularity","compare","compare_from","compare_to","freshness","meta","cohorts","paid_cohorts","max_week_offset"],"title":"RetentionResponse","type":"object"},"RevertSubtitlesResponse":{"properties":{"message":{"title":"Message","type":"string"},"success":{"title":"Success","type":"boolean"}},"required":["success","message"],"title":"RevertSubtitlesResponse","type":"object"},"RewriteScriptBody":{"properties":{"avatar_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Avatar Id"}},"title":"RewriteScriptBody","type":"object"},"RunFullProcessRequest":{"properties":{"avatar_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Avatar Id"},"script_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Script Id"}},"title":"RunFullProcessRequest","type":"object"},"SaveCaptionRequest":{"description":"Body for `POST /api/v1/videos/:id/caption` (save a user-edited caption).","properties":{"caption":{"default":"","title":"Caption","type":"string"}},"title":"SaveCaptionRequest","type":"object"},"SaveCaptionResponse":{"properties":{"caption":{"title":"Caption","type":"string"},"success":{"title":"Success","type":"boolean"}},"required":["success","caption"],"title":"SaveCaptionResponse","type":"object"},"SaveConfigRequest":{"description":"The admin page's full working state.\n\n`order` is the rail order the admin sees; `hidden` and `regen` carry\nthe flags. Anything absent from `regen` is treated as unflagged, so\na save is a complete replacement of the state for every slug it\nmentions rather than a partial patch. A slug the `hidden` map never\nmentions keeps a null override, so its YAML `hideFromRail` stands.\n\nEvery collection is capped and the note is length-limited. A payload\nthat breaks a bound never reaches the service: flask-openapi3\nrejects it at the boundary with a 422, which the route documents.","properties":{"hidden":{"maxProperties":500,"title":"Hidden","type":"object"},"order":{"items":{"maxLength":120,"pattern":"^[a-z0-9-]{1,120}$","type":"string"},"maxItems":500,"title":"Order","type":"array"},"regen":{"maxProperties":500,"title":"Regen","type":"object"}},"title":"SaveConfigRequest","type":"object"},"SaveConfigResponse":{"properties":{"ok":{"title":"Ok","type":"boolean"},"saved":{"title":"Saved","type":"integer"}},"required":["ok","saved"],"title":"SaveConfigResponse","type":"object"},"SaveDraftRequest":{"properties":{"description":{"default":"","title":"Description","type":"string"},"draft_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Draft Id"},"face_image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Face Image Url"},"name":{"default":"","title":"Name","type":"string"},"story":{"default":"","title":"Story","type":"string"},"voice_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Voice Id"}},"title":"SaveDraftRequest","type":"object"},"SaveDraftResponse":{"properties":{"draft_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Draft Id"},"ok":{"default":true,"title":"Ok","type":"boolean"}},"title":"SaveDraftResponse","type":"object"},"SaveStoreRequest":{"description":"Body for PUT /api/v1/funnel-store.","properties":{"claimed":{"default":false,"title":"Claimed","type":"boolean"},"niche":{"title":"Niche","type":"string"},"price_cents":{"maximum":99900,"minimum":100.0,"title":"Price Cents","type":"integer"},"product_key":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Product Key"},"source":{"enum":["catalog","upload"],"title":"Source","type":"string"},"theme":{"title":"Theme","type":"string"},"title":{"maxLength":120,"minLength":1,"title":"Title","type":"string"}},"required":["source","niche","title","price_cents","theme"],"title":"SaveStoreRequest","type":"object"},"SaveViewPrefsRequest":{"description":"Body for PUT /api/v1/prefs/views/<page_key>.","properties":{"filters":{"additionalProperties":true,"title":"Filters","type":"object"}},"title":"SaveViewPrefsRequest","type":"object"},"SaveViewPrefsResponse":{"properties":{"ok":{"title":"Ok","type":"boolean"},"page_key":{"title":"Page Key","type":"string"}},"required":["ok","page_key"],"title":"SaveViewPrefsResponse","type":"object"},"ScanHistoryEntry":{"properties":{"followers":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Followers"},"following":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Following"},"posts_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Posts Count"},"scanned_at":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Scanned At"}},"title":"ScanHistoryEntry","type":"object"},"ScanResultRow":{"properties":{"account_id":{"title":"Account Id","type":"integer"},"error_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Error Reason"},"followers":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Followers"},"followers_fmt":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Followers Fmt"},"growth":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Growth"},"growth_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Growth Pct"},"prev_followers":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Prev Followers"},"scanned_at":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Scanned At"},"status":{"default":"","title":"Status","type":"string"},"username":{"title":"Username","type":"string"}},"required":["username","account_id"],"title":"ScanResultRow","type":"object"},"ScanRunDetailResponse":{"properties":{"failed":{"default":0,"title":"Failed","type":"integer"},"finished_at":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Finished At"},"id":{"title":"Id","type":"integer"},"results":{"items":{"$ref":"#/components/schemas/ScanResultRow"},"title":"Results","type":"array"},"started_at":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Started At"},"status":{"default":"","title":"Status","type":"string"},"success":{"default":0,"title":"Success","type":"integer"},"total":{"default":0,"title":"Total","type":"integer"}},"required":["id"],"title":"ScanRunDetailResponse","type":"object"},"ScanRunSummary":{"properties":{"failed":{"default":0,"title":"Failed","type":"integer"},"finished_at":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Finished At"},"id":{"title":"Id","type":"integer"},"started_at":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Started At"},"status":{"default":"","title":"Status","type":"string"},"success":{"default":0,"title":"Success","type":"integer"},"total":{"default":0,"title":"Total","type":"integer"}},"required":["id"],"title":"ScanRunSummary","type":"object"},"ScanRunsListResponse":{"properties":{"runs":{"items":{"$ref":"#/components/schemas/ScanRunSummary"},"title":"Runs","type":"array"}},"title":"ScanRunsListResponse","type":"object"},"SceneTemplateCategoriesResponse":{"properties":{"categories":{"items":{"type":"string"},"title":"Categories","type":"array"}},"required":["categories"],"title":"SceneTemplateCategoriesResponse","type":"object"},"SceneTemplatesResponse":{"properties":{"items":{"items":{},"title":"Items","type":"array"}},"required":["items"],"title":"SceneTemplatesResponse","type":"object"},"ScreenshotResponse":{"description":"The storage key the in-app form hands back on `POST /contact`.","properties":{"key":{"title":"Key","type":"string"}},"required":["key"],"title":"ScreenshotResponse","type":"object"},"ScriptCard":{"properties":{"avatar_face":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Avatar Face"},"avatar_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Avatar Id"},"avatar_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Avatar Name"},"category_color":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Category Color"},"category_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Category Id"},"category_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Category Name"},"id":{"title":"Id","type":"integer"},"ig_comments":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Ig Comments"},"ig_display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Ig Display Name"},"ig_followers":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Ig Followers"},"ig_likes":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Ig Likes"},"ig_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Ig Url"},"ig_username":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Ig Username"},"ig_views":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Ig Views"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Notes"},"script_text":{"title":"Script Text","type":"string"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Source"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Status"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Title"},"updated_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Updated At"},"viral_score":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Viral Score"}},"required":["id","script_text"],"title":"ScriptCard","type":"object"},"ScriptDetailResponse":{"description":"Single-script GET response (alias for the form payload).","properties":{"avatar_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Avatar Id"},"id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Id"},"notes":{"title":"Notes","type":"string"},"script_text":{"title":"Script Text","type":"string"},"source":{"title":"Source","type":"string"},"title":{"title":"Title","type":"string"}},"required":["title","script_text","notes","source"],"title":"ScriptDetailResponse","type":"object"},"ScriptListView":{"properties":{"avatars":{"items":{"$ref":"#/components/schemas/AvatarOption"},"title":"Avatars","type":"array"},"cat_counts":{"additionalProperties":{"type":"integer"},"title":"Cat Counts","type":"object"},"categories":{"items":{"$ref":"#/components/schemas/CategoryRow"},"title":"Categories","type":"array"},"scraped_accounts":{"items":{"type":"string"},"title":"Scraped Accounts","type":"array"},"scripts":{"items":{"$ref":"#/components/schemas/ScriptCard"},"title":"Scripts","type":"array"}},"required":["scripts","avatars","categories","cat_counts","scraped_accounts"],"title":"ScriptListView","type":"object"},"SeriesPoint":{"description":"One point on the chart. EXACTLY ONE of `date` and `at` is set.\n\n`at` is a UTC hour, for the two short periods that draw hours (`today`\nand `24h`). `date` is a UTC day, or the Monday of a UTC ISO week once a\nlong period (`ytd`, `365d`) breaks the daily cap. A client reads whichever\none is present rather than guessing the bucket width from the count.","properties":{"at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"At"},"clicks":{"default":0,"title":"Clicks","type":"integer"},"date":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"title":"Date"},"earnings_cents":{"default":0,"title":"Earnings Cents","type":"integer"},"signups":{"default":0,"title":"Signups","type":"integer"}},"title":"SeriesPoint","type":"object"},"ServiceResponse":{"additionalProperties":true,"properties":{},"title":"ServiceResponse","type":"object"},"SetPasswordRequest":{"properties":{"password":{"maxLength":256,"minLength":6,"title":"Password","type":"string"}},"required":["password"],"title":"SetPasswordRequest","type":"object"},"SetPaymentMethodRequest":{"description":"Body for `POST /api/v1/billing/payment-method`.","properties":{"payment_method_id":{"title":"Payment Method Id","type":"string"}},"required":["payment_method_id"],"title":"SetPaymentMethodRequest","type":"object"},"SettingsValues":{"properties":{"default_image_resolution":{"default":"2K","title":"Default Image Resolution","type":"string"},"default_text_style":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Default Text Style"},"default_video_engine":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Default Video Engine"},"model_image":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Model Image"},"model_writing":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Model Writing"},"upscaler_backend":{"default":"lanczos","title":"Upscaler Backend","type":"string"}},"title":"SettingsValues","type":"object"},"SettingsViewResponse":{"additionalProperties":true,"properties":{"image_models":{"items":{},"title":"Image Models","type":"array"},"resolved_image":{"default":null,"title":"Resolved Image"},"resolved_writing":{"default":null,"title":"Resolved Writing"},"settings":{"$ref":"#/components/schemas/SettingsValues"},"user_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"User Id"},"writing_models":{"items":{},"title":"Writing Models","type":"array"}},"required":["settings"],"title":"SettingsViewResponse","type":"object"},"SetupIntentResponse":{"properties":{"client_secret":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Client Secret"},"setup_intent_id":{"title":"Setup Intent Id","type":"string"}},"required":["setup_intent_id"],"title":"SetupIntentResponse","type":"object"},"SetupStatusResponse":{"properties":{"avatar":{"title":"Avatar","type":"boolean"},"complete":{"title":"Complete","type":"boolean"},"done_count":{"title":"Done Count","type":"integer"},"followed":{"title":"Followed","type":"boolean"},"onboarding":{"title":"Onboarding","type":"boolean"},"steps":{"items":{"$ref":"#/components/schemas/SetupStepItem"},"title":"Steps","type":"array"},"total":{"title":"Total","type":"integer"},"video":{"title":"Video","type":"boolean"}},"required":["onboarding","avatar","video","followed","done_count","total","complete","steps"],"title":"SetupStatusResponse","type":"object"},"SetupStepItem":{"properties":{"done":{"title":"Done","type":"boolean"},"key":{"title":"Key","type":"string"},"locked":{"default":false,"title":"Locked","type":"boolean"},"required_plan":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Required Plan"},"required_plan_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Required Plan Name"}},"required":["key","done"],"title":"SetupStepItem","type":"object"},"ShotEditsPayload":{"description":"Optional input fixes for a shot regeneration (spec 2026-08-03).\n\n`transcript` replaces the spoken text (fresh TTS), `doing` replaces the\nshot's motion instruction on EVERY model (Kling reads it as the action\nprompt, HeyGen as the talking-head motion prompt; capped at\n`shot_reroll.SHOT_DOING_MAX_CHARS`, an empty string clears it), and\n`scene_image_id` swaps the source frame to another of the avatar's saved\nscenes (ownership checked in the service; a body-param id is the same\nBOLA risk as a path param).","properties":{"doing":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Doing"},"scene_image_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Scene Image Id"},"transcript":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Transcript"}},"title":"ShotEditsPayload","type":"object"},"ShotProgressItem":{"additionalProperties":true,"description":"One shot's live render status for the per-shot re-roll poll.\n\n`status` is the durable `render_shots` state (pending / submitted /\ncompleted / failed / skipped); `attempts` is the re-roll counter. The\nre-roll UI polls these so it can show a single shot re-rendering without\nthe whole video leaving its `completed` status.","properties":{"attempts":{"default":0,"title":"Attempts","type":"integer"},"awaiting_review":{"default":false,"title":"Awaiting Review","type":"boolean"},"candidate_clip":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Candidate Clip"},"shot_index":{"title":"Shot Index","type":"integer"},"status":{"title":"Status","type":"string"}},"required":["shot_index","status"],"title":"ShotProgressItem","type":"object"},"ShowcaseCard":{"description":"One admin card: the YAML roster entry merged with its DB row.","properties":{"followers":{"default":"","title":"Followers","type":"string"},"followersNumber":{"default":0,"title":"Followersnumber","type":"integer"},"handle":{"title":"Handle","type":"string"},"hideFromRail":{"default":false,"title":"Hidefromrail","type":"boolean"},"image":{"default":"","title":"Image","type":"string"},"name":{"title":"Name","type":"string"},"portraitNeedsRegen":{"default":false,"title":"Portraitneedsregen","type":"boolean"},"railPriority":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Railpriority"},"regenNote":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Regennote"},"slug":{"title":"Slug","type":"string"},"socialUrl":{"default":"","title":"Socialurl","type":"string"},"style":{"default":"realistic","title":"Style","type":"string"}},"required":["slug","name","handle"],"title":"ShowcaseCard","type":"object"},"ShowcaseResponse":{"description":"The three lists the admin page renders directly.","properties":{"hidden":{"default":[],"items":{"$ref":"#/components/schemas/ShowcaseCard"},"title":"Hidden","type":"array"},"rail":{"default":[],"items":{"$ref":"#/components/schemas/ShowcaseCard"},"title":"Rail","type":"array"},"stylized":{"default":[],"items":{"$ref":"#/components/schemas/ShowcaseCard"},"title":"Stylized","type":"array"}},"title":"ShowcaseResponse","type":"object"},"SlideResponse":{"properties":{"attempts":{"default":0,"title":"Attempts","type":"integer"},"avatar_pose":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Avatar Pose"},"background_image":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Background Image"},"body":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Body"},"composited_image":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Composited Image"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Error Message"},"headline":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Headline"},"id":{"title":"Id","type":"integer"},"layout_style":{"title":"Layout Style","type":"string"},"role":{"title":"Role","type":"string"},"slide_index":{"title":"Slide Index","type":"integer"},"status":{"title":"Status","type":"string"}},"required":["id","slide_index","role","layout_style","status"],"title":"SlideResponse","type":"object"},"SourceReelItem":{"additionalProperties":true,"description":"The reel a cloned video was copied from (Clone-a-Reel), shown as\nthe detail page's Source Reel rail card (Lior, 2026-08-15). None of\nthis is fabricated: url + duration come from the cached ingest,\nthumb is the first analyzed source frame, shot_count is the\nanalysis's shot list, and ingest_id powers the instant Copy Again\nhandoff.","properties":{"cloned_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Cloned At"},"duration_seconds":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Duration Seconds"},"ingest_id":{"title":"Ingest Id","type":"integer"},"shot_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Shot Count"},"thumb":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Thumb"},"url":{"title":"Url","type":"string"}},"required":["ingest_id","url"],"title":"SourceReelItem","type":"object"},"StatsLifetime":{"description":"The all-time numbers, which never move when the range tab changes.\n\n`paying_now` is a snapshot, not a total: the referrals whose status right\nnow is `paying` or `past_due`. A past-due subscriber is still a customer\nthe affiliate earned, they are simply late.","properties":{"clicks":{"default":0,"title":"Clicks","type":"integer"},"paying_now":{"default":0,"title":"Paying Now","type":"integer"},"revenue_referred_cents":{"default":0,"title":"Revenue Referred Cents","type":"integer"},"signups":{"default":0,"title":"Signups","type":"integer"}},"title":"StatsLifetime","type":"object"},"StatsRates":{"description":"The two conversion rates, as floats 0..1, over the RANGE's totals.\n\nNull, never zero, when the denominator is zero: \"no clicks yet\" and \"100\nclicks and no signups\" are different facts and a dashboard that printed\n0% for both would be lying about the first one.","properties":{"click_to_signup":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Click To Signup"},"signup_to_paying":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Signup To Paying"}},"title":"StatsRates","type":"object"},"StatsTotals":{"description":"What happened inside the range.\n\nEVERY field counts referrals ATTRIBUTED IN THE RANGE, never all of them.\n`signups` is how many there were, `trials` how many of those ever started\na trial (the subscription carries a `trial_end` for life, so this is not\n\"trialing right now\"), `paying` how many of those have at least one paid\ninvoice booked in the range. The last three are CURRENT status counts\namong the referrals attributed in the range, so a user who signed up in\nthe range and churned yesterday is counted once, under `churned`.","properties":{"churned":{"default":0,"title":"Churned","type":"integer"},"clicks":{"default":0,"title":"Clicks","type":"integer"},"past_due":{"default":0,"title":"Past Due","type":"integer"},"paying":{"default":0,"title":"Paying","type":"integer"},"refunded":{"default":0,"title":"Refunded","type":"integer"},"signups":{"default":0,"title":"Signups","type":"integer"},"trials":{"default":0,"title":"Trials","type":"integer"}},"title":"StatsTotals","type":"object"},"StockAssetRef":{"properties":{"asset_type":{"enum":["music","footage"],"title":"Asset Type","type":"string"},"provider_asset_id":{"maxLength":64,"minLength":1,"title":"Provider Asset Id","type":"string"}},"required":["asset_type","provider_asset_id"],"title":"StockAssetRef","type":"object"},"StockSearchItemOut":{"properties":{"artist":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Artist"},"asset_type":{"title":"Asset Type","type":"string"},"duration_seconds":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Duration Seconds"},"preview_url":{"title":"Preview Url","type":"string"},"provider_asset_id":{"title":"Provider Asset Id","type":"string"},"thumbnail_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Thumbnail Url"},"title":{"title":"Title","type":"string"}},"required":["provider_asset_id","asset_type","title","preview_url"],"title":"StockSearchItemOut","type":"object"},"StockSearchResponse":{"properties":{"has_more":{"title":"Has More","type":"boolean"},"items":{"items":{"$ref":"#/components/schemas/StockSearchItemOut"},"title":"Items","type":"array"},"total_count":{"title":"Total Count","type":"integer"}},"required":["items","total_count","has_more"],"title":"StockSearchResponse","type":"object"},"StoreRequestResponse":{"description":"The caller's saved picks.","properties":{"claimed":{"title":"Claimed","type":"boolean"},"niche":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Niche"},"price_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Price Cents"},"product_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Product Key"},"theme":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Theme"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"upload_bytes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Upload Bytes"},"upload_filename":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Upload Filename"}},"required":["niche","product_key","upload_filename","upload_bytes","title","price_cents","theme","claimed"],"title":"StoreRequestResponse","type":"object"},"StoriesRequest":{"properties":{"age":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Age"},"avatar_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Avatar Id"},"gender":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Gender"},"origin":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Origin"},"religion":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Religion"},"topic":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Topic"}},"title":"StoriesRequest","type":"object"},"StoriesResponse":{"properties":{"stories":{"default":[],"items":{"type":"string"},"title":"Stories","type":"array"}},"title":"StoriesResponse","type":"object"},"SubscriptionStateRunRequest":{"description":"Body of `POST /api/v1/admin/metrics/subscription-state/run`; empty means yesterday (UTC).","properties":{"as_of_date":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"title":"As Of Date"}},"title":"SubscriptionStateRunRequest","type":"object"},"SubscriptionStateRunResponse":{"properties":{"as_of_date":{"format":"date","title":"As Of Date","type":"string"},"env":{"title":"Env","type":"string"},"queued":{"title":"Queued","type":"boolean"}},"required":["env","as_of_date","queued"],"title":"SubscriptionStateRunResponse","type":"object"},"SubscriptionStatusResponse":{"properties":{"can_create_scene":{"default":false,"title":"Can Create Scene","type":"boolean"},"can_create_video":{"default":false,"title":"Can Create Video","type":"boolean"},"cancel_at_period_end":{"default":false,"title":"Cancel At Period End","type":"boolean"},"credits":{"anyOf":[{"$ref":"#/components/schemas/CreditSummaryResponse"},{"type":"null"}],"default":null},"current_period_end":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Current Period End"},"entitlements":{"anyOf":[{"$ref":"#/components/schemas/EntitlementsResponse"},{"type":"null"}],"default":null},"free_quota":{"anyOf":[{"$ref":"#/components/schemas/FreeQuotaResponse"},{"type":"null"}],"default":null},"has_subscription":{"title":"Has Subscription","type":"boolean"},"influencer_addon":{"default":false,"title":"Influencer Addon","type":"boolean"},"interval":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Interval"},"is_trialing":{"default":false,"title":"Is Trialing","type":"boolean"},"meta_purchase_currency":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Meta Purchase Currency"},"meta_purchase_event_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Meta Purchase Event Id"},"meta_purchase_value":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Meta Purchase Value"},"meta_trial_event_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Meta Trial Event Id"},"paused_until":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Paused Until"},"pending_effective_at":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Pending Effective At"},"pending_interval":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Pending Interval"},"pending_plan_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Pending Plan Slug"},"plan_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Plan Slug"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Status"},"trial_end":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Trial End"},"trial_video_used":{"default":false,"title":"Trial Video Used","type":"boolean"}},"required":["has_subscription"],"title":"SubscriptionStatusResponse","type":"object"},"SubtitleStatusResponse":{"properties":{"done":{"title":"Done","type":"boolean"},"file":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"File"}},"required":["done"],"title":"SubtitleStatusResponse","type":"object"},"SuggestRequest":{"description":"Body for POST /suggest. Validation of length happens in the route so an\nempty value returns a clean 400 (not a 422 pydantic envelope).","properties":{"name":{"default":"","title":"Name","type":"string"}},"title":"SuggestRequest","type":"object"},"Surface":{"description":"Which form sent this. It rides into the mail and into the event.","enum":["marketing","app"],"title":"Surface","type":"string"},"TagCount":{"properties":{"count":{"title":"Count","type":"integer"},"tag":{"title":"Tag","type":"string"}},"required":["tag","count"],"title":"TagCount","type":"object"},"TagsResponse":{"properties":{"tags":{"items":{"additionalProperties":true,"type":"object"},"title":"Tags","type":"array"}},"title":"TagsResponse","type":"object"},"TelegramOkResponse":{"properties":{"ok":{"default":true,"title":"Ok","type":"boolean"}},"title":"TelegramOkResponse","type":"object"},"TelegramSendResponse":{"additionalProperties":true,"properties":{"ok":{"default":true,"title":"Ok","type":"boolean"}},"title":"TelegramSendResponse","type":"object"},"TemplateResponse":{"properties":{"description":{"title":"Description","type":"string"},"key":{"title":"Key","type":"string"},"max_slides":{"default":10,"title":"Max Slides","type":"integer"},"min_slides":{"default":3,"title":"Min Slides","type":"integer"},"name":{"title":"Name","type":"string"}},"required":["key","name","description"],"title":"TemplateResponse","type":"object"},"TemplatesResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/TemplateResponse"},"title":"Items","type":"array"}},"title":"TemplatesResponse","type":"object"},"TodayStats":{"properties":{"completed":{"default":0,"title":"Completed","type":"integer"},"failed":{"default":0,"title":"Failed","type":"integer"},"pending":{"default":0,"title":"Pending","type":"integer"},"running":{"default":0,"title":"Running","type":"integer"}},"title":"TodayStats","type":"object"},"ToggleFavoriteRequest":{"description":"Body for POST /api/v1/prefs/favorites.","properties":{"kind":{"title":"Kind","type":"string"},"ref_id":{"title":"Ref Id","type":"integer"}},"required":["kind","ref_id"],"title":"ToggleFavoriteRequest","type":"object"},"ToggleFavoriteResponse":{"properties":{"favorited":{"title":"Favorited","type":"boolean"},"kind":{"title":"Kind","type":"string"},"ok":{"title":"Ok","type":"boolean"},"ref_id":{"title":"Ref Id","type":"integer"}},"required":["ok","kind","ref_id","favorited"],"title":"ToggleFavoriteResponse","type":"object"},"ToggleResponse":{"properties":{"key":{"title":"Key","type":"string"},"voted":{"title":"Voted","type":"boolean"},"votes":{"title":"Votes","type":"integer"}},"required":["key","votes","voted"],"title":"ToggleResponse","type":"object"},"TopReel":{"properties":{"account":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url"},"views":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Views"}},"required":["account","views","url"],"title":"TopReel","type":"object"},"TrackNewAccountRequest":{"description":"Canonical create body for POST /api/v1/followed-accounts.\n\nAudit-spec shape (Phase 2B, 2026-05-25): platform + handle. The\nlegacy /add route remains for backwards compat with the older\ntemplate flow; new clients should call POST \"\" with this body.","properties":{"handle":{"default":"","title":"Handle","type":"string"},"platform":{"default":"instagram","title":"Platform","type":"string"}},"title":"TrackNewAccountRequest","type":"object"},"TrackedAccountResponse":{"description":"Row representation returned by POST /api/v1/followed-accounts.\n\nFields mirror what the list endpoint returns for the same row so the\nSPA can prepend the new row to its cache without an extra refetch.\nReal follower-count / profile-pic enrichment is deferred to a\nbackground job (Phase 2B follow-up).","properties":{"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Display Name"},"follower_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Follower Count"},"handle":{"title":"Handle","type":"string"},"id":{"title":"Id","type":"integer"},"is_global":{"default":false,"title":"Is Global","type":"boolean"},"is_shared":{"default":false,"title":"Is Shared","type":"boolean"},"last_synced_at":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Last Synced At"},"platform":{"title":"Platform","type":"string"},"profile_picture_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Picture Url"},"reels_indexed":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Reels Indexed"}},"required":["id","platform","handle"],"title":"TrackedAccountResponse","type":"object"},"TrackedAccountRow":{"properties":{"id":{"title":"Id","type":"integer"},"username":{"title":"Username","type":"string"}},"required":["id","username"],"title":"TrackedAccountRow","type":"object"},"TrendingIdea":{"description":"One trending avatar-character concept from the ideation generator.\n\n``title`` is the only required field; the rest are the generator's rich\npersona hints (kept typed rather than dropped so the MCP ``get_trending``\ntool and any future consumer can use them without a 500).","properties":{"description":{"default":"","title":"Description","type":"string"},"niche":{"default":"","title":"Niche","type":"string"},"origin":{"default":"","title":"Origin","type":"string"},"outfit":{"default":"","title":"Outfit","type":"string"},"religion":{"default":"","title":"Religion","type":"string"},"title":{"title":"Title","type":"string"},"why_trending":{"default":"","title":"Why Trending","type":"string"}},"required":["title"],"title":"TrendingIdea","type":"object"},"TrendingIdeasRequest":{"properties":{"age":{"default":"","title":"Age","type":"string"},"gender":{"default":"","title":"Gender","type":"string"},"niche":{"default":"","title":"Niche","type":"string"},"origin":{"default":"","title":"Origin","type":"string"},"religion":{"default":"","title":"Religion","type":"string"}},"title":"TrendingIdeasRequest","type":"object"},"TrendingIdeasResponse":{"properties":{"ideas":{"default":[],"items":{"$ref":"#/components/schemas/TrendingIdea"},"title":"Ideas","type":"array"}},"title":"TrendingIdeasResponse","type":"object"},"TrendingReelsResponse":{"properties":{"rows":{"items":{"$ref":"#/components/schemas/ReelTableRow"},"title":"Rows","type":"array"}},"title":"TrendingReelsResponse","type":"object"},"TriggerSourceRequest":{"properties":{"triggered_by":{"default":"manual","title":"Triggered By","type":"string"}},"title":"TriggerSourceRequest","type":"object"},"UnseenNotificationsResponse":{"description":"GET /unseen payload: oldest first so toasts stack chronologically.","properties":{"notifications":{"items":{"$ref":"#/components/schemas/NotificationItem"},"title":"Notifications","type":"array"}},"required":["notifications"],"title":"UnseenNotificationsResponse","type":"object"},"UpdateAccountCategoriesRequest":{"properties":{"category_ids":{"items":{"type":"integer"},"title":"Category Ids","type":"array"},"primary":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Primary"}},"title":"UpdateAccountCategoriesRequest","type":"object"},"UpdateAccountCategoryRequest":{"properties":{"category_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Category Id"}},"title":"UpdateAccountCategoryRequest","type":"object"},"UpdateAccountTagsRequest":{"properties":{"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"string"},{"type":"null"}],"default":null,"title":"Tags"}},"title":"UpdateAccountTagsRequest","type":"object"},"UpdateAvatarRequest":{"additionalProperties":false,"description":"Payload for ``PATCH /api/v1/avatars/<id>``.\n\nPartial update for the editable identity fields surfaced as pencil\nicons on the avatar-detail page. Every field is optional; the empty\nbody is a no-op (returns the current state with 200).\n\nUnknown fields are rejected (``extra=\"forbid\"``) so the SPA can't\nsilently drift the schema. Length limits are conservative defaults\nmatching the design-preview text-field affordances; tune later as\nthe form grows.\n\nOut-of-scope (not editable via this endpoint, each has its own\ndedicated flow):\n\n- ``face_image``       \u2192 ``/api/v1/avatars/<id>/face`` (upload)\n- ``voice_id``         \u2192 voice-generation pipeline (wizard step-voice)\n- ``heygen_avatar_id`` \u2192 HeyGen post-save jobs\n\n\"niche\" is a frontend-only concept; this endpoint accepts the\ncanonical ``category_id`` (FK to ``account_categories``). The SPA's\n``resolveCategoryId(nicheKey, categories)`` turns the wizard niche\ninto a category id before posting.","properties":{"category_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Category Id"},"description":{"anyOf":[{"maxLength":1000,"type":"string"},{"type":"null"}],"default":null,"title":"Description"},"forbidden_topics":{"anyOf":[{"maxLength":1000,"type":"string"},{"type":"null"}],"default":null,"title":"Forbidden Topics"},"image_prompt":{"anyOf":[{"maxLength":2000,"type":"string"},{"type":"null"}],"default":null,"title":"Image Prompt"},"name":{"anyOf":[{"maxLength":200,"minLength":1,"type":"string"},{"type":"null"}],"default":null,"title":"Name"},"signature_phrases":{"anyOf":[{"maxLength":2000,"type":"string"},{"type":"null"}],"default":null,"title":"Signature Phrases"},"story":{"anyOf":[{"maxLength":5000,"type":"string"},{"type":"null"}],"default":null,"title":"Story"},"target_audience":{"anyOf":[{"maxLength":1000,"type":"string"},{"type":"null"}],"default":null,"title":"Target Audience"},"voice_description":{"anyOf":[{"maxLength":2000,"type":"string"},{"type":"null"}],"default":null,"title":"Voice Description"}},"title":"UpdateAvatarRequest","type":"object"},"UpdateCaptionRequest":{"properties":{"caption":{"default":"","title":"Caption","type":"string"}},"title":"UpdateCaptionRequest","type":"object"},"UpdateCaptionResponse":{"properties":{"success":{"title":"Success","type":"boolean"}},"required":["success"],"title":"UpdateCaptionResponse","type":"object"},"UpdateSlideCopyBody":{"description":"PATCH .../slides/<id>: edit stored copy (text-only, free).","properties":{"body":{"anyOf":[{"maxLength":240,"type":"string"},{"type":"null"}],"default":null,"title":"Body"},"headline":{"anyOf":[{"maxLength":60,"type":"string"},{"type":"null"}],"default":null,"title":"Headline"}},"title":"UpdateSlideCopyBody","type":"object"},"UploadBody":{"properties":{"credit_cost":{"default":null,"title":"Credit Cost"},"duration":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Duration"},"extraction_level":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Extraction Level"},"ig_username":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Ig Username"},"script":{"default":"","title":"Script","type":"string"},"upsert":{"default":true,"title":"Upsert","type":"boolean"},"url":{"default":"","title":"Url","type":"string"},"visual_breakdown":{"default":null,"title":"Visual Breakdown"}},"title":"UploadBody","type":"object"},"UploadResponse":{"description":"What the upload route stored.","properties":{"bytes":{"title":"Bytes","type":"integer"},"filename":{"title":"Filename","type":"string"},"kind":{"enum":["pdf","txt"],"title":"Kind","type":"string"}},"required":["filename","bytes","kind"],"title":"UploadResponse","type":"object"},"UsageKpis":{"properties":{"avatars_created":{"$ref":"#/components/schemas/KpiValue"},"carousels_created":{"$ref":"#/components/schemas/KpiValue"},"credits_used":{"$ref":"#/components/schemas/KpiValue"},"dau":{"$ref":"#/components/schemas/KpiFloat"},"failure_rate_pct":{"$ref":"#/components/schemas/KpiFloat"},"mau":{"$ref":"#/components/schemas/KpiValue"},"videos_completed":{"$ref":"#/components/schemas/KpiValue"},"videos_failed":{"$ref":"#/components/schemas/KpiValue"},"videos_started":{"$ref":"#/components/schemas/KpiValue"},"wau":{"$ref":"#/components/schemas/KpiValue"}},"required":["dau","wau","mau","videos_started","videos_completed","videos_failed","failure_rate_pct","credits_used","avatars_created","carousels_created"],"title":"UsageKpis","type":"object"},"UsagePoint":{"properties":{"avatars_created":{"title":"Avatars Created","type":"integer"},"bucket":{"format":"date","title":"Bucket","type":"string"},"carousels_created":{"title":"Carousels Created","type":"integer"},"credits_used":{"title":"Credits Used","type":"integer"},"dau":{"title":"Dau","type":"number"},"failure_rate_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Failure Rate Pct"},"mau":{"title":"Mau","type":"integer"},"videos_completed":{"title":"Videos Completed","type":"integer"},"videos_failed":{"title":"Videos Failed","type":"integer"},"videos_started":{"title":"Videos Started","type":"integer"},"wau":{"title":"Wau","type":"integer"}},"required":["bucket","dau","wau","mau","videos_started","videos_completed","videos_failed","failure_rate_pct","credits_used","avatars_created","carousels_created"],"title":"UsagePoint","type":"object"},"UsageResponse":{"properties":{"compare":{"enum":["previous","yoy","none"],"title":"Compare","type":"string"},"compare_from":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"title":"Compare From"},"compare_series":{"anyOf":[{"items":{"$ref":"#/components/schemas/UsagePoint"},"type":"array"},{"type":"null"}],"title":"Compare Series"},"compare_to":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"title":"Compare To"},"currency":{"const":"USD","default":"USD","title":"Currency","type":"string"},"env":{"enum":["production","staging","local","test"],"title":"Env","type":"string"},"estimated_before":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"title":"Estimated Before"},"filters":{"items":{"$ref":"#/components/schemas/FilterEcho"},"title":"Filters","type":"array"},"freshness":{"$ref":"#/components/schemas/FreshnessSummary"},"from":{"format":"date","title":"From","type":"string"},"granularity":{"enum":["day","week","month"],"title":"Granularity","type":"string"},"kpis":{"$ref":"#/components/schemas/UsageKpis"},"meta":{"$ref":"#/components/schemas/ResponseMeta"},"notes":{"items":{"type":"string"},"title":"Notes","type":"array"},"series":{"items":{"$ref":"#/components/schemas/UsagePoint"},"title":"Series","type":"array"},"to":{"format":"date","title":"To","type":"string"}},"required":["env","from","to","granularity","compare","compare_from","compare_to","freshness","meta","kpis","series","compare_series"],"title":"UsageResponse","type":"object"},"ValidationErrorModel":{"properties":{"ctx":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"An optional object which contains values required to render the error message.","title":"Error context"},"input":{"description":"The input provided for validation.","title":"Input"},"loc":{"description":"The error's location as a list.","items":{},"title":"Location","type":"array"},"msg":{"description":"A human readable explanation of the error.","title":"Message","type":"string"},"type":{"description":"A computer-readable identifier of the error type.","title":"Error Type","type":"string"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The URL to further information about the error.","title":"URL"}},"required":["type","loc","msg","input"],"title":"ValidationErrorModel","type":"object"},"VideoAssetItem":{"additionalProperties":true,"description":"One asset on the video detail page's \"Assets In This Video\" rail.\n\nWire shape (spec 2026-06-26): `video_file` is the bare filename under\nthe videos/ prefix (resolved client-side by `resolveVideoFileUrl`);\n`source_image` is the scene still under the faces/ prefix (resolved by\n`resolveFaceImage`), present for `scene` assets only.","properties":{"duration_seconds":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Duration Seconds"},"file_size_bytes":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"File Size Bytes"},"id":{"title":"Id","type":"integer"},"kind":{"title":"Kind","type":"string"},"label":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Label"},"scene_index":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Scene Index"},"source_image":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Source Image"},"video_file":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Video File"}},"required":["id","kind"],"title":"VideoAssetItem","type":"object"},"VideoCaptionsResponse":{"description":"The word timings captured while burning subtitles; empty for\nvideos rendered before capture shipped (the editor then opens\nwithout seeded captions).","properties":{"words":{"items":{"$ref":"#/components/schemas/CaptionWordItem"},"title":"Words","type":"array"}},"required":["words"],"title":"VideoCaptionsResponse","type":"object"},"VideoDetailResponse":{"additionalProperties":true,"properties":{"approval_status":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Approval Status"},"assets":{"default":[],"items":{"$ref":"#/components/schemas/VideoAssetItem"},"title":"Assets","type":"array"},"audio_file":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Audio File"},"avatar":{"anyOf":[{"$ref":"#/components/schemas/GalleryAvatar"},{"type":"null"}],"default":null},"avatar_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Avatar Id"},"background":{"anyOf":[{"$ref":"#/components/schemas/GalleryBackground"},{"type":"null"}],"default":null},"background_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Background Id"},"caption_cuts":{"default":[],"items":{"$ref":"#/components/schemas/CaptionCut"},"title":"Caption Cuts","type":"array"},"captions_ready":{"default":false,"title":"Captions Ready","type":"boolean"},"clean_master_file":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Clean Master File"},"completed_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Completed At"},"composition_json":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Composition Json"},"created_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Created At"},"draft_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Draft Id"},"duration_seconds":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Duration Seconds"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Error Message"},"estimated_duration_seconds":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Estimated Duration Seconds"},"final_video_file":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Final Video File"},"has_post":{"default":false,"title":"Has Post","type":"boolean"},"heygen_video_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Heygen Video Id"},"id":{"title":"Id","type":"integer"},"ig_account":{"anyOf":[{"$ref":"#/components/schemas/VideoIgAccount"},{"type":"null"}],"default":null},"ig_caption":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Ig Caption"},"needs_rebuild":{"default":false,"title":"Needs Rebuild","type":"boolean"},"original_video_file":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Original Video File"},"publishing":{"$ref":"#/components/schemas/VideoPublishing","default":{"instagram":{"account_name":null,"connected":false,"posted":false},"tiktok":{"account_name":null,"connected":false,"posted":false}}},"raw_video_file":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Raw Video File"},"render_error":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Render Error"},"render_strategy":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Render Strategy"},"script_text":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Script Text"},"segments":{"default":[],"items":{"$ref":"#/components/schemas/VideoSegment"},"title":"Segments","type":"array"},"shots":{"default":[],"items":{"$ref":"#/components/schemas/VideoShotItem"},"title":"Shots","type":"array"},"shots_submitted":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Shots Submitted"},"source_reel":{"anyOf":[{"$ref":"#/components/schemas/SourceReelItem"},{"type":"null"}],"default":null},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Status"},"supports_caption_styles":{"default":true,"title":"Supports Caption Styles","type":"boolean"},"template_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Template Id"},"text_style":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Text Style"},"thumbnail_file":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Thumbnail File"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Title"}},"required":["id"],"title":"VideoDetailResponse","type":"object"},"VideoFeedbackRequest":{"description":"Body for `POST /api/v1/videos/:id/rating/feedback`. `reasons` are keys\nfrom `video_rating.REASONS`; `skipped` drops both reasons and note.","properties":{"note":{"anyOf":[{"maxLength":1000,"type":"string"},{"type":"null"}],"default":null,"title":"Note"},"reasons":{"items":{"type":"string"},"maxItems":10,"title":"Reasons","type":"array"},"skipped":{"default":false,"title":"Skipped","type":"boolean"}},"title":"VideoFeedbackRequest","type":"object"},"VideoGalleryCounts":{"additionalProperties":true,"description":"Per-status counts across the FULL (unpaginated) filtered set.","properties":{"all":{"default":0,"title":"All","type":"integer"},"drafts":{"default":0,"title":"Drafts","type":"integer"},"failed":{"default":0,"title":"Failed","type":"integer"},"published":{"default":0,"title":"Published","type":"integer"},"published_today":{"default":0,"title":"Published Today","type":"integer"},"rendering":{"default":0,"title":"Rendering","type":"integer"},"this_month":{"default":0,"title":"This Month","type":"integer"}},"title":"VideoGalleryCounts","type":"object"},"VideoGalleryResponse":{"properties":{"counts":{"anyOf":[{"$ref":"#/components/schemas/VideoGalleryCounts"},{"type":"null"}],"default":null},"has_more":{"default":false,"title":"Has More","type":"boolean"},"items":{"items":{"$ref":"#/components/schemas/GalleryVideoCard"},"title":"Items","type":"array"},"page":{"default":1,"title":"Page","type":"integer"},"page_size":{"default":24,"title":"Page Size","type":"integer"},"total":{"default":0,"title":"Total","type":"integer"}},"required":["items"],"title":"VideoGalleryResponse","type":"object"},"VideoIgAccount":{"additionalProperties":true,"properties":{"account_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Account Name"},"id":{"title":"Id","type":"integer"},"platform":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Platform"}},"required":["id"],"title":"VideoIgAccount","type":"object"},"VideoPublishing":{"additionalProperties":true,"description":"Bundle of per-platform publish state for the Publishing card.","properties":{"instagram":{"$ref":"#/components/schemas/PlatformPublishState","default":{"account_name":null,"connected":false,"posted":false}},"tiktok":{"$ref":"#/components/schemas/PlatformPublishState","default":{"account_name":null,"connected":false,"posted":false}}},"title":"VideoPublishing","type":"object"},"VideoRatingPayload":{"description":"The caller's stored rating of a video (the Video Detail feedback strip).","properties":{"feedback_submitted":{"title":"Feedback Submitted","type":"boolean"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Note"},"rating":{"title":"Rating","type":"integer"},"reasons":{"items":{"type":"string"},"title":"Reasons","type":"array"}},"required":["rating","reasons","feedback_submitted"],"title":"VideoRatingPayload","type":"object"},"VideoRatingResponse":{"description":"Response for the `/api/v1/videos/:id/rating` routes. `rating` is null\nuntil the caller has rated the video.","properties":{"rating":{"anyOf":[{"$ref":"#/components/schemas/VideoRatingPayload"},{"type":"null"}],"default":null}},"title":"VideoRatingResponse","type":"object"},"VideoSegment":{"additionalProperties":true,"properties":{"text":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Text"}},"title":"VideoSegment","type":"object"},"VideoShotItem":{"additionalProperties":true,"description":"One original shot spec on the video detail page, reconstructed from\nthe durable `render_shots.spec_json` written at render time.\n\nThis is the source for the \"Generate Similar\" prefill: the wizard\nrebuilds its shot list from these exactly as the user configured them\n(model, action text, per-shot transcript, length, scene). `scene_image`\nis the scene still's bare filename under the faces/ prefix (resolved\nclient-side by `resolveFaceImage`).","properties":{"action_lead_seconds":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Action Lead Seconds"},"awaiting_review":{"default":false,"title":"Awaiting Review","type":"boolean"},"candidate_clip":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Candidate Clip"},"chain_guard_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Chain Guard Reason"},"chain_start":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Chain Start"},"doing":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Doing"},"identity_score":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Identity Score"},"identity_verdict":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Identity Verdict"},"model":{"title":"Model","type":"string"},"reroll_cost":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Reroll Cost"},"scene_image":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Scene Image"},"scene_source":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Scene Source"},"scene_title":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Scene Title"},"seconds":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Seconds"},"shot_index":{"title":"Shot Index","type":"integer"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Status"},"transcript":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Transcript"}},"required":["shot_index","model"],"title":"VideoShotItem","type":"object"},"VideoStatusResponse":{"additionalProperties":true,"description":"Lightweight status payload for /generate/<id>/status hydration.\n\nAlso the payload the video library's rendering cards poll, so it\ncarries the live render trio \u2014 `progress` (0-100), `progress_label`\n(\"Shot 2 of 3 \u00b7 Kling\") and `eta_seconds` (honest countdown learned\nfrom the user's render history). All None when not rendering.\n\nPhase 3 adds the progressive-reveal trio for multi-shot renders:\n`shots_ready` / `shots_total` (the \"X of N shots ready\" line) and\n`ready_scenes` (the finished per-shot clips available so far). Zero /\nempty for a single-job (non-multi-shot) render.\n\nThe Shot Quality Feedback Loop adds `shots` (per-shot render status, so\nthe re-roll UI can poll one shot) and `needs_rebuild` (the Full Cut is\nstale until a rebuild).","properties":{"avatar_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Avatar Id"},"avatar_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Avatar Name"},"elapsed_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Elapsed Seconds"},"eta_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Eta Seconds"},"final_video_file":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Final Video File"},"id":{"title":"Id","type":"integer"},"needs_rebuild":{"default":false,"title":"Needs Rebuild","type":"boolean"},"progress":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Progress"},"progress_label":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Progress Label"},"ready_scenes":{"default":[],"items":{"$ref":"#/components/schemas/ReadySceneItem"},"title":"Ready Scenes","type":"array"},"script_text":{"default":"","title":"Script Text","type":"string"},"shots":{"default":[],"items":{"$ref":"#/components/schemas/ShotProgressItem"},"title":"Shots","type":"array"},"shots_ready":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Shots Ready"},"shots_total":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Shots Total"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Status"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Title"}},"required":["id"],"title":"VideoStatusResponse","type":"object"},"ViewPrefsResponse":{"properties":{"filters":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"title":"Filters"},"page_key":{"title":"Page Key","type":"string"}},"required":["page_key"],"title":"ViewPrefsResponse","type":"object"},"ViralRadarUsage":{"description":"The caller's Viral Radar quota position, for the page-head display.\n\nOne plan number caps both axes: accounts tracked and account-scans per\nday (UTC). Omitted (None on the parent) for admins, who bypass quotas.","properties":{"accounts_used":{"title":"Accounts Used","type":"integer"},"limit":{"title":"Limit","type":"integer"},"scans_used_today":{"title":"Scans Used Today","type":"integer"}},"required":["limit","accounts_used","scans_used_today"],"title":"ViralRadarUsage","type":"object"},"VoiceItem":{"properties":{"category":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Category"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Name"},"preview_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Preview Url"},"voice_id":{"title":"Voice Id","type":"string"}},"required":["voice_id"],"title":"VoiceItem","type":"object"},"VoicesResponse":{"properties":{"voices":{"items":{"$ref":"#/components/schemas/VoiceItem"},"title":"Voices","type":"array"}},"title":"VoicesResponse","type":"object"},"WebhookAck":{"properties":{"duplicate":{"anyOf":[{"type":"boolean"},{"type":"null"}],"default":null,"title":"Duplicate"},"ok":{"title":"Ok","type":"boolean"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Type"}},"required":["ok"],"title":"WebhookAck","type":"object"},"WebhookEventRequest":{"description":"HeyGen webhook payload \u2014 event_type + event_data envelope.","properties":{"event_data":{"additionalProperties":true,"title":"Event Data","type":"object"},"event_type":{"default":"","title":"Event Type","type":"string"}},"title":"WebhookEventRequest","type":"object"},"WebhookResponse":{"properties":{"message":{"default":"","title":"Message","type":"string"},"ok":{"title":"Ok","type":"boolean"}},"required":["ok"],"title":"WebhookResponse","type":"object"},"WizardAvatarOption":{"properties":{"default_text_style":{"default":"white_text","title":"Default Text Style","type":"string"},"description":{"default":"","title":"Description","type":"string"},"face_focus":{"anyOf":[{"$ref":"#/components/schemas/FaceFocusPoint"},{"type":"null"}],"default":null},"face_image":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Face Image"},"id":{"title":"Id","type":"integer"},"name":{"title":"Name","type":"string"},"story":{"default":"","title":"Story","type":"string"},"voice_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Voice Id"}},"required":["id","name"],"title":"WizardAvatarOption","type":"object"},"WizardBackground":{"properties":{"category":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Category"},"id":{"title":"Id","type":"integer"},"image_file":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Image File"},"name":{"title":"Name","type":"string"}},"required":["id","name"],"title":"WizardBackground","type":"object"},"WizardBootstrapResponse":{"properties":{"avatars":{"default":[],"items":{},"title":"Avatars","type":"array"},"categories":{"default":[],"items":{},"title":"Categories","type":"array"},"scripts":{"default":[],"items":{},"title":"Scripts","type":"array"},"templates":{"default":[],"items":{},"title":"Templates","type":"array"}},"title":"WizardBootstrapResponse","type":"object"},"WizardDraftView":{"properties":{"current_step":{"default":1,"title":"Current Step","type":"integer"},"draft_data":{"additionalProperties":true,"title":"Draft Data","type":"object"},"id":{"title":"Id","type":"integer"}},"required":["id"],"title":"WizardDraftView","type":"object"},"WizardScene":{"additionalProperties":true,"properties":{"filename":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Filename"},"heygen_photo_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Heygen Photo Id"},"id":{"title":"Id","type":"integer"},"is_primary":{"default":false,"title":"Is Primary","type":"boolean"},"scene_title":{"default":"","title":"Scene Title","type":"string"}},"required":["id"],"title":"WizardScene","type":"object"},"WizardSessionResponse":{"properties":{"avatars":{"items":{"$ref":"#/components/schemas/WizardAvatarOption"},"title":"Avatars","type":"array"},"backgrounds":{"items":{"$ref":"#/components/schemas/WizardBackground"},"title":"Backgrounds","type":"array"},"draft":{"anyOf":[{"$ref":"#/components/schemas/WizardDraftView"},{"type":"null"}],"default":null},"scenes_by_avatar":{"additionalProperties":{"items":{"$ref":"#/components/schemas/WizardScene"},"type":"array"},"title":"Scenes By Avatar","type":"object"}},"title":"WizardSessionResponse","type":"object"},"_ArchiveResponse":{"properties":{"archived":{"title":"Archived","type":"integer"},"success":{"title":"Success","type":"boolean"}},"required":["success","archived"],"title":"_ArchiveResponse","type":"object"},"_SegmentRerunBody":{"description":"Fix This Part: which model renders the part again and what the user wants changed.\nBoth optional; the model defaults to the part's own.","properties":{"model_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Model Id"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Note"}},"title":"_SegmentRerunBody","type":"object"},"_SegmentResolveBody":{"properties":{"keep":{"enum":["new","old"],"title":"Keep","type":"string"}},"required":["keep"],"title":"_SegmentResolveBody","type":"object"},"_SendBody":{"properties":{"chat_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Chat Id"},"text":{"default":"","title":"Text","type":"string"}},"title":"_SendBody","type":"object"},"_SetMainImageResponse":{"properties":{"face_image":{"title":"Face Image","type":"string"},"image_id":{"title":"Image Id","type":"integer"},"success":{"title":"Success","type":"boolean"}},"required":["success","image_id","face_image"],"title":"_SetMainImageResponse","type":"object"},"_VariationsBody":{"properties":{"count":{"default":2,"title":"Count","type":"integer"},"prompt":{"default":"","title":"Prompt","type":"string"}},"title":"_VariationsBody","type":"object"},"_VariationsResponse":{"properties":{"outfits":{"items":{"type":"string"},"title":"Outfits","type":"array"}},"required":["outfits"],"title":"_VariationsResponse","type":"object"}},"securitySchemes":{"bearer_jwt":{"bearerFormat":"JWT","description":"Cognito-issued `id_token` (or `access_token`) in `Authorization: Bearer \u2026`. Used by the React SPA and external scripts. Take any of the tokens from a /login response and paste below.","scheme":"bearer","type":"http"},"session_auth":{"description":"Session cookie issued by `/login` or `/auth/callback` after a successful Cognito authentication. Sign in at `/login` first, then use Swagger's Try-it-out: the browser sends the cookie automatically.","in":"cookie","name":"session","type":"apiKey"}}},"info":{"title":"AvatarFactory API","version":"1.0.0"},"openapi":"3.1.0","paths":{"/api/telegram/send":{"post":{"operationId":"telegram_api_api_telegram_send_api_telegram_send_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_SendBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TelegramSendResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Send an arbitrary message to the configured admin Telegram chat.","tags":["Telegram"]}},"/api/v1/account/email-change/confirm":{"post":{"operationId":"account_api_api_email_change_confirm_email_change_confirm_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeConfirmRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailChangeConfirmResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Confirm a pending email change with the mailed code.","tags":["Account"]}},"/api/v1/account/email-change/start":{"post":{"operationId":"account_api_api_email_change_start_email_change_start_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailChangeStartRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Begin a Cognito email change to a new address.","tags":["Account"]}},"/api/v1/account/identities":{"get":{"operationId":"account_api_api_get_identities_identities_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountIdentitiesResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Sign-in methods for the logged-in user (never anyone else's).","tags":["Account"]}},"/api/v1/account/set-password":{"post":{"operationId":"account_api_api_set_password_set_password_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetPasswordRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Add an email+password login to a social-only account.","tags":["Account"]}},"/api/v1/account/verify-email/confirm":{"post":{"operationId":"account_api_api_verify_email_confirm_verify_email_confirm_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeConfirmRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Confirm ownership of the current email with the mailed code.","tags":["Account"]}},"/api/v1/account/verify-email/send":{"post":{"operationId":"account_api_api_verify_email_send_verify_email_send_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccessTokenRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Email a verification code to the current address.","tags":["Account"]}},"/api/v1/activity":{"get":{"description":"<br/>Default limit is 20; max is 100. Events are sourced from real rows<br/>in the avatars, scenes, videos, and posts tables. Every user, admins<br/>included, sees only their own events (default-own scoping, spec<br/>\u00a73.5, 2026-08-11).","operationId":"activity_api_api_list_activity_get","parameters":[{"in":"query","name":"limit","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Limit"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityListResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Per-user activity feed, newest first.","tags":["Activity"]}},"/api/v1/admin/affiliate-assets":{"get":{"operationId":"affiliates_admin_api_admin_list_assets_affiliate_assets_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAssetsResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Every asset, inactive ones included, in the order the portal shows them.","tags":["Affiliate Admin"]},"post":{"operationId":"affiliates_admin_api_admin_create_asset_affiliate_assets_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAssetRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAssetItem"}}},"description":"Created"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Add one marketing asset to the portal's materials section.","tags":["Affiliate Admin"]}},"/api/v1/admin/affiliate-assets/{asset_id}":{"delete":{"description":"<br/>Assets are linked from the portal and from campaigns an affiliate already<br/>shared, so hiding beats destroying. The response is the retired row.","operationId":"affiliates_admin_api_admin_delete_asset_affiliate_assets__int_asset_id__delete","parameters":[{"in":"path","name":"asset_id","required":true,"schema":{"title":"Asset Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAssetItem"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Retire one asset. Soft delete: the row survives with `is_active` false.","tags":["Affiliate Admin"]},"put":{"operationId":"affiliates_admin_api_admin_update_asset_affiliate_assets__int_asset_id__put","parameters":[{"in":"path","name":"asset_id","required":true,"schema":{"title":"Asset Id","type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAssetRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAssetItem"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Replace one marketing asset. An unknown id writes nothing and is a 404.","tags":["Affiliate Admin"]}},"/api/v1/admin/affiliates":{"get":{"description":"<br/>`status` filters the queue tabs, `q` searches name, email and code.<br/>Payout details come back masked, exactly as they do in the portal.","operationId":"affiliates_admin_api_admin_list_affiliates_affiliates_get","parameters":[{"in":"query","name":"status","required":false,"schema":{"anyOf":[{"maxLength":32,"type":"string"},{"type":"null"}],"default":null,"title":"Status"}},{"in":"query","name":"q","required":false,"schema":{"anyOf":[{"maxLength":120,"type":"string"},{"type":"null"}],"default":null,"title":"Q"}},{"in":"query","name":"cursor","required":false,"schema":{"anyOf":[{"minimum":1.0,"type":"integer"},{"type":"null"}],"default":null,"title":"Cursor"}},{"in":"query","name":"limit","required":false,"schema":{"default":25,"maximum":100,"minimum":1.0,"title":"Limit","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAffiliatesResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"One page of applications, newest first (spec 4.2).","tags":["Affiliate Admin"]}},"/api/v1/admin/affiliates/{affiliate_id}":{"get":{"description":"<br/>`gross_revenue_cents` and `net_commission_cents` are the same two numbers<br/>the affiliate's own portal shows, under the same names, so the admin and<br/>the affiliate never read different figures for the same referral.","operationId":"affiliates_admin_api_admin_affiliate_detail_affiliates__int_affiliate_id__get","parameters":[{"in":"path","name":"affiliate_id","required":true,"schema":{"title":"Affiliate Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAffiliateDetailResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The drawer: the row, the balances, the referred users, the payouts.","tags":["Affiliate Admin"]}},"/api/v1/admin/affiliates/{affiliate_id}/approve":{"post":{"description":"<br/>Nothing new is generated. The referral code was created at apply time, so<br/>approving only unlocks it: `code_is_valid` and the attribution guard both<br/>key off the approved status.<br/><br/>Every decision appends an `audit_log` row naming this admin, in the SAME<br/>transaction as the status change. Approving turns a partner's link live,<br/>starts their counting and starts their money, and it used to leave no<br/>trace of who did it (round 15 walkthrough, finding 2).","operationId":"affiliates_admin_api_admin_approve_affiliate_affiliates__int_affiliate_id__approve_post","parameters":[{"in":"path","name":"affiliate_id","required":true,"schema":{"title":"Affiliate Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAffiliateItem"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Approve the application: status, `decided_at`, `decided_by_user_id`.","tags":["Affiliate Admin"]}},"/api/v1/admin/affiliates/{affiliate_id}/commissions":{"get":{"description":"<br/>Unmasked: there is nothing to mask on a commission row, unlike the<br/>affiliate record. `amount_cents` is signed, per Task 4's ledger, so a<br/>refund or chargeback reversal shows up as a negative row rather than a<br/>separate field.","operationId":"affiliates_admin_api_admin_affiliate_commissions_affiliates__int_affiliate_id__commissions_get","parameters":[{"in":"path","name":"affiliate_id","required":true,"schema":{"title":"Affiliate Id","type":"integer"}},{"in":"query","name":"cursor","required":false,"schema":{"anyOf":[{"minimum":1.0,"type":"integer"},{"type":"null"}],"default":null,"title":"Cursor"}},{"in":"query","name":"limit","required":false,"schema":{"default":25,"maximum":100,"minimum":1.0,"title":"Limit","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminCommissionsResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"One page of the affiliate's commission ledger, newest first.","tags":["Affiliate Admin"]}},"/api/v1/admin/affiliates/{affiliate_id}/decline":{"post":{"operationId":"affiliates_admin_api_admin_decline_affiliate_affiliates__int_affiliate_id__decline_post","parameters":[{"in":"path","name":"affiliate_id","required":true,"schema":{"title":"Affiliate Id","type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminDeclineRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAffiliateItem"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Decline the application. The reason is required and is stored on the row.","tags":["Affiliate Admin"]}},"/api/v1/admin/affiliates/{affiliate_id}/payout-details":{"get":{"description":"<br/>Deliberately a separate route from the drawer: reading an affiliate's<br/>application must not hand out their IBAN as a side effect. Every answer<br/>appends an `audit_log` row naming the admin, the affiliate and the route,<br/>which is the record of who saw the credentials and when. The details are<br/>never logged, only returned.","operationId":"affiliates_admin_api_admin_affiliate_payout_details_affiliates__int_affiliate_id__payout_details_get","parameters":[{"in":"path","name":"affiliate_id","required":true,"schema":{"title":"Affiliate Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminPayoutDetailsResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The payout details IN THE CLEAR, for the admin who sends the money.","tags":["Affiliate Admin"]}},"/api/v1/admin/affiliates/{affiliate_id}/payouts":{"post":{"description":"<br/>v1 pays by hand: the admin has already sent the PayPal or bank transfer<br/>and is recording it with its reference, so the payout is created `paid`<br/>and every commission it covers flips to `paid` in the same transaction.<br/>A balance below PAYOUT_MINIMUM_CENTS, negative balances included, is a<br/>422 that writes nothing and rolls into the next run (R11).","operationId":"affiliates_admin_api_admin_create_payout_run_affiliates__int_affiliate_id__payouts_post","parameters":[{"in":"path","name":"affiliate_id","required":true,"schema":{"title":"Affiliate Id","type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminPayoutRunRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayoutItem"}}},"description":"Created"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Record one manual payout for one affiliate (spec 4.6).","tags":["Affiliate Admin"]}},"/api/v1/admin/affiliates/{affiliate_id}/rate":{"put":{"description":"<br/>The program default is 50 percent and a negotiated partner can carry any<br/>whole percent from 1 to 100. Anything else is 422 `invalid_rate` and<br/>writes nothing, and that is the ONLY refusal shape this route has: a<br/>fractional percent and a string both come back as `{code, error}` rather<br/>than as the validator's raw array (round 14 walkthrough, finding 7). The change is NEVER retroactive: every commission row<br/>stores the rate it was booked at, so this only reaches invoices that<br/>arrive from now on.<br/><br/>Every change appends an `audit_log` row naming this admin, the affiliate,<br/>and the old and new rate, the same treatment the payout-details reveal<br/>gets. The response is the updated queue row, so the drawer re-renders from<br/>the answer rather than re-reading.","operationId":"affiliates_admin_api_admin_set_commission_rate_affiliates__int_affiliate_id__rate_put","parameters":[{"in":"path","name":"affiliate_id","required":true,"schema":{"title":"Affiliate Id","type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminRateRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAffiliateItem"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Set this affiliate's commission rate, in whole percent (spec 3.7).","tags":["Affiliate Admin"]}},"/api/v1/admin/affiliates/{affiliate_id}/suspend":{"post":{"operationId":"affiliates_admin_api_admin_suspend_affiliate_affiliates__int_affiliate_id__suspend_post","parameters":[{"in":"path","name":"affiliate_id","required":true,"schema":{"title":"Affiliate Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAffiliateItem"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Suspend the affiliate: no new attribution, and payouts are held.","tags":["Affiliate Admin"]}},"/api/v1/admin/evidence/users/{user_id}/pack":{"get":{"description":"<br/>JSON by default. `?format=text` returns the plain-text narrative that gets<br/>pasted straight into Stripe's dispute form.","operationId":"evidence_api_api_dispute_pack_users__int_user_id__pack_get","parameters":[{"in":"path","name":"user_id","required":true,"schema":{"minimum":1.0,"title":"User Id","type":"integer"}},{"in":"query","name":"format","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Format"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisputePackResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Everything we can prove about this account, for a Stripe dispute response.","tags":["Evidence"]}},"/api/v1/admin/followed/classify-backfill":{"get":{"operationId":"followed_accounts_admin_api_read_classify_backfill_counts_classify_backfill_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClassifyBackfillCountsResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"How many tracked accounts have a category right now. Admin only.","tags":["Followed Accounts Admin"]},"post":{"description":"<br/>Returns the counts as they were BEFORE the run, so the same endpoint's GET<br/>can be compared against them once the task drains. A second POST inside the<br/>single-flight window answers 409; past it, a re-run is safe and continues<br/>where the last one stopped, because a classified account drops out of the<br/>candidate set for a week.","operationId":"followed_accounts_admin_api_start_classify_backfill_classify_backfill_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClassifyBackfillRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClassifyBackfillQueuedResponse"}}},"description":"OK"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Start the retro category pass on the workers. Admin only.","tags":["Followed Accounts Admin"]}},"/api/v1/admin/followed/discovered":{"get":{"description":"<br/>Most-pasted first, so the ones several different users keep copying are<br/>the ones an admin looks at when deciding what to promote to Verified.","operationId":"followed_accounts_admin_api_list_discovered_accounts_discovered_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiscoveredAccountsResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The accounts our users' Copy From Reel pastes surfaced. Admin only.","tags":["Followed Accounts Admin"]}},"/api/v1/admin/followed/{account_id}/promote":{"post":{"description":"<br/>The same row flips `is_global`, so the reels, the scan history and the<br/>discovery evidence all survive; the action is written to `audit_log`.<br/>404 when there is no discovered account with that id (a Verified or<br/>personal account is not something this route promotes), 409 when it has<br/>already been promoted, so a double click is never a silent second write.","operationId":"followed_accounts_admin_api_promote_discovered_account__int_account_id__promote_post","parameters":[{"in":"path","name":"account_id","required":true,"schema":{"title":"Account Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromoteAccountResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Make a discovered account AvatarFactory Verified. Admin only.","tags":["Followed Accounts Admin"]}},"/api/v1/admin/generation-failures":{"get":{"operationId":"ai_failures_api_api_list_generation_failures_get","parameters":[{"in":"query","name":"surface","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Surface"}},{"in":"query","name":"model","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Model"}},{"in":"query","name":"q","required":false,"schema":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"title":"Q"}},{"in":"query","name":"page","required":false,"schema":{"default":1,"minimum":1.0,"title":"Page","type":"integer"}},{"in":"query","name":"page_size","required":false,"schema":{"default":25,"maximum":100,"minimum":1.0,"title":"Page Size","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FailureListResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Newest-first failed image generations with surface/model/text filters.","tags":["AI Failures"]}},"/api/v1/admin/impersonation":{"delete":{"description":"<br/>Stateless: the token stays valid until its TTL (documented spec<br/>behavior); the client drops it and per-write audits keep integrity.<br/>An EXPIRED but authentic token is still accepted here so a view that<br/>outlived the TTL can close its `impersonation_ended` trail (the swap<br/>itself never accepts an expired token). Tampered tokens 403.","operationId":"admin_api_api_impersonation_end_impersonation_delete","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}},"description":"OK"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"End the current view session (audit only).","tags":["Admin"]},"post":{"description":"<br/>If the request already carries an authentic grant (switching users<br/>mid-view), the old view is audited as ended first. An expired but<br/>authentic carried grant still closes its trail; only a tampered one<br/>is ignored. Grants are stateless, so a second browser session can<br/>hold its own open view; the trail closes each view it can see.","operationId":"admin_api_api_impersonation_start_impersonation_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImpersonationStartRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImpersonationStartResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Mint an impersonation grant for the given user.","tags":["Admin"]}},"/api/v1/admin/metrics/acquisition":{"get":{"operationId":"metrics_admin_api_get_acquisition_acquisition_get","parameters":[{"in":"query","name":"tz","required":false,"schema":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"title":"Tz"}},{"in":"query","name":"include_internal","required":false,"schema":{"anyOf":[{"enum":["0","1"],"type":"string"},{"type":"null"}],"default":null,"title":"Include Internal"}},{"in":"query","name":"from","required":false,"schema":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"title":"From"}},{"in":"query","name":"to","required":false,"schema":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"title":"To"}},{"in":"query","name":"filters","required":false,"schema":{"anyOf":[{"maxLength":4000,"type":"string"},{"type":"null"}],"default":null,"title":"Filters"}},{"in":"query","name":"granularity","required":false,"schema":{"default":"day","enum":["day","week","month"],"title":"Granularity","type":"string"}},{"in":"query","name":"compare","required":false,"schema":{"default":"previous","enum":["previous","yoy","none"],"title":"Compare","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcquisitionResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Visit, signup, trial, paid funnel by first-touch source, in the request's timezone.","tags":["Metrics Admin"]}},"/api/v1/admin/metrics/drill":{"get":{"operationId":"metrics_admin_api_get_drill_drill_get","parameters":[{"in":"query","name":"tz","required":false,"schema":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"title":"Tz"}},{"in":"query","name":"include_internal","required":false,"schema":{"anyOf":[{"enum":["0","1"],"type":"string"},{"type":"null"}],"default":null,"title":"Include Internal"}},{"in":"query","name":"from","required":false,"schema":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"title":"From"}},{"in":"query","name":"to","required":false,"schema":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"title":"To"}},{"in":"query","name":"filters","required":false,"schema":{"anyOf":[{"maxLength":4000,"type":"string"},{"type":"null"}],"default":null,"title":"Filters"}},{"in":"query","name":"steps","required":false,"schema":{"anyOf":[{"maxLength":400,"type":"string"},{"type":"null"}],"default":null,"title":"Steps"}},{"in":"query","name":"window_days","required":false,"schema":{"default":14,"title":"Window Days","type":"integer"}},{"in":"query","name":"kind","required":true,"schema":{"enum":["funnel_dropoff","metric","churn"],"title":"Kind","type":"string"}},{"in":"query","name":"metric","required":false,"schema":{"anyOf":[{"enum":["signups","trials","new_paid"],"type":"string"},{"type":"null"}],"default":null,"title":"Metric"}},{"in":"query","name":"step_index","required":false,"schema":{"anyOf":[{"maximum":7,"minimum":1.0,"type":"integer"},{"type":"null"}],"default":null,"title":"Step Index"}},{"in":"query","name":"by","required":false,"schema":{"anyOf":[{"enum":["country","device","source","medium","campaign","plan","billing","reason"],"type":"string"},{"type":"null"}],"default":null,"title":"By"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DrillResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Segments behind a funnel drop-off, a KPI or churned MRR.","tags":["Metrics Admin"]}},"/api/v1/admin/metrics/drill/export.csv":{"get":{"description":"10,000 rows. The zone is checked before the rate limit; the audit_log row is<br/>committed before the first byte streams. X-Metrics-Notes lists the drill's<br/>notes (paying_filters_ignored) when it has any.","operationId":"metrics_admin_api_get_drill_export_drill_export_csv_get","parameters":[{"in":"query","name":"tz","required":false,"schema":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"title":"Tz"}},{"in":"query","name":"include_internal","required":false,"schema":{"anyOf":[{"enum":["0","1"],"type":"string"},{"type":"null"}],"default":null,"title":"Include Internal"}},{"in":"query","name":"from","required":false,"schema":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"title":"From"}},{"in":"query","name":"to","required":false,"schema":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"title":"To"}},{"in":"query","name":"filters","required":false,"schema":{"anyOf":[{"maxLength":4000,"type":"string"},{"type":"null"}],"default":null,"title":"Filters"}},{"in":"query","name":"steps","required":false,"schema":{"anyOf":[{"maxLength":400,"type":"string"},{"type":"null"}],"default":null,"title":"Steps"}},{"in":"query","name":"window_days","required":false,"schema":{"default":14,"title":"Window Days","type":"integer"}},{"in":"query","name":"kind","required":true,"schema":{"enum":["funnel_dropoff","metric","churn"],"title":"Kind","type":"string"}},{"in":"query","name":"metric","required":false,"schema":{"anyOf":[{"enum":["signups","trials","new_paid"],"type":"string"},{"type":"null"}],"default":null,"title":"Metric"}},{"in":"query","name":"step_index","required":false,"schema":{"anyOf":[{"maximum":7,"minimum":1.0,"type":"integer"},{"type":"null"}],"default":null,"title":"Step Index"}},{"in":"query","name":"by","required":false,"schema":{"anyOf":[{"enum":["country","device","source","medium","campaign","plan","billing","reason"],"type":"string"},{"type":"null"}],"default":null,"title":"By"}}],"responses":{"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"CSV of the people behind a drill (200 text/csv): masked emails only, at most","tags":["Metrics Admin"]}},"/api/v1/admin/metrics/drill/people":{"get":{"operationId":"metrics_admin_api_get_drill_people_drill_people_get","parameters":[{"in":"query","name":"tz","required":false,"schema":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"title":"Tz"}},{"in":"query","name":"include_internal","required":false,"schema":{"anyOf":[{"enum":["0","1"],"type":"string"},{"type":"null"}],"default":null,"title":"Include Internal"}},{"in":"query","name":"from","required":false,"schema":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"title":"From"}},{"in":"query","name":"to","required":false,"schema":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"title":"To"}},{"in":"query","name":"filters","required":false,"schema":{"anyOf":[{"maxLength":4000,"type":"string"},{"type":"null"}],"default":null,"title":"Filters"}},{"in":"query","name":"steps","required":false,"schema":{"anyOf":[{"maxLength":400,"type":"string"},{"type":"null"}],"default":null,"title":"Steps"}},{"in":"query","name":"window_days","required":false,"schema":{"default":14,"title":"Window Days","type":"integer"}},{"in":"query","name":"kind","required":true,"schema":{"enum":["funnel_dropoff","metric","churn"],"title":"Kind","type":"string"}},{"in":"query","name":"metric","required":false,"schema":{"anyOf":[{"enum":["signups","trials","new_paid"],"type":"string"},{"type":"null"}],"default":null,"title":"Metric"}},{"in":"query","name":"step_index","required":false,"schema":{"anyOf":[{"maximum":7,"minimum":1.0,"type":"integer"},{"type":"null"}],"default":null,"title":"Step Index"}},{"in":"query","name":"by","required":false,"schema":{"anyOf":[{"enum":["country","device","source","medium","campaign","plan","billing","reason"],"type":"string"},{"type":"null"}],"default":null,"title":"By"}},{"in":"query","name":"offset","required":false,"schema":{"default":0,"maximum":9950,"minimum":0.0,"title":"Offset","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DrillPeopleResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"One page (50) of the people behind a drill, masked emails only.","tags":["Metrics Admin"]}},"/api/v1/admin/metrics/exports":{"get":{"description":"timestamps are absolute, so the zone is echoed with tz_applied false.","operationId":"metrics_admin_api_get_exports_exports_get","parameters":[{"in":"query","name":"tz","required":false,"schema":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"title":"Tz"}},{"in":"query","name":"include_internal","required":false,"schema":{"anyOf":[{"enum":["0","1"],"type":"string"},{"type":"null"}],"default":null,"title":"Include Internal"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportsResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The newest 50 drill exports: who, when, what and how many rows. The","tags":["Metrics Admin"]}},"/api/v1/admin/metrics/filters/values":{"get":{"operationId":"metrics_admin_api_get_filter_values_filters_values_get","parameters":[{"in":"query","name":"tz","required":false,"schema":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"title":"Tz"}},{"in":"query","name":"include_internal","required":false,"schema":{"anyOf":[{"enum":["0","1"],"type":"string"},{"type":"null"}],"default":null,"title":"Include Internal"}},{"in":"query","name":"from","required":false,"schema":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"title":"From"}},{"in":"query","name":"to","required":false,"schema":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"title":"To"}},{"in":"query","name":"dimension","required":true,"schema":{"enum":["plan","billing","country","device","source","medium","campaign"],"title":"Dimension","type":"string"}},{"in":"query","name":"q","required":false,"schema":{"anyOf":[{"maxLength":100,"type":"string"},{"type":"null"}],"default":null,"title":"Q"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FilterValuesResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Values of one filter dimension with their counts (date range only), in the request's zone.","tags":["Metrics Admin"]}},"/api/v1/admin/metrics/freshness":{"get":{"operationId":"metrics_admin_api_get_freshness_freshness_get","parameters":[{"in":"query","name":"tz","required":false,"schema":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"title":"Tz"}},{"in":"query","name":"include_internal","required":false,"schema":{"anyOf":[{"enum":["0","1"],"type":"string"},{"type":"null"}],"default":null,"title":"Include Internal"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FreshnessResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Latest build per model and whether the data is stale (env: this deployment).","tags":["Metrics Admin"]}},"/api/v1/admin/metrics/funnel":{"get":{"operationId":"metrics_admin_api_get_funnel_funnel_get","parameters":[{"in":"query","name":"tz","required":false,"schema":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"title":"Tz"}},{"in":"query","name":"include_internal","required":false,"schema":{"anyOf":[{"enum":["0","1"],"type":"string"},{"type":"null"}],"default":null,"title":"Include Internal"}},{"in":"query","name":"from","required":false,"schema":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"title":"From"}},{"in":"query","name":"to","required":false,"schema":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"title":"To"}},{"in":"query","name":"filters","required":false,"schema":{"anyOf":[{"maxLength":4000,"type":"string"},{"type":"null"}],"default":null,"title":"Filters"}},{"in":"query","name":"steps","required":false,"schema":{"anyOf":[{"maxLength":400,"type":"string"},{"type":"null"}],"default":null,"title":"Steps"}},{"in":"query","name":"window_days","required":false,"schema":{"default":14,"title":"Window Days","type":"integer"}},{"in":"query","name":"breakdown","required":false,"schema":{"default":"none","enum":["none","device","country","source","plan"],"title":"Breakdown","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FunnelResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"An ordered funnel over catalog steps, with a window and an optional breakdown.","tags":["Metrics Admin"]}},"/api/v1/admin/metrics/funnel/steps":{"get":{"operationId":"metrics_admin_api_get_funnel_steps_funnel_steps_get","parameters":[{"in":"query","name":"tz","required":false,"schema":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"title":"Tz"}},{"in":"query","name":"include_internal","required":false,"schema":{"anyOf":[{"enum":["0","1"],"type":"string"},{"type":"null"}],"default":null,"title":"Include Internal"}},{"in":"query","name":"from","required":false,"schema":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"title":"From"}},{"in":"query","name":"to","required":false,"schema":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"title":"To"}},{"in":"query","name":"filters","required":false,"schema":{"anyOf":[{"maxLength":4000,"type":"string"},{"type":"null"}],"default":null,"title":"Filters"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FunnelStepsResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The step picker: every catalog step, grouped, with distinct people in the range.","tags":["Metrics Admin"]}},"/api/v1/admin/metrics/meta":{"get":{"description":"funnel and drill catalogs for the UI.","operationId":"metrics_admin_api_get_meta_meta_get","parameters":[{"in":"query","name":"tz","required":false,"schema":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"title":"Tz"}},{"in":"query","name":"include_internal","required":false,"schema":{"anyOf":[{"enum":["0","1"],"type":"string"},{"type":"null"}],"default":null,"title":"Include Internal"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetaResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The zone and today in it, go-live date, thresholds, and the filter,","tags":["Metrics Admin"]}},"/api/v1/admin/metrics/overview":{"get":{"operationId":"metrics_admin_api_get_overview_overview_get","parameters":[{"in":"query","name":"tz","required":false,"schema":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"title":"Tz"}},{"in":"query","name":"include_internal","required":false,"schema":{"anyOf":[{"enum":["0","1"],"type":"string"},{"type":"null"}],"default":null,"title":"Include Internal"}},{"in":"query","name":"from","required":false,"schema":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"title":"From"}},{"in":"query","name":"to","required":false,"schema":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"title":"To"}},{"in":"query","name":"filters","required":false,"schema":{"anyOf":[{"maxLength":4000,"type":"string"},{"type":"null"}],"default":null,"title":"Filters"}},{"in":"query","name":"granularity","required":false,"schema":{"default":"day","enum":["day","week","month"],"title":"Granularity","type":"string"}},{"in":"query","name":"compare","required":false,"schema":{"default":"previous","enum":["previous","yoy","none"],"title":"Compare","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OverviewResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"KPI cards, MRR movements and churn by reason, in the request's timezone.","tags":["Metrics Admin"]}},"/api/v1/admin/metrics/rebuild":{"post":{"operationId":"metrics_admin_api_post_rebuild_rebuild_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RebuildRequest"}}},"required":true},"responses":{"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RebuildResponse"}}},"description":"Accepted"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Queue a model build for THIS environment (never another one, A14).","tags":["Metrics Admin"]}},"/api/v1/admin/metrics/retention":{"get":{"operationId":"metrics_admin_api_get_retention_retention_get","parameters":[{"in":"query","name":"tz","required":false,"schema":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"title":"Tz"}},{"in":"query","name":"include_internal","required":false,"schema":{"anyOf":[{"enum":["0","1"],"type":"string"},{"type":"null"}],"default":null,"title":"Include Internal"}},{"in":"query","name":"from","required":false,"schema":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"title":"From"}},{"in":"query","name":"to","required":false,"schema":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"title":"To"}},{"in":"query","name":"filters","required":false,"schema":{"anyOf":[{"maxLength":4000,"type":"string"},{"type":"null"}],"default":null,"title":"Filters"}},{"in":"query","name":"granularity","required":false,"schema":{"default":"day","enum":["day","week","month"],"title":"Granularity","type":"string"}},{"in":"query","name":"compare","required":false,"schema":{"default":"previous","enum":["previous","yoy","none"],"title":"Compare","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetentionResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Weekly signup and paid cohorts, in the request's timezone.","tags":["Metrics Admin"]}},"/api/v1/admin/metrics/subscription-state/run":{"post":{"operationId":"billing_metrics_admin_api_run_subscription_state_subscription_state_run_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionStateRunRequest"}}},"required":true},"responses":{"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionStateRunResponse"}}},"description":"Accepted"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Queue the subscription_state snapshot for this environment.","tags":["Metrics Admin"]}},"/api/v1/admin/metrics/usage":{"get":{"operationId":"metrics_admin_api_get_usage_usage_get","parameters":[{"in":"query","name":"tz","required":false,"schema":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"title":"Tz"}},{"in":"query","name":"include_internal","required":false,"schema":{"anyOf":[{"enum":["0","1"],"type":"string"},{"type":"null"}],"default":null,"title":"Include Internal"}},{"in":"query","name":"from","required":false,"schema":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"title":"From"}},{"in":"query","name":"to","required":false,"schema":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"title":"To"}},{"in":"query","name":"filters","required":false,"schema":{"anyOf":[{"maxLength":4000,"type":"string"},{"type":"null"}],"default":null,"title":"Filters"}},{"in":"query","name":"granularity","required":false,"schema":{"default":"day","enum":["day","week","month"],"title":"Granularity","type":"string"}},{"in":"query","name":"compare","required":false,"schema":{"default":"previous","enum":["previous","yoy","none"],"title":"Compare","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"DAU, WAU, MAU and product usage counts, in the request's timezone.","tags":["Metrics Admin"]}},"/api/v1/admin/qa-findings":{"get":{"description":"the report reads: counts by gate, action, outcome and model, the refusal rate per gate,<br/>the credits burnt on refused attempts and the findings that keep coming back.<br/><br/>The window defaults to the last seven days and the events come back newest first, a<br/>page at a time; the summary covers the whole window that was read, and `truncated` says<br/>the window held more rows than one call reads.","operationId":"copy_qa_api_api_qa_findings_get","parameters":[{"in":"query","name":"since","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Since"}},{"in":"query","name":"until","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Until"}},{"in":"query","name":"video_id","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Video Id"}},{"in":"query","name":"limit","required":false,"schema":{"default":200,"maximum":5000,"minimum":1.0,"title":"Limit","type":"integer"}},{"in":"query","name":"offset","required":false,"schema":{"default":0,"minimum":0.0,"title":"Offset","type":"integer"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Everything that failed QA in a window and what was done about it, with the summary","tags":["Video Templates"]}},"/api/v1/admin/users/lookup":{"get":{"operationId":"admin_api_api_admin_user_lookup_users_lookup_get","parameters":[{"description":"Email of the user to look up","in":"query","name":"email","required":true,"schema":{"description":"Email of the user to look up","minLength":1,"title":"Email","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminUserView"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Preview a user by email before starting a view session.","tags":["Admin"]}},"/api/v1/admin/videos/copied":{"get":{"operationId":"videos_admin_api_list_copied_videos_copied_get","parameters":[{"description":"Videos per page","in":"query","name":"limit","required":false,"schema":{"default":10,"description":"Videos per page","maximum":50,"minimum":1.0,"title":"Limit","type":"integer"}},{"description":"Copies by real accounts to skip","in":"query","name":"offset","required":false,"schema":{"default":0,"description":"Copies by real accounts to skip","maximum":5000,"minimum":0.0,"title":"Offset","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CopiedVideosResponse"}}},"description":"OK"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The newest copies of a reel by real accounts, newest first.","tags":["Videos Admin"]}},"/api/v1/affiliate/accept-terms":{"post":{"operationId":"affiliates_api_api_accept_terms_accept_terms_post","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AffiliateMeResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Record the caller's acceptance of the current terms version.","tags":["Affiliate"]}},"/api/v1/affiliate/apply":{"post":{"description":"<br/>Applying records the current terms version, so `accept_terms` is required.<br/>`service.apply` emits the `affiliate_applied` analytics event; this route<br/>deliberately does not emit it again.","operationId":"affiliates_api_api_apply_apply_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AffiliateMeResponse"}}},"description":"Created"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Create the caller's pending affiliate application (spec 4.1).","tags":["Affiliate"]}},"/api/v1/affiliate/assets":{"get":{"description":"<br/>Approved affiliates only. These are program collateral, not public<br/>marketing: an asset can be an unlisted deck, a partner-only pricing sheet<br/>or a pre-announcement reel, so a signed-in customer who never applied, or<br/>one whose application is still pending, declined or suspended, gets a 403<br/>rather than the list.<br/><br/>Reading the list is also what ticks the `assets_viewed_at` milestone on<br/>the dashboard checklist (spec 1.2). It is stamped AFTER the approval<br/>check, so a 403 never ticks a step the caller could not take, and only<br/>the first read moves it.","operationId":"affiliates_api_api_assets_assets_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetsResponse"}}},"description":"OK"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The active marketing materials, in the order the admin arranged them.","tags":["Affiliate"]}},"/api/v1/affiliate/attribute":{"post":{"description":"<br/>The SPA calls this once, right after signup, with the code it read from<br/>the `af_ref` cookie or from `?ref=` on /register. Always 200: the service<br/>silently refuses an unknown code, a second code, a self-referral or an<br/>older account, so the client can fire and forget. `reason` stays coarse<br/>so the endpoint never confirms whether a code exists.","operationId":"affiliates_api_api_attribute_attribute_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttributeRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttributeResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Lock the caller's fresh signup to a referral code (spec 4.3).","tags":["Affiliate"]}},"/api/v1/affiliate/clicks":{"post":{"description":"<br/>The marketing site fires this once per page load that carries a valid<br/>`?ref=`, with `keepalive: true` and nobody reading the response, so the<br/>route answers 204 to everything it is handed: an unknown code, a code<br/>whose affiliate is still pending, a body that is not JSON, a visitor who<br/>already counted today. Every one of those is the same silence, because an<br/>endpoint that answered them differently would be a free oracle for<br/>\"which referral codes exist\" to anyone with a script.<br/><br/>The body is parsed here instead of being declared as a `body:` parameter:<br/>the framework answers an unparseable body with its own 422, and this<br/>route promises 204. `ClickBeaconRequest` still owns the shape.<br/><br/>The ONE refusal a caller can see is 429. A rate limit has to be visible<br/>or a client cannot back off, and the limit is per ip, so saying it out<br/>loud reveals nothing about any affiliate. The limiter fails open: an<br/>unreachable Redis lets the click through rather than blocking the site.<br/><br/>The identity of the caller is `request.remote_addr` and nothing a client<br/>can write. See `clicks.client_ip`: with `X-Forwarded-For` read directly,<br/>anyone could mint a fresh visitor per request and both the dedup and the<br/>rate limit would be decoration.","operationId":"affiliates_api_api_record_click_clicks_post","responses":{"204":{"description":"No Content"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Count one landing on a referral link. Unauthenticated, 204 (spec 1.1).","tags":["Affiliate"]}},"/api/v1/affiliate/code":{"post":{"operationId":"affiliates_api_api_rename_code_code_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AffiliateMeResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Change the referral code. Allowed exactly once, then locked (R10).","tags":["Affiliate"]}},"/api/v1/affiliate/code/{code}/valid":{"get":{"description":"<br/>The marketing site calls this cross-origin to show \"20 percent off<br/>unlocked\" once the `af_ref` cookie is set. It carries the verdict and the<br/>code the caller already sent, and nothing about the affiliate behind it:<br/>no name, no status, no id. Allowlisted by endpoint name in<br/>`app/__init__.py`, the same way the Resend webhook is.","operationId":"affiliates_api_api_code_valid_code__code__valid_get","parameters":[{"in":"path","name":"code","required":true,"schema":{"title":"Code","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeValidResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Is this referral code live? Unauthenticated, on purpose.","tags":["Affiliate"]}},"/api/v1/affiliate/me":{"get":{"description":"<br/>A user who never applied gets `affiliate: null` with zero balances rather<br/>than a 404, so the portal can render its apply pitch from one call.","operationId":"affiliates_api_api_me_me_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AffiliateMeResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The caller's own affiliate record, link, balances and terms state.","tags":["Affiliate"]}},"/api/v1/affiliate/milestones":{"post":{"description":"<br/>`{\"event\": \"link_copied\"}` is the only body this accepts; anything else<br/>is 422 `invalid_event`. The portal calls it when the affiliate copies<br/>their link, which is the one checklist step with no server seam of its<br/>own: copying happens in the clipboard, not in an API call.<br/><br/>Idempotent by construction. The first stamp wins in SQL, so two tabs<br/>pressing copy cannot move a date the checklist has already shown, and the<br/>route answers 204 either way rather than telling the client whether it<br/>was first.","operationId":"affiliates_api_api_record_milestone_milestones_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MilestoneRequest"}}},"required":true},"responses":{"204":{"description":"No Content"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Stamp one onboarding milestone for the caller (spec 1.2).","tags":["Affiliate"]}},"/api/v1/affiliate/payouts":{"get":{"operationId":"affiliates_api_api_payouts_payouts_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayoutsResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The caller's payout history, newest first. Empty for a non-affiliate.","tags":["Affiliate"]}},"/api/v1/affiliate/profile":{"put":{"description":"<br/>Payout details are only replaced when the request carries a populated<br/>object. Missing, null or empty means \"keep what is stored\", because reads<br/>are masked and a round-tripped mask would destroy the real credentials.","operationId":"affiliates_api_api_update_profile_profile_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfileRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AffiliateMeResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Edit the caller's profile (spec 4.7).","tags":["Affiliate"]}},"/api/v1/affiliate/referrals":{"get":{"description":"<br/>Emails are masked in the service. `gross_revenue_cents` is the sum of the<br/>invoice bases booked for that referral, before refunds;<br/>`net_commission_cents` is the signed ledger total, so it drops when a<br/>claw-back lands while the revenue column keeps the historical figure.<br/>`status` is the six-word vocabulary (spec 1.3) and `total` counts every<br/>referral, not the page.","operationId":"affiliates_api_api_referrals_referrals_get","parameters":[{"in":"query","name":"cursor","required":false,"schema":{"anyOf":[{"minimum":1.0,"type":"integer"},{"type":"null"}],"default":null,"title":"Cursor"}},{"in":"query","name":"limit","required":false,"schema":{"default":25,"maximum":100,"minimum":1.0,"title":"Limit","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReferralsResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"One page of the caller's referred users, newest first (spec 4.7).","tags":["Affiliate"]}},"/api/v1/affiliate/stats":{"get":{"description":"<br/>Open to EVERY affiliate status: a pending applicant reads the same<br/>payload with every number at zero plus the checklist that tells them what<br/>happens next, which is what makes the dashboard available from day one.<br/>Only a user with NO affiliate row at all is refused, with 404<br/>`not_an_affiliate`, the same code `/referrals` and `/profile` answer for<br/>the same condition. (Spec 2 wrote it `not_affiliate`; one module speaking<br/>one word about one fact beats matching the prose.)<br/><br/>`range` is one of `today`, `24h`, `7d`, `30d`, `ytd`, `365d`, defaulting<br/>to `30d` when it is absent. ONE period covers the whole page, so the<br/>tiles, the chart, the funnel, the activity feed and the two card<br/>previews are all counted over it; the balances, the next payout and the<br/>checklist are all time and say so on the page. An unrecognised word is<br/>422 `invalid_range` in this module's error shape rather than a silent<br/>fall back to the default: a client asking for a window we do not have<br/>should be told, not quietly answered about a different one.<br/><br/>The response is cached for a minute, privately. The numbers move on<br/>webhook time, not on request time, so a dashboard that re-renders four<br/>cards in a second should not run these aggregates four times; `private`<br/>keeps one affiliate's figures out of any shared cache between us and them.<br/><br/>Serialized with `mode=\"json\"`, so every date and datetime ships as ISO<br/>8601 (\"2026-09-11\", \"2026-09-11T12:00:00Z\"). Flask's default provider<br/>renders a bare `date` as an HTTP-date (\"Fri, 11 Sep 2026 00:00:00 GMT\"),<br/>which is unusable as the key of a chart bucket. This matches what most of<br/>the app's routes already do; the older affiliate routes do not, which is<br/>a wart to clean up separately rather than in the middle of this one.","operationId":"affiliates_api_api_stats_stats_get","parameters":[{"in":"query","name":"range","required":false,"schema":{"default":"30d","enum":["today","24h","7d","30d","ytd","365d"],"maxLength":32,"title":"Range","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AffiliateStatsResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Everything the affiliate dashboard paints, for one period (spec 3.8).","tags":["Affiliate"]}},"/api/v1/analytics/accounts/{account_id}":{"get":{"description":"<br/>Access rules (mirrors _visible_to scoping in followed_accounts):<br/>  - Global (is_global=True) accounts are readable by all authenticated<br/>    users regardless of owner_id.<br/>  - Personal accounts are readable by their steward, their followers<br/>    (shared followed accounts, 2026-09-16) or admins.","operationId":"analytics_api_api_account_analytics_accounts__int_account_id__get","parameters":[{"in":"path","name":"account_id","required":true,"schema":{"title":"Account Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountAnalytics"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Return reel analytics for a followed account.","tags":["Analytics"]}},"/api/v1/analytics/reels":{"get":{"description":"<br/>Scoped to the caller: regular users see only reels they own (plus<br/>aggregates over the same set); admins see the platform-wide view.","operationId":"analytics_api_api_reels_dashboard_reels_get","parameters":[{"in":"query","name":"sort_by","required":false,"schema":{"default":"vph","title":"Sort By","type":"string"}},{"in":"query","name":"account","required":false,"schema":{"default":"","title":"Account","type":"string"}},{"in":"query","name":"category_id","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Category Id"}},{"in":"query","name":"tag","required":false,"schema":{"default":"","title":"Tag","type":"string"}},{"in":"query","name":"min_views","required":false,"schema":{"default":50000,"title":"Min Views","type":"integer"}},{"in":"query","name":"min_engagement","required":false,"schema":{"default":0.0,"title":"Min Engagement","type":"number"}},{"in":"query","name":"min_vph","required":false,"schema":{"default":0,"title":"Min Vph","type":"integer"}},{"in":"query","name":"days","required":false,"schema":{"default":0,"title":"Days","type":"integer"}},{"in":"query","name":"min_followers","required":false,"schema":{"default":0,"title":"Min Followers","type":"integer"}},{"in":"query","name":"max_followers","required":false,"schema":{"default":0,"title":"Max Followers","type":"integer"}},{"in":"query","name":"favorites_only","required":false,"schema":{"default":false,"title":"Favorites Only","type":"boolean"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReelDashboardResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Reel dashboard payload (used by /analytics/reels).","tags":["Analytics"]}},"/api/v1/analytics/reels/table":{"get":{"description":"<br/>Visibility: own reels + reels of global (\"AvatarFactory Verified\")<br/>accounts (admins see all). Supports range/account/category/date<br/>filters, two-axis sort, and limit/offset pagination with a total<br/>count plus the facet lists for the filter dropdowns.<br/><br/>Two of those knobs are plan-gated (Lior, 2026-09-30): asking for<br/>``outperformers_only=true`` or ``sort_by=outperform`` without the<br/>Outperformers entitlement is a 402 ``UPGRADE_REQUIRED``. The gate is on<br/>the REQUEST, not the payload: every row still carries<br/>``outperform_ratio`` and ``is_outperformer`` for every caller, because<br/>seeing the badges is what makes the upgrade worth asking for.","operationId":"analytics_api_api_reels_table_reels_table_get","parameters":[{"in":"query","name":"min_views","required":false,"schema":{"anyOf":[{"minimum":0.0,"type":"integer"},{"type":"null"}],"default":null,"title":"Min Views"}},{"in":"query","name":"max_views","required":false,"schema":{"anyOf":[{"minimum":0.0,"type":"integer"},{"type":"null"}],"default":null,"title":"Max Views"}},{"in":"query","name":"min_likes","required":false,"schema":{"anyOf":[{"minimum":0.0,"type":"integer"},{"type":"null"}],"default":null,"title":"Min Likes"}},{"in":"query","name":"max_likes","required":false,"schema":{"anyOf":[{"minimum":0.0,"type":"integer"},{"type":"null"}],"default":null,"title":"Max Likes"}},{"in":"query","name":"min_comments","required":false,"schema":{"anyOf":[{"minimum":0.0,"type":"integer"},{"type":"null"}],"default":null,"title":"Min Comments"}},{"in":"query","name":"max_comments","required":false,"schema":{"anyOf":[{"minimum":0.0,"type":"integer"},{"type":"null"}],"default":null,"title":"Max Comments"}},{"in":"query","name":"min_followers","required":false,"schema":{"anyOf":[{"minimum":0.0,"type":"integer"},{"type":"null"}],"default":null,"title":"Min Followers"}},{"in":"query","name":"max_followers","required":false,"schema":{"anyOf":[{"minimum":0.0,"type":"integer"},{"type":"null"}],"default":null,"title":"Max Followers"}},{"in":"query","name":"min_engagement","required":false,"schema":{"anyOf":[{"maximum":100,"minimum":0.0,"type":"number"},{"type":"null"}],"default":null,"title":"Min Engagement"}},{"in":"query","name":"max_engagement","required":false,"schema":{"anyOf":[{"maximum":100,"minimum":0.0,"type":"number"},{"type":"null"}],"default":null,"title":"Max Engagement"}},{"in":"query","name":"account","required":false,"schema":{"items":{"type":"string"},"title":"Account","type":"array"}},{"in":"query","name":"category_id","required":false,"schema":{"items":{"type":"integer"},"title":"Category Id","type":"array"}},{"in":"query","name":"posted_after","required":false,"schema":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"title":"Posted After"}},{"in":"query","name":"posted_before","required":false,"schema":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"title":"Posted Before"}},{"in":"query","name":"favorites_only","required":false,"schema":{"default":false,"title":"Favorites Only","type":"boolean"}},{"in":"query","name":"outperformers_only","required":false,"schema":{"default":false,"title":"Outperformers Only","type":"boolean"}},{"in":"query","name":"source","required":false,"schema":{"default":"all","enum":["all","mine","verified"],"title":"Source","type":"string"}},{"in":"query","name":"sort_by","required":false,"schema":{"default":"recent","enum":["views","engagement","recent","vph","likes","comments","followers","outperform","af_score"],"title":"Sort By","type":"string"}},{"in":"query","name":"sort_dir","required":false,"schema":{"default":"desc","enum":["asc","desc"],"title":"Sort Dir","type":"string"}},{"in":"query","name":"page","required":false,"schema":{"default":1,"minimum":1.0,"title":"Page","type":"integer"}},{"in":"query","name":"page_size","required":false,"schema":{"default":50,"maximum":200,"minimum":1.0,"title":"Page Size","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReelTableResponse"}}},"description":"OK"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Payment Required"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Server-paginated reel table across every reel the viewer can see.","tags":["Analytics"]}},"/api/v1/analytics/reels/transcript":{"get":{"description":"<br/>Backs the grid view's \"read transcript\" action: looks up the<br/>caller's own copy-ingest history by the reel's URL (admins see every<br/>ingest). 404 when the caller never pulled this reel's transcript.","operationId":"analytics_api_api_reel_transcript_reels_transcript_get","parameters":[{"in":"query","name":"url","required":true,"schema":{"minLength":1,"title":"Url","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReelTranscriptResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Transcript for a reel the caller already ingested (Copy From Reel).","tags":["Analytics"]}},"/api/v1/analytics/reels/trending":{"get":{"description":"<br/>Visibility: own reels + reels of global (\"AvatarFactory Verified\")<br/>accounts (admins see all), posted within the last `hours`, ordered by<br/>views_per_hour. A brand-new user with no followed accounts still sees<br/>the global Verified set.","operationId":"analytics_api_api_reels_trending_reels_trending_get","parameters":[{"in":"query","name":"limit","required":false,"schema":{"default":6,"maximum":24,"minimum":1.0,"title":"Limit","type":"integer"}},{"in":"query","name":"hours","required":false,"schema":{"default":24,"maximum":168,"minimum":1.0,"title":"Hours","type":"integer"}},{"in":"query","name":"verified_only","required":false,"schema":{"default":false,"title":"Verified Only","type":"boolean"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrendingReelsResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Top reels by velocity for the dashboard \"Trending right now\" teaser.","tags":["Analytics"]}},"/api/v1/analytics/reels/{reel_id}/refresh":{"post":{"operationId":"analytics_api_api_refresh_reel_reels__int_reel_id__refresh_post","parameters":[{"in":"path","name":"reel_id","required":true,"schema":{"title":"Reel Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReelRefreshResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal Server Error"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Refresh analytics snapshot for a single reel.","tags":["Analytics"]}},"/api/v1/auth/email-exists":{"post":{"description":"<br/>Returns ``{\"exists\": true}`` if the local ``users`` table has a row<br/>with this email (case-insensitive), otherwise ``{\"exists\": false}``.<br/><br/>The SPA uses this to decide whether to show a LOGIN (password only)<br/>or REGISTER (full name + password) form after the email step. The<br/>endpoint does not require authentication.","operationId":"auth_api_api_email_exists_email_exists_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailExistsRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailExistsResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Look up whether an email is already registered.","tags":["Auth"]}},"/api/v1/automation/approvals":{"get":{"description":"<br/>Scoped to the caller in SQL via `scope_query` inside the repository.","operationId":"automation_api_api_approvals_approvals_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovalQueueResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Pending approval videos (used by the approval queue page).","tags":["Automation"]}},"/api/v1/automation/dashboard":{"get":{"description":"<br/>Scoped to the caller in SQL via `scope_query` inside the repository:<br/>regular users see only their own avatars / videos / runs; admins see<br/>every row.","operationId":"automation_api_api_dashboard_dashboard_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Dashboard payload (avatars + today's stats + recent runs + pending count).","tags":["Automation"]}},"/api/v1/automation/pipeline-run/{run_id}/status":{"get":{"operationId":"automation_api_pipeline_run_status_pipeline_run__int_run_id__status_get","parameters":[{"in":"path","name":"run_id","required":true,"schema":{"title":"Run Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PipelineStatusResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Poll the status of an in-progress pipeline run.","tags":["Automation"]}},"/api/v1/automation/reel-to-video/avatar-scenes/{avatar_id}":{"get":{"operationId":"automation_api_reel_to_video_avatar_scenes_reel_to_video_avatar_scenes__int_avatar_id__get","parameters":[{"in":"path","name":"avatar_id","required":true,"schema":{"title":"Avatar Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AvatarScenesResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"List scenes available for the reel-to-video picker for a given avatar.","tags":["Automation"]}},"/api/v1/automation/reel-to-video/run-one":{"post":{"operationId":"automation_api_reel_to_video_run_one_reel_to_video_run_one_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReelToVideoRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReelToVideoStartedResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal Server Error"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Reel-to-video orchestrator: build a Script + PipelineRun and start.","tags":["Automation"]}},"/api/v1/automation/run-full-process":{"post":{"operationId":"automation_api_run_full_process_run_full_process_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunFullProcessRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PipelineStartedResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal Server Error"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Kick off a full pipeline run for a script + avatar pair.","tags":["Automation"]}},"/api/v1/avatars":{"get":{"description":"<br/>Two views (Lior, 2026-05-30):<br/><br/>- ``view=\"me\"`` (default): caller's own avatars via ``scope_query``,<br/>  with template rows (``is_template=1``) excluded so they never<br/>  pollute a user's library.<br/>- ``view=\"templates\"``: admin-only. Bypasses ownership scoping and<br/>  returns the global template avatars (``is_template=1``,<br/>  ``owner_id IS NULL``). Non-admins get 403.","operationId":"avatars_api_api_list_avatars_get","parameters":[{"in":"query","name":"archived","required":false,"schema":{"default":0,"title":"Archived","type":"integer"}},{"in":"query","name":"category_id","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Category Id"}},{"in":"query","name":"sort","required":false,"schema":{"default":"custom","title":"Sort","type":"string"}},{"in":"query","name":"q","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Q"}},{"in":"query","name":"view","required":false,"schema":{"default":"me","title":"View","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AvatarListResponse"}}},"description":"OK"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Avatar list view used by the /avatars page.","tags":["Avatars"]},"post":{"description":"<br/>Mirrors the legacy form-based `/avatars/new` POST handler at the<br/>JSON layer so the React wizard can submit a single payload at the<br/>end of the 4-step flow. Returns the new avatar id + identity<br/>fields so the SPA can route to `/avatars/{id}` and pre-fill<br/>the detail screen without an extra GET round trip.","operationId":"avatars_api_api_create_avatar_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAvatarRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAvatarResponse"}}},"description":"Created"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Create a new avatar from the SPA wizard.","tags":["Avatars"]}},"/api/v1/avatars/admin/templates/reorder":{"post":{"description":"<br/>``ids`` is the templates in their new order (typically one niche<br/>tab's cards). Each template row gets ``display_order`` = (position+1)<br/>* 10; duplicate ids honour the first occurrence and non-template ids<br/>are skipped, so the endpoint can never touch user avatars. Non-admins<br/>get 403; anonymous callers get 401.","operationId":"avatars_api_api_reorder_templates_admin_templates_reorder_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReorderAvatarsRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReorderAvatarsResponse"}}},"description":"OK"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Persist a new curated template order. Admin-only.","tags":["Avatars"]}},"/api/v1/avatars/meta/categories":{"get":{"operationId":"avatars_api_api_categories_meta_categories_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AvatarCategoriesResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Account categories with avatar counts (used by list/form pages).","tags":["Avatars"]}},"/api/v1/avatars/meta/defaults":{"get":{"operationId":"avatars_api_api_defaults_meta_defaults_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AvatarDefaultsResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Static defaults used by the avatar create/edit forms.","tags":["Avatars"]}},"/api/v1/avatars/reorder":{"post":{"description":"<br/>The SPA sends the caller's avatars in their new order; each owned row's<br/>``display_order`` is set to its position in that list, in a single<br/>transaction. Ids the caller does not own (or that don't exist) are<br/>skipped, so a stale or malicious client can never reorder another<br/>user's rows. The default list sort (``custom``) reads ``display_order``<br/>ascending, so this is exactly the order the grid renders next load.<br/><br/>Returns the owned ids that were reordered, in their new order.","operationId":"avatars_api_api_reorder_avatars_reorder_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReorderAvatarsRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReorderAvatarsResponse"}}},"description":"OK"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Persist a new avatar order for the current user.","tags":["Avatars"]}},"/api/v1/avatars/{avatar_id}":{"patch":{"description":"<br/>Powers the pencil-edit affordances on ``/avatars/:id``. Body<br/>contract is defined by ``UpdateAvatarRequest`` (extra-forbid, length<br/>bounded). Unknown fields \u2192 422 from the schema layer; an empty body<br/>is a no-op that returns the current detail bundle with 200<br/>(idempotent).<br/><br/>On success the response mirrors ``GET /api/v1/avatars/<id>/detail``<br/>so the SPA can drop the new payload straight into its react-query<br/>cache via ``setQueryData`` without an extra round trip.<br/><br/>Backend note on \"niche\": the avatar model exposes ``category_id``<br/>(FK to ``account_categories``), not a free-text niche column. The<br/>SPA's ``resolveCategoryId(niche, categories)`` helper turns the<br/>wizard's niche key into a ``category_id`` before posting; this<br/>endpoint accepts ``category_id`` directly. The string \"niche\" is<br/>rejected (extra-forbid) so the SPA cannot silently fail-silent on<br/>a misnamed key.","operationId":"avatars_api_api_update_avatar__int_avatar_id__patch","parameters":[{"in":"path","name":"avatar_id","required":true,"schema":{"title":"Avatar Id","type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAvatarRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AvatarDetailResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Partial update for an avatar's editable identity fields.","tags":["Avatars"]}},"/api/v1/avatars/{avatar_id}/archive":{"post":{"description":"<br/>The legacy `/avatars/<id>/archive` page route still exists for HTML<br/>form posts, but the React SPA must use this JSON variant so it can<br/>detect a 401 / 403 instead of silently following a 302.","operationId":"avatars_api_api_avatar_archive__int_avatar_id__archive_post","parameters":[{"in":"path","name":"avatar_id","required":true,"schema":{"title":"Avatar Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_ArchiveResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Archive an avatar (set archived=1). Returns JSON on success.","tags":["Avatars"]}},"/api/v1/avatars/{avatar_id}/detail":{"get":{"description":"<br/>Assembled by ``build_detail_response`` (shared with the PATCH echo), so the two<br/>responses can never drift; the Scenes split excludes outfit sheets and the bundle<br/>carries ``outfit_count`` for the Outfits tab (plan 3).","operationId":"avatars_api_api_avatar_detail__int_avatar_id__detail_get","parameters":[{"in":"path","name":"avatar_id","required":true,"schema":{"title":"Avatar Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AvatarDetailResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Full bundle the avatar detail page needs in one round-trip.","tags":["Avatars"]}},"/api/v1/avatars/{avatar_id}/images/{image_id}/set-main":{"post":{"description":"<br/>Ownership is enforced by the decorator (403 for another tenant's<br/>avatar, admins pass with an `audit_log` row naming the<br/>`set_main_image` action). The image itself must belong to THAT<br/>avatar: an id from any other avatar is a 404, never a silent<br/>promotion.<br/><br/>Idempotent \u2014 re-posting the image that is already main returns 200<br/>with the same `face_image`.<br/><br/>Nothing is deleted. The row that used to be primary survives and<br/>keeps naming the previous face blob, so the stored object stays<br/>referenced (see `repository.face_blob_is_referenced`).","operationId":"avatars_api_api_avatar_set_main_image__int_avatar_id__images__int_image_id__set_main_post","parameters":[{"in":"path","name":"avatar_id","required":true,"schema":{"title":"Avatar Id","type":"integer"}},{"in":"path","name":"image_id","required":true,"schema":{"title":"Image Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_SetMainImageResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Make one saved image this avatar's main picture.","tags":["Avatars"]}},"/api/v1/avatars/{avatar_id}/outfits":{"get":{"description":"``first_outfit_pending`` is true while the free first outfit is on its way.","operationId":"avatars_api_api_list_outfits__int_avatar_id__outfits_get","parameters":[{"in":"path","name":"avatar_id","required":true,"schema":{"title":"Avatar Id","type":"integer"}},{"in":"query","name":"page","required":false,"schema":{"default":1,"minimum":1.0,"title":"Page","type":"integer"}},{"in":"query","name":"page_size","required":false,"schema":{"anyOf":[{"minimum":1.0,"type":"integer"},{"type":"null"}],"default":null,"title":"Page Size"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AvatarOutfitsPage"}}},"description":"OK"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"One page of the avatar's outfits, newest first (24 per page, 48 at most).","tags":["Avatars"]},"post":{"description":"page (202 + poll ``/avatars/<id>/scene-jobs/<job_id>``). Approve the draft with<br/>``as_outfit`` + ``clothes_only`` to save it as a clothes-only outfit.","operationId":"avatars_api_api_generate_outfit__int_avatar_id__outfits_post","parameters":[{"in":"path","name":"avatar_id","required":true,"schema":{"title":"Avatar Id","type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateOutfitRequest"}}},"required":true},"responses":{"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OutfitJobResponse"}}},"description":"Accepted"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Describe the clothes; a job renders the outfit ALONE, laid out on a white","tags":["Avatars"]}},"/api/v1/avatars/{avatar_id}/outfits/variations":{"post":{"description":"(text only, no credits). Every constraint in the description holds in<br/>each take; they differ in colors, fabrics, cuts and accessories.","operationId":"avatars_api_api_outfit_variations__int_avatar_id__outfits_variations_post","parameters":[{"in":"path","name":"avatar_id","required":true,"schema":{"title":"Avatar Id","type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_VariationsBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_VariationsResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"N distinct takes of one outfit description for the studio's options","tags":["Avatars"]}},"/api/v1/avatars/{avatar_id}/outfits/{outfit_id}":{"delete":{"operationId":"avatars_api_api_delete_outfit__int_avatar_id__outfits__int_outfit_id__delete","parameters":[{"in":"path","name":"avatar_id","required":true,"schema":{"title":"Avatar Id","type":"integer"}},{"in":"path","name":"outfit_id","required":true,"schema":{"title":"Outfit Id","type":"integer"}}],"responses":{"204":{"description":"No Content"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Delete one of the caller's outfits on this avatar.","tags":["Avatars"]}},"/api/v1/avatars/{avatar_id}/pillars":{"get":{"operationId":"avatars_api_api_avatar_pillars__int_avatar_id__pillars_get","parameters":[{"in":"path","name":"avatar_id","required":true,"schema":{"title":"Avatar Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AvatarPillarsResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"List content pillars for an avatar (used by the automation pillars page).","tags":["Avatars"]}},"/api/v1/avatars/{avatar_id}/social-accounts":{"get":{"operationId":"avatars_api_api_avatar_social_accounts__int_avatar_id__social_accounts_get","parameters":[{"in":"path","name":"avatar_id","required":true,"schema":{"title":"Avatar Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AvatarSocialAccountsResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Connected social accounts for an avatar.","tags":["Avatars"]}},"/api/v1/avatars/{avatar_id}/unarchive":{"post":{"operationId":"avatars_api_api_avatar_unarchive__int_avatar_id__unarchive_post","parameters":[{"in":"path","name":"avatar_id","required":true,"schema":{"title":"Avatar Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_ArchiveResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Unarchive an avatar (set archived=0). Returns JSON on success.","tags":["Avatars"]}},"/api/v1/backgrounds":{"get":{"description":"<br/>Returns all preset backgrounds (owner_id=NULL) plus the caller's<br/>own uploads. Admins additionally see other users' uploads.<br/>Filtering happens in the service layer for presets; per-user<br/>scoping is layered here.","operationId":"backgrounds_api_api_list_backgrounds_get","parameters":[{"in":"query","name":"category","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Category"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackgroundsListResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Backgrounds list (used by /backgrounds).","tags":["Backgrounds"]}},"/api/v1/backgrounds/generate":{"post":{"operationId":"backgrounds_api_api_generate_background_generate_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateBackgroundRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateBackgroundResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal Server Error"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Generate a background image with Gemini.","tags":["Backgrounds"]}},"/api/v1/billing/cancel":{"post":{"description":"<br/>The account and its data stay (cancel subscription only, Lior's<br/>decision 2026-08-21); the survey answer is recorded as churned.","operationId":"billing_api_api_cancel_subscription_cancel_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelSubscriptionRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionStatusResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The retention flow's final action: the plan lapses at period end.","tags":["Billing"]}},"/api/v1/billing/change-plan":{"post":{"operationId":"billing_api_api_change_plan_change_plan_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangePlanRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionStatusResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Payment Required"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Switch a live subscription to another plan/interval (charges card on file).","tags":["Billing"]}},"/api/v1/billing/change-plan/cancel-scheduled":{"post":{"operationId":"billing_api_api_cancel_scheduled_change_change_plan_cancel_scheduled_post","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionStatusResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Cancel a pending (scheduled) downgrade so the current plan continues.","tags":["Billing"]}},"/api/v1/billing/change-plan/preview":{"get":{"operationId":"billing_api_api_change_plan_preview_change_plan_preview_get","parameters":[{"in":"query","name":"plan","required":true,"schema":{"title":"Plan","type":"string"}},{"in":"query","name":"interval","required":false,"schema":{"default":"monthly","title":"Interval","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangePlanPreviewResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Payment Required"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Summarise a plan switch (amount, item, card) for the confirmation modal.","tags":["Billing"]}},"/api/v1/billing/charges":{"get":{"operationId":"billing_api_api_charges_charges_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChargesResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The current user's one-off charges/refunds (the $1 trial, top-ups, refunds).","tags":["Billing"]}},"/api/v1/billing/checkout/finalize":{"post":{"operationId":"billing_api_api_checkout_finalize_checkout_finalize_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinalizeCheckoutRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionStatusResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Payment Required"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Create the trial subscription once the upfront intent is confirmed.","tags":["Billing"]}},"/api/v1/billing/checkout/payment-intent":{"post":{"description":"<br/>Normally a $1 card-validation PaymentIntent; a fully-discounting promo code<br/>switches it to a $0 SetupIntent so the card is saved but never charged.","operationId":"billing_api_api_checkout_payment_intent_checkout_payment_intent_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutPaymentIntentRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutIntentResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Payment Required"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Create the upfront intent for the picked plan.","tags":["Billing"]}},"/api/v1/billing/config":{"get":{"operationId":"billing_api_api_config_config_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfigResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The Stripe publishable key for the embedded Payment Element.","tags":["Billing"]}},"/api/v1/billing/credit-costs":{"get":{"description":"<br/>Internal provider USD costs are deliberately not included. The demo account<br/>reads a third of every price, what its meter charges (``demo_pricing``).","operationId":"billing_api_api_credit_costs_credit_costs_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditCostsResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Credit charges per action so the SPA can render on-button cost badges.","tags":["Billing"]}},"/api/v1/billing/credit-history":{"get":{"description":"<br/>Powers the \"what did I spend credits on\" view. Internal provider USD cost is<br/>not exposed.","operationId":"billing_api_api_credit_history_credit_history_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditHistoryResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The current user's credit spend history (the ledger), most recent first.","tags":["Billing"]}},"/api/v1/billing/funnel/checkout":{"post":{"operationId":"billing_api_api_funnel_guest_start_funnel_checkout_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestCheckoutRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestCheckoutResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The email check, then open, resume or reuse the checkout (monthly, paid in full).","tags":["Billing"]}},"/api/v1/billing/funnel/checkout/{checkout_id}/confirm":{"post":{"operationId":"billing_api_api_funnel_guest_confirm_funnel_checkout__checkout_id__confirm_post","parameters":[{"in":"path","name":"checkout_id","required":true,"schema":{"maxLength":32,"title":"Checkout Id","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestConfirmRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestStatusResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The card form finished: check with Stripe that the first invoice is paid.","tags":["Billing"]}},"/api/v1/billing/funnel/checkout/{checkout_id}/influencer-addon":{"post":{"description":"<br/>No session: the account may not exist yet (Lior, 2026-10-14). The add-on<br/>is charged on the purchase's saved card and lands on whichever account<br/>finishes it.","operationId":"billing_api_api_funnel_guest_addon_funnel_checkout__checkout_id__influencer_addon_post","parameters":[{"in":"path","name":"checkout_id","required":true,"schema":{"maxLength":32,"title":"Checkout Id","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestTokenRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestAddonResponse"}}},"description":"OK"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Payment Required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The payment-received step's 2 more influencers, for the purchase's token holder.","tags":["Billing"]}},"/api/v1/billing/funnel/checkout/{checkout_id}/status":{"post":{"operationId":"billing_api_api_funnel_guest_status_funnel_checkout__checkout_id__status_post","parameters":[{"in":"path","name":"checkout_id","required":true,"schema":{"maxLength":32,"title":"Checkout Id","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestTokenRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestStatusResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Where the checkout stands, for its token holder (the finish step).","tags":["Billing"]}},"/api/v1/billing/funnel/claim":{"post":{"operationId":"billing_api_api_funnel_guest_claim_funnel_claim_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestClaimRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestClaimResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Attach the paid purchase to the signed-in account (Google is the truth).","tags":["Billing"]}},"/api/v1/billing/funnel/influencer-addon":{"post":{"operationId":"billing_api_api_influencer_addon_funnel_influencer_addon_post","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InfluencerAddonResponse"}}},"description":"OK"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Payment Required"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Add two influencers to the AI Influencer plan, charged now on the saved card.","tags":["Billing"]}},"/api/v1/billing/funnel/prefill":{"get":{"operationId":"billing_api_api_funnel_guest_prefill_funnel_prefill_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestPrefillResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The avatar choices of the account's finished funnel purchase, on any device.","tags":["Billing"]}},"/api/v1/billing/funnel/resend":{"post":{"operationId":"billing_api_api_funnel_guest_resend_funnel_resend_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestResendRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestResendResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Email the finish link again. Always ``ok``: it says nothing about the email.","tags":["Billing"]}},"/api/v1/billing/invoices":{"get":{"operationId":"billing_api_api_invoices_invoices_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoicesResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The current user's invoice history (local read-model).","tags":["Billing"]}},"/api/v1/billing/pause":{"post":{"description":"<br/>Step 1 of the retention flow (Lior, 2026-08-21). One pause at a<br/>time; pausing an already-paused account is a 400.","operationId":"billing_api_api_pause_account_pause_post","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionStatusResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Pause the account for 30 days: no charges, data kept, auto-resume.","tags":["Billing"]}},"/api/v1/billing/payment-issue":{"get":{"description":"<br/>Split from ``GET /subscription`` on purpose: that route runs on every page<br/>load and must stay free of provider calls, while this one costs up to three<br/>Stripe reads and is only called by the paywall while a charge the user just<br/>started has not unlocked anything yet.<br/><br/>Always 200. A user looking at a paywall gets a worse outcome from a 500 than<br/>from ``state: \"unknown\"``, and guessing either way is harmful: ``settled``<br/>strands them, ``failed`` tells them to pay twice (weekly review 2026-09-28,<br/>item 1: two users looped on the paywall with no message at all, one of them<br/>for 13.6 minutes, the other forever).","operationId":"billing_api_api_payment_issue_payment_issue_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentIssueResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Where the charge behind the caller's latest invoice stands, and why.","tags":["Billing"]}},"/api/v1/billing/payment-method":{"get":{"operationId":"billing_api_api_payment_method_payment_method_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentMethodEnvelope"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The card on file that the next charge would use (or null).","tags":["Billing"]},"post":{"operationId":"billing_api_api_set_payment_method_payment_method_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetPaymentMethodRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Make the newly-collected card the default for invoices + the subscription.","tags":["Billing"]}},"/api/v1/billing/plans":{"get":{"description":"<br/>Deliberately ANONYMOUS: this is the price list. ``/packages`` is a public<br/>route in the SPA, so gating it behind ``@login_required`` bounced a visitor<br/>who had not signed in yet to ``/?reason=session-expired`` instead of<br/>showing them the plans (mobile QA fix round 1). The payload carries the<br/>same numbers the marketing pricing page publishes and nothing about any<br/>user; every other billing route stays gated. Also allowlisted by endpoint<br/>name in ``app/__init__.py`` so the app-wide auth gate lets it through.","operationId":"billing_api_api_plans_plans_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlansResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The plan catalog (prices in cents + monthly credit allotments).","tags":["Billing"]}},"/api/v1/billing/redeem-code":{"post":{"description":"<br/>A trial code grants the capped trial entitlement, exactly as the MCP<br/>paywall route already did. A plan_grant code creates a real Stripe<br/>subscription discounted to zero, so a design partner ends up with the full<br/>package and every downstream surface treats them as a normal subscriber.<br/><br/>Rate limited on the same backoff bucket as the MCP redeem route, because<br/>this endpoint is the other door into the same guessable secret.","operationId":"billing_api_api_redeem_code_redeem_code_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RedeemCodeRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RedeemCodeResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Redeem a partner code on the packages step.","tags":["Billing"]}},"/api/v1/billing/resume":{"post":{"operationId":"billing_api_api_resume_account_resume_post","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionStatusResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Resume a paused account immediately (billing and access restart).","tags":["Billing"]}},"/api/v1/billing/retention-offer":{"post":{"description":"recording the exit-survey answer with the kept outcome.","operationId":"billing_api_api_retention_offer_retention_offer_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetentionOfferRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionStatusResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Apply a keep-the-account offer from the flow's last screen,","tags":["Billing"]}},"/api/v1/billing/setup-intent":{"post":{"operationId":"billing_api_api_setup_intent_setup_intent_post","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupIntentResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Start a card change: returns a SetupIntent client secret for the Element.","tags":["Billing"]}},"/api/v1/billing/subscription":{"get":{"operationId":"billing_api_api_subscription_subscription_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionStatusResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The current user's subscription + credit state.","tags":["Billing"]}},"/api/v1/billing/upgrade":{"post":{"operationId":"billing_api_api_upgrade_upgrade_post","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionStatusResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Convert the trial to a paid subscription immediately.","tags":["Billing"]}},"/api/v1/campaign-studio/admin/generate-scene-previews":{"post":{"operationId":"campaign_studio_api_api_generate_scene_previews_admin_generate_scene_previews_post","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Batch-generate previews for all scene templates. Admin only.","tags":["Campaign Studio"]}},"/api/v1/campaign-studio/avatar-images/{image_id}/assign-template":{"post":{"operationId":"campaign_studio_api_api_assign_template_avatar_images__int_image_id__assign_template_post","parameters":[{"in":"path","name":"image_id","required":true,"schema":{"title":"Image Id","type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssignTemplateBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Manually assign a scene template to an avatar image.","tags":["Campaign Studio"]}},"/api/v1/campaign-studio/avatar-images/{image_id}/auto-assign-template":{"post":{"operationId":"campaign_studio_api_api_auto_assign_template_avatar_images__int_image_id__auto_assign_template_post","parameters":[{"in":"path","name":"image_id","required":true,"schema":{"title":"Image Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Auto-assign the best scene template to an avatar image.","tags":["Campaign Studio"]}},"/api/v1/campaign-studio/campaigns":{"get":{"description":"<br/>Scoped to the caller's own campaigns in SQL via `scope_query`<br/>inside the repository, admins included (default-own scoping, spec<br/>\u00a73.5, 2026-08-11).","operationId":"campaign_studio_api_api_list_campaigns_campaigns_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignsListResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"List campaigns (used by /campaign-studio).","tags":["Campaign Studio"]},"post":{"operationId":"campaign_studio_api_api_create_campaign_campaigns_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCampaignBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Create a new campaign owned by the caller.","tags":["Campaign Studio"]}},"/api/v1/campaign-studio/campaigns/{campaign_id}/approve-all":{"post":{"operationId":"campaign_studio_api_api_approve_all_campaigns__int_campaign_id__approve_all_post","parameters":[{"in":"path","name":"campaign_id","required":true,"schema":{"title":"Campaign Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Approve all items in a campaign.","tags":["Campaign Studio"]}},"/api/v1/campaign-studio/campaigns/{campaign_id}/items/{item_id}/approve":{"post":{"operationId":"campaign_studio_api_api_approve_item_campaigns__int_campaign_id__items__int_item_id__approve_post","parameters":[{"in":"path","name":"campaign_id","required":true,"schema":{"title":"Campaign Id","type":"integer"}},{"in":"path","name":"item_id","required":true,"schema":{"title":"Item Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Approve a single campaign item. Caller must own the parent campaign.","tags":["Campaign Studio"]}},"/api/v1/campaign-studio/campaigns/{campaign_id}/items/{item_id}/regenerate-scene":{"post":{"operationId":"campaign_studio_api_api_regenerate_scene_campaigns__int_campaign_id__items__int_item_id__regenerate_scene_post","parameters":[{"in":"path","name":"campaign_id","required":true,"schema":{"title":"Campaign Id","type":"integer"}},{"in":"path","name":"item_id","required":true,"schema":{"title":"Item Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Regenerate the scene for a campaign item.","tags":["Campaign Studio"]}},"/api/v1/campaign-studio/campaigns/{campaign_id}/items/{item_id}/reject":{"post":{"operationId":"campaign_studio_api_api_reject_item_campaigns__int_campaign_id__items__int_item_id__reject_post","parameters":[{"in":"path","name":"campaign_id","required":true,"schema":{"title":"Campaign Id","type":"integer"}},{"in":"path","name":"item_id","required":true,"schema":{"title":"Item Id","type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RejectItemBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Reject a single campaign item with an optional reason.","tags":["Campaign Studio"]}},"/api/v1/campaign-studio/campaigns/{campaign_id}/launch":{"post":{"operationId":"campaign_studio_api_api_launch_campaign_campaigns__int_campaign_id__launch_post","parameters":[{"in":"path","name":"campaign_id","required":true,"schema":{"title":"Campaign Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Launch a campaign (kick off video generation).","tags":["Campaign Studio"]}},"/api/v1/campaign-studio/campaigns/{campaign_id}/publish":{"post":{"operationId":"campaign_studio_api_api_publish_campaign_campaigns__int_campaign_id__publish_post","parameters":[{"in":"path","name":"campaign_id","required":true,"schema":{"title":"Campaign Id","type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublishCampaignBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Publish a campaign with optional stagger between posts.","tags":["Campaign Studio"]}},"/api/v1/campaign-studio/campaigns/{campaign_id}/status":{"get":{"operationId":"campaign_studio_api_api_campaign_status_campaigns__int_campaign_id__status_get","parameters":[{"in":"path","name":"campaign_id","required":true,"schema":{"title":"Campaign Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Get the current status of a campaign.","tags":["Campaign Studio"]}},"/api/v1/campaign-studio/scene-template-categories":{"get":{"operationId":"campaign_studio_api_api_scene_template_categories_scene_template_categories_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SceneTemplateCategoriesResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Distinct YAML scene template categories.","tags":["Campaign Studio"]}},"/api/v1/campaign-studio/scene-templates":{"get":{"description":"<br/>Scene templates are global presets (nullable ``owner_id`` per<br/>CLAUDE.md \u00a73 \u2014 \"everyone reads; only admins write\"), so this GET<br/>is intentionally public-read. The auth gate in ``create_app()``<br/>still gates the path in production where Cognito is configured;<br/>in test / CodeBuild safety-check environments without Cognito the<br/>gate skips and this list is reachable anonymously, which is what<br/>``tests/test_safety.py::test_api_returns_200`` asserts.<br/><br/>The ``@login_required`` originally landed here in 952c915<br/>(\"full route hardening\") but contradicts both the global-preset<br/>design and the safety smoke test, so it was removed.","operationId":"campaign_studio_api_api_scene_templates_scene_templates_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SceneTemplatesResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"List scene templates, optionally filtered by category.","tags":["Campaign Studio"]}},"/api/v1/campaign-studio/scene-templates/{template_id}/avatar-coverage":{"get":{"description":"<br/>The template itself is a global preset, but the avatar list it<br/>enumerates is per-user-owned, so it's scoped to the caller in SQL.","operationId":"campaign_studio_api_api_template_coverage_scene_templates__int_template_id__avatar_coverage_get","parameters":[{"in":"path","name":"template_id","required":true,"schema":{"title":"Template Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Get avatar coverage for a scene template.","tags":["Campaign Studio"]}},"/api/v1/campaign-studio/scene-templates/{template_id}/generate-preview":{"post":{"operationId":"campaign_studio_api_api_generate_single_preview_scene_templates__int_template_id__generate_preview_post","parameters":[{"in":"path","name":"template_id","required":true,"schema":{"title":"Template Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Generate a preview for a single scene template.","tags":["Campaign Studio"]}},"/api/v1/campaign-studio/wizard/bootstrap":{"get":{"description":"<br/>Scripts and avatars are scoped to the caller in SQL (the user-owned<br/>halves of the bundle). Scene templates are global presets.","operationId":"campaign_studio_api_api_wizard_bootstrap_wizard_bootstrap_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WizardBootstrapResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Bundled wizard bootstrap data (scripts + templates + categories + avatars).","tags":["Campaign Studio"]}},"/api/v1/carousels":{"get":{"operationId":"carousels_api_api_list_carousels_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CarouselListResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The caller's carousels, newest first.","tags":["Carousels"]},"post":{"operationId":"carousels_api_api_create_carousel_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCarouselBody"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCarouselResponse"}}},"description":"Created"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Direct the slides, reserve credits, and fan out generation.","tags":["Carousels"]}},"/api/v1/carousels/drafts":{"post":{"operationId":"carousels_api_api_create_draft_drafts_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DraftBody"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDraftResponse"}}},"description":"Created"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"tags":["Carousels"]}},"/api/v1/carousels/drafts/{draft_id}":{"get":{"operationId":"carousels_api_api_get_draft_drafts__int_draft_id__get","parameters":[{"in":"path","name":"draft_id","required":true,"schema":{"title":"Draft Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DraftResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"tags":["Carousels"]},"patch":{"operationId":"carousels_api_api_patch_draft_drafts__int_draft_id__patch","parameters":[{"in":"path","name":"draft_id","required":true,"schema":{"title":"Draft Id","type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DraftBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DraftResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"tags":["Carousels"]}},"/api/v1/carousels/templates":{"get":{"operationId":"carousels_api_api_list_templates_templates_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplatesResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The v1 slide-structure template set for the wizard picker.","tags":["Carousels"]}},"/api/v1/carousels/{carousel_id}":{"delete":{"operationId":"carousels_api_api_delete_carousel__int_carousel_id__delete","parameters":[{"in":"path","name":"carousel_id","required":true,"schema":{"title":"Carousel Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"tags":["Carousels"]},"get":{"operationId":"carousels_api_api_get_carousel__int_carousel_id__get","parameters":[{"in":"path","name":"carousel_id","required":true,"schema":{"title":"Carousel Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CarouselResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"tags":["Carousels"]}},"/api/v1/carousels/{carousel_id}/download":{"get":{"operationId":"carousels_api_api_download_carousel__int_carousel_id__download_get","parameters":[{"in":"path","name":"carousel_id","required":true,"schema":{"title":"Carousel Id","type":"integer"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Zip of the final slide PNGs (slide-01.png, slide-02.png, ...).","tags":["Carousels"]}},"/api/v1/carousels/{carousel_id}/slides/{slide_id}":{"patch":{"operationId":"carousels_api_api_update_slide_copy__int_carousel_id__slides__int_slide_id__patch","parameters":[{"in":"path","name":"carousel_id","required":true,"schema":{"title":"Carousel Id","type":"integer"}},{"in":"path","name":"slide_id","required":true,"schema":{"title":"Slide Id","type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSlideCopyBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlideResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Edit overlay copy; re-composites the slide for free.","tags":["Carousels"]}},"/api/v1/carousels/{carousel_id}/slides/{slide_id}/image":{"post":{"description":"<br/>Multipart: `file` (png, jpg, webp or heic, up to 25 MB) OR<br/>`avatar_image_id` (one of the carousel avatar's saved scenes and<br/>photos). No generation and no credits; not counted as a reroll.","operationId":"carousels_api_api_replace_slide_image__int_carousel_id__slides__int_slide_id__image_post","parameters":[{"in":"path","name":"carousel_id","required":true,"schema":{"title":"Carousel Id","type":"integer"}},{"in":"path","name":"slide_id","required":true,"schema":{"title":"Slide Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlideResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Replace a slide's image with your own picture or a saved one (free).","tags":["Carousels"]}},"/api/v1/carousels/{carousel_id}/slides/{slide_id}/refine":{"post":{"description":"<br/>The current image is the pixel starting point and the avatar's face<br/>reference rides along, so the notes can change anything while the<br/>identity holds (the avatar-creation refine pattern).","operationId":"carousels_api_api_refine_slide__int_carousel_id__slides__int_slide_id__refine_post","parameters":[{"in":"path","name":"carousel_id","required":true,"schema":{"title":"Carousel Id","type":"integer"}},{"in":"path","name":"slide_id","required":true,"schema":{"title":"Slide Id","type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefineSlideBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlideResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Transform one slide's image with free-form change notes (1 credit).","tags":["Carousels"]}},"/api/v1/carousels/{carousel_id}/slides/{slide_id}/reroll":{"post":{"operationId":"carousels_api_api_reroll_slide__int_carousel_id__slides__int_slide_id__reroll_post","parameters":[{"in":"path","name":"carousel_id","required":true,"schema":{"title":"Carousel Id","type":"integer"}},{"in":"path","name":"slide_id","required":true,"schema":{"title":"Slide Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlideResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Regenerate one slide's image (1 credit, attempts capped).","tags":["Carousels"]}},"/api/v1/carousels/{carousel_id}/status":{"get":{"operationId":"carousels_api_api_carousel_status__int_carousel_id__status_get","parameters":[{"in":"path","name":"carousel_id","required":true,"schema":{"title":"Carousel Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CarouselStatusResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Per-slide generation status; the detail page polls this.","tags":["Carousels"]}},"/api/v1/copy-ingest":{"post":{"description":"<br/>Body: { url: \"https://instagram.com/reel/...\" }<br/><br/>Creates a CopyHistory row in 'queued' state, hands off to the<br/>`run_queued_ingest` Celery task, and returns 202 + the ingest_id<br/>so the frontend can poll GET /api/v1/copy-ingest/history.<br/><br/>Dedupes per (owner, url): re-posting the same URL from the same<br/>user returns the existing row's id with its current status (200,<br/>not 202) so the client's poll loop keeps working.<br/><br/>Worker handoff: the row stays in 'queued' state until the Celery<br/>task picks it up (`app/modules/copy_ingest/tasks.py::run_queued_ingest`).<br/><br/>`level` picks the extraction tier (transcript|scene|full|replica).<br/>'replica' (Clone-a-Reel, 2026-07-10) adds the per-shot source<br/>breakdown used to auto-build a replicated storyboard; re-posting a<br/>URL with a higher level than its existing row upgrades that row<br/>in place.<br/><br/>429 `COPY_INGEST_DAILY_CAP` once the caller has started<br/>`COPY_INGEST_DAILY_CAP` new copies inside the window (20 by default,<br/>admins exempt). A dedupe and a free clone of a ready analysis never<br/>count; see `daily_cap.py`.","operationId":"copy_ingest_api_api_copy_ingest_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IngestBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IngestQueuedResponse"}}},"description":"OK"},"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IngestQueuedResponse"}}},"description":"Accepted"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Canonical queued-ingest endpoint (Phase 2B, 2026-05-25).","tags":["Copy Ingest"]}},"/api/v1/copy-ingest/extract":{"post":{"operationId":"copy_ingest_api_api_copy_extract_extract_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Run the extraction pipeline (tiered: transcript / scene / full).","tags":["Copy Ingest"]}},"/api/v1/copy-ingest/history":{"get":{"description":"<br/>Scoped to the caller: users see their own newest copy ingests (the<br/>owner filter runs in SQL before the limit); admins see every owner's.<br/><br/>`state` narrows the page: 'all' (default, also what an omitted or<br/>unrecognised value means) returns every lifecycle state, 'done'<br/>only settled rows, 'in_process' only queued / processing / failed.","operationId":"copy_ingest_api_api_copy_history_history_get","parameters":[{"in":"query","name":"limit","required":false,"schema":{"default":20,"title":"Limit","type":"integer"}},{"in":"query","name":"state","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"State"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HistoryListResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Recent copy-extraction history, newest first.","tags":["Copy Ingest"]}},"/api/v1/copy-ingest/prewarm":{"post":{"description":"<br/>The wizard's source step calls it when it opens and every 15 s while it is shown,<br/>until a link is pasted. At most one ping per user per 15 s; extra calls return<br/>`pinged: false`. A no-op without Modal credentials. Never waits on the GPU.","operationId":"copy_ingest_api_api_copy_prewarm_prewarm_post","responses":{"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrewarmResponse"}}},"description":"Accepted"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Wake the speaker detection GPU while the user is on the new copy video screen.","tags":["Copy Ingest"]}},"/api/v1/copy-ingest/upload":{"post":{"operationId":"copy_ingest_api_api_copy_upload_upload_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Upload a pre-transcribed reel script (CopyHistory + Script rows).","tags":["Copy Ingest"]}},"/api/v1/copy-ingest/{ingest_id}":{"delete":{"description":"<br/>Settled rows are the copy cache and processing rows are owned by a<br/>live worker, so both refuse with 409; Retry for a failed row is a<br/>plain re-POST of the same URL (queueing handles it in place).","operationId":"copy_ingest_api_api_copy_ingest_cancel__int_ingest_id__delete","parameters":[{"in":"path","name":"ingest_id","required":true,"schema":{"title":"Ingest Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Cancel a queued or failed ingest (Copied Reels page).","tags":["Copy Ingest"]},"get":{"description":"<br/>Used by the Clone-a-Reel flow after the poll loop reports ready: the<br/>wizard reads `replica_breakdown` (shot list + resolved source-frame<br/>URLs) or its {\"error\": ...} payload naming why the analysis degraded,<br/>so the client can alert the user about the fallback.","operationId":"copy_ingest_api_api_copy_ingest_detail__int_ingest_id__get","parameters":[{"in":"path","name":"ingest_id","required":true,"schema":{"title":"Ingest Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IngestDetail"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Full record for one ingest, including the replica breakdown.","tags":["Copy Ingest"]}},"/api/v1/dashboard/summary":{"get":{"description":"<br/>Scoped to the caller: every user, admins included, sees only their<br/>own asset counts and their own recent videos (default-own scoping,<br/>spec \u00a73.5, 2026-08-11). Platform-wide totals need a future admin<br/>ops surface.","operationId":"dashboard_api_api_dashboard_summary_summary_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardSummaryResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Dashboard summary payload (avatar/video counts + recent videos strip).","tags":["Dashboard"]}},"/api/v1/diagnostics/admin/cleanup":{"post":{"description":"<br/>Dry-run by default. Pass `{\"confirm\": \"DELETE\"}` to execute.<br/>Admin only.","operationId":"diagnostics_api_api_admin_cleanup_admin_cleanup_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminCleanupRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminCleanupResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Bulk delete non-primary scenes, videos, scripts, posts, pipeline runs.","tags":["Diagnostics"]}},"/api/v1/diagnostics/all":{"get":{"operationId":"diagnostics_api_diag_all_all_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AllChecksResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Run all diagnostic checks and return aggregated summary.","tags":["Diagnostics"]}},"/api/v1/diagnostics/brightdata":{"get":{"operationId":"diagnostics_api_diag_brightdata_brightdata_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiagnosticCheckResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Check BrightData proxy connectivity.","tags":["Diagnostics"]}},"/api/v1/diagnostics/captions":{"get":{"operationId":"diagnostics_api_diag_captions_captions_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiagnosticCheckResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Check captions pipeline health.","tags":["Diagnostics"]}},"/api/v1/diagnostics/db":{"get":{"operationId":"diagnostics_api_diag_db_db_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiagnosticCheckResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Check database connectivity.","tags":["Diagnostics"]}},"/api/v1/diagnostics/debug/gemini-config":{"get":{"operationId":"diagnostics_api_api_debug_gemini_config_debug_gemini_config_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeminiConfigResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Return non-sensitive Gemini config status for ECS debugging.","tags":["Diagnostics"]}},"/api/v1/diagnostics/egress-ip":{"get":{"operationId":"diagnostics_api_diag_egress_ip_egress_ip_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EgressIpResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Return the current egress IP address.","tags":["Diagnostics"]}},"/api/v1/diagnostics/env":{"get":{"operationId":"diagnostics_api_diag_env_env_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvCheckResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Check required and recommended environment variables. Admin only.","tags":["Diagnostics"]}},"/api/v1/diagnostics/gemini":{"get":{"operationId":"diagnostics_api_diag_gemini_gemini_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiagnosticCheckResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Check Gemini text generation connectivity.","tags":["Diagnostics"]}},"/api/v1/diagnostics/gemini-image":{"get":{"operationId":"diagnostics_api_diag_gemini_image_gemini_image_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiagnosticCheckResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Check Gemini image generation connectivity.","tags":["Diagnostics"]}},"/api/v1/diagnostics/heygen":{"get":{"operationId":"diagnostics_api_diag_heygen_heygen_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiagnosticCheckResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Check HeyGen API connectivity.","tags":["Diagnostics"]}},"/api/v1/diagnostics/missing-face-images":{"get":{"description":"<br/>The reconciliation the face pipeline never had: a lost object used to<br/>surface only as a 403 on the avatar page. `thumb_1080` marks the rows<br/>a restore can still be built from.","operationId":"diagnostics_api_diag_missing_face_images_missing_face_images_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MissingFaceImagesResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"List avatars whose main picture is no longer in storage. Admin only.","tags":["Diagnostics"]}},"/api/v1/diagnostics/sentry-boom":{"get":{"operationId":"diagnostics_api_diag_sentry_boom_sentry_boom_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Deliberately raise an unhandled error to verify Sentry API capture.","tags":["Diagnostics"]}},"/api/v1/diagnostics/sentry-boom-task":{"get":{"operationId":"diagnostics_api_diag_sentry_boom_task_sentry_boom_task_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Enqueue a deliberately failing job to verify Sentry worker capture.","tags":["Diagnostics"]}},"/api/v1/diagnostics/storage":{"get":{"operationId":"diagnostics_api_diag_storage_storage_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiagnosticCheckResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Check storage backend connectivity.","tags":["Diagnostics"]}},"/api/v1/diagnostics/whoami":{"get":{"description":"<br/>Use cases:<br/><br/>- Confirm session-based auth is wired correctly (`session_present`).<br/>- Confirm a Bearer JWT was accepted (`bearer_token_present`).<br/>- Inspect the Cognito groups your token carries (`groups`).<br/>- List every Cognito identity (Google / Facebook / email) linked<br/>  to your local user row (`identities`).<br/>- Sanity-check the pool the backend is pointed at (`cognito_*`).<br/>- See whether the request runs under an admin impersonation grant<br/>  (`impersonating` + `real_admin_email`, spec \u00a73.6); the SPA<br/>  banner renders from this, the server's truth.<br/>- Read whether the caller has a product subscription at all<br/>  (`has_subscription`), which is what tells the partner shell<br/>  whether a Product tab would lead anywhere but the paywall.<br/>- Read whether the caller is in the affiliate program at all<br/>  (`is_affiliate`), which is what lets the plan paywall offer a<br/>  partner a route back to their portal.<br/><br/>Authenticated callers only \u2014 anonymous requests get 401.","operationId":"diagnostics_api_api_whoami_whoami_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthWhoamiResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Return everything the auth gate decided about this request.","tags":["Diagnostics"]}},"/api/v1/followed-accounts":{"get":{"description":"<br/>Regular users see their own accounts plus every system account (the<br/>AvatarFactory Verified AI personas and the real influencers we track for<br/>everyone). Admins see the same; Discovered accounts stay on their own<br/>admin route. `AccountCategory` is a global taxonomy so its rows are<br/>returned unfiltered.<br/><br/>`kind=ai|real` narrows to one kind of creator. The page itself does not<br/>send it (it holds one list and switches tabs over it, so its tab counts<br/>always match the screen); it is here for API callers that want one set.","operationId":"followed_accounts_api_api_list_followed_get","parameters":[{"in":"query","name":"archived","required":false,"schema":{"default":0,"title":"Archived","type":"integer"}},{"in":"query","name":"favorites_only","required":false,"schema":{"default":false,"title":"Favorites Only","type":"boolean"}},{"in":"query","name":"kind","required":false,"schema":{"anyOf":[{"enum":["ai","real"],"type":"string"},{"type":"null"}],"default":null,"title":"Kind"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FollowedAccountsListResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"List view used by /followed-accounts.","tags":["Followed Accounts"]},"post":{"description":"<br/>Canonical create endpoint for the Followed Accounts page (Phase 2B,<br/>2026-05-25). Body shape: {platform, handle}. Real profile / follower<br/>enrichment is deferred to a background job and noted as a Phase 2B<br/>follow-up; the row is created with display_name = handle and<br/>follower_count = null until the enrichment worker runs.","operationId":"followed_accounts_api_api_track_new_account_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackNewAccountRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackedAccountResponse"}}},"description":"Created"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Track a new Instagram or TikTok account for the caller.","tags":["Followed Accounts"]}},"/api/v1/followed-accounts/add":{"post":{"operationId":"followed_accounts_api_add_account_add_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddAccountRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountAddedResponse"}}},"description":"Created"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal Server Error"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Add a new account to the followed list, owned by the caller.","tags":["Followed Accounts"]}},"/api/v1/followed-accounts/background-categories":{"get":{"operationId":"followed_accounts_api_list_background_categories_background_categories_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoriesResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"List categories available for background assignment.","tags":["Followed Accounts"]}},"/api/v1/followed-accounts/bulk-update":{"post":{"operationId":"followed_accounts_api_bulk_update_profiles_bulk_update_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkUpdateProfilesRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkUpdateResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal Server Error"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Bulk update profile data for multiple accounts.","tags":["Followed Accounts"]}},"/api/v1/followed-accounts/categories":{"post":{"operationId":"followed_accounts_api_create_category_categories_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryCreateRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryResponse"}}},"description":"Created"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Create a new account category.","tags":["Followed Accounts"]}},"/api/v1/followed-accounts/categories/{cat_id}":{"delete":{"operationId":"followed_accounts_api_delete_category_categories__int_cat_id__delete","parameters":[{"in":"path","name":"cat_id","required":true,"schema":{"title":"Cat Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Delete an account category and unlink it from all accounts.","tags":["Followed Accounts"]}},"/api/v1/followed-accounts/categories/{cat_id}/scenes":{"patch":{"description":"<br/>Categories have nullable owner (global taxonomy) \u2014 gated by login<br/>only; per-category ownership enforcement is a follow-up.","operationId":"followed_accounts_api_update_category_scenes_categories__int_cat_id__scenes_patch","parameters":[{"in":"path","name":"cat_id","required":true,"schema":{"title":"Cat Id","type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryScenesRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryScenesOkResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Update the scene categories for a given account category.","tags":["Followed Accounts"]}},"/api/v1/followed-accounts/classify-suggest":{"post":{"operationId":"followed_accounts_api_classify_suggest_classify_suggest_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClassifySuggestRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClassifySuggestResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal Server Error"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Return AI-suggested categories for an Instagram username.","tags":["Followed Accounts"]}},"/api/v1/followed-accounts/discovered":{"get":{"description":"<br/>Lior, 2026-09-30: \"the discovered is for everyone not only admin\". Scoped by<br/>the caller's own `account_discoveries` rows, so it is never a cross-tenant<br/>read and an admin gets their own pastes here too; the platform-wide list, the<br/>Interest count and the promote action stay on the admin route. Plan-gated<br/>with the rest of Tracked Competitors. Why the shape differs from the admin<br/>row: `discovery.list_discovered_for_user`.","operationId":"followed_accounts_api_api_list_my_discovered_discovered_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiscoveredAccountsResponse"}}},"description":"OK"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Payment Required"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The creators the caller's OWN Copy From Reel pastes surfaced (MIP-705).","tags":["Followed Accounts"]}},"/api/v1/followed-accounts/export":{"get":{"operationId":"followed_accounts_api_export_accounts_export_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportPayloadResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Export all followed accounts as JSON, scoped to the caller.","tags":["Followed Accounts"]}},"/api/v1/followed-accounts/global":{"post":{"description":"<br/>Global accounts are visible to all users and cannot be modified or<br/>deleted by regular users. The account is created with is_global=True<br/>and no profile scrape; enrichment is deferred to the admin scan flow.","operationId":"followed_accounts_api_create_global_account_global_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGlobalAccountRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackedAccountResponse"}}},"description":"Created"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Create an AvatarFactory Verified (global) account. Admin only.","tags":["Followed Accounts"]}},"/api/v1/followed-accounts/global/{account_id}":{"delete":{"description":"<br/>Returns 400 if the account exists but is not a global account \u2014 use<br/>DELETE /<id> for personal account deletion.","operationId":"followed_accounts_api_delete_global_account_global__int_account_id__delete","parameters":[{"in":"path","name":"account_id","required":true,"schema":{"title":"Account Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Permanently delete an AvatarFactory Verified account. Admin only.","tags":["Followed Accounts"]}},"/api/v1/followed-accounts/rescan-all":{"post":{"description":"<br/>Global (AvatarFactory Verified) accounts are excluded for regular<br/>users \u2014 a separate scheduled process handles those. Admins rescan<br/>everything.","operationId":"followed_accounts_api_rescan_all_accounts_rescan_all_post","parameters":[{"in":"query","name":"category_id","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Category Id"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RescanAllResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal Server Error"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Stream a full rescan of the caller's own followed accounts as SSE.","tags":["Followed Accounts"]}},"/api/v1/followed-accounts/rescan-failed/{run_id}":{"post":{"operationId":"followed_accounts_api_rescan_failed_accounts_rescan_failed__int_run_id__post","parameters":[{"in":"path","name":"run_id","required":true,"schema":{"title":"Run Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RescanFailedResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal Server Error"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Stream a rescan of all failed accounts from a previous run as SSE.","tags":["Followed Accounts"]}},"/api/v1/followed-accounts/scan-runs":{"get":{"description":"<br/>Scoped to the caller in SQL via `scope_query` inside the repository;<br/>admins see all runs.","operationId":"followed_accounts_api_scan_runs_list_scan_runs_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanRunsListResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"List historical scan runs.","tags":["Followed Accounts"]}},"/api/v1/followed-accounts/scan-runs/{run_id}":{"get":{"operationId":"followed_accounts_api_scan_run_detail_scan_runs__int_run_id__get","parameters":[{"in":"path","name":"run_id","required":true,"schema":{"title":"Run Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanRunDetailResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Return detailed results for a specific scan run.","tags":["Followed Accounts"]}},"/api/v1/followed-accounts/tags":{"get":{"operationId":"followed_accounts_api_list_all_tags_tags_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagsResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Return all tags with their account counts, scoped to the caller.","tags":["Followed Accounts"]}},"/api/v1/followed-accounts/{account_id}":{"delete":{"description":"<br/>A follower drops only their follow. The steward's remove deletes the<br/>row unless others follow it, in which case the earliest follower<br/>becomes the steward and the account, its reels and its history stay<br/>(Lior, 2026-09-16).","operationId":"followed_accounts_api_remove_account__int_account_id__delete","parameters":[{"in":"path","name":"account_id","required":true,"schema":{"title":"Account Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Remove a followed account.","tags":["Followed Accounts"]}},"/api/v1/followed-accounts/{account_id}/archive":{"post":{"operationId":"followed_accounts_api_archive_account__int_account_id__archive_post","parameters":[{"in":"path","name":"account_id","required":true,"schema":{"title":"Account Id","type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArchiveAccountRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountUsernameOkResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Archive a followed account (a follower archives only their own follow).","tags":["Followed Accounts"]}},"/api/v1/followed-accounts/{account_id}/categories":{"patch":{"description":"<br/>A follower on a shared row keeps one category of their own (the<br/>primary); the steward's assignments are untouched.","operationId":"followed_accounts_api_update_account_categories__int_account_id__categories_patch","parameters":[{"in":"path","name":"account_id","required":true,"schema":{"title":"Account Id","type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAccountCategoriesRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountCategoriesOkResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Replace all category assignments for an account.","tags":["Followed Accounts"]}},"/api/v1/followed-accounts/{account_id}/category":{"patch":{"operationId":"followed_accounts_api_update_account_category__int_account_id__category_patch","parameters":[{"in":"path","name":"account_id","required":true,"schema":{"title":"Account Id","type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAccountCategoryRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountCategoryOkResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Set the primary category for an account (a follower's own category on a shared row).","tags":["Followed Accounts"]}},"/api/v1/followed-accounts/{account_id}/history":{"get":{"operationId":"followed_accounts_api_account_scan_history__int_account_id__history_get","parameters":[{"in":"path","name":"account_id","required":true,"schema":{"title":"Account Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountScanHistoryResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Return scan history for a followed account.","tags":["Followed Accounts"]}},"/api/v1/followed-accounts/{account_id}/rescan":{"post":{"operationId":"followed_accounts_api_rescan_account__int_account_id__rescan_post","parameters":[{"in":"path","name":"account_id","required":true,"schema":{"title":"Account Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RescanResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal Server Error"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Trigger a fresh scrape for a single account.","tags":["Followed Accounts"]}},"/api/v1/followed-accounts/{account_id}/tags":{"patch":{"operationId":"followed_accounts_api_update_account_tags__int_account_id__tags_patch","parameters":[{"in":"path","name":"account_id","required":true,"schema":{"title":"Account Id","type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAccountTagsRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountTagsOkResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Update tags for an account. Tags are shared, so only the steward sets them.","tags":["Followed Accounts"]}},"/api/v1/followed-accounts/{account_id}/unarchive":{"post":{"operationId":"followed_accounts_api_unarchive_account__int_account_id__unarchive_post","parameters":[{"in":"path","name":"account_id","required":true,"schema":{"title":"Account Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountUsernameOkResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Unarchive a previously archived account (or the caller's own follow).","tags":["Followed Accounts"]}},"/api/v1/funnel-store":{"get":{"operationId":"funnel_store_api_api_get_store_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StoreRequestResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The caller's saved digital product store picks, or 404 before the first save.","tags":["Funnel Store"]},"put":{"description":"<br/>`claimed: true` marks the Shopify claim and emits `funnel_store_completed`.","operationId":"funnel_store_api_api_save_store_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveStoreRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StoreRequestResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Save the product, its title and price, and the store theme.","tags":["Funnel Store"]}},"/api/v1/funnel-store/upload":{"post":{"description":"<br/>Replaces an earlier upload. Emits `funnel_store_upload_created`.","operationId":"funnel_store_api_api_upload_product_upload_post","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Request Entity Too Large"},"415":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unsupported Media Type"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Upload the buyer's own product: multipart field `file`, a PDF or .txt up to 25 MB.","tags":["Funnel Store"]}},"/api/v1/generate/drafts":{"get":{"description":"<br/>Scoped to the caller: regular users see only their own drafts;<br/>admins see every in-progress draft. The repository applies<br/>`scope_query`, so the filter runs in SQL \u2014 no post-fetch trimming.","operationId":"generate_api_api_in_progress_drafts_drafts_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DraftListResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"In-progress video drafts (used by /generate).","tags":["Generate"]}},"/api/v1/generate/wizard-session/{draft_id}":{"get":{"operationId":"generate_api_api_wizard_session_wizard_session__int_draft_id__get","parameters":[{"in":"path","name":"draft_id","required":true,"schema":{"title":"Draft Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WizardSessionResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Wizard bootstrap: draft + active avatars + scenes_by_avatar + backgrounds.","tags":["Generate"]}},"/api/v1/ideation/create-avatar":{"post":{"operationId":"ideation_api_api_ideation_create_avatar_create_avatar_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAvatarRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAvatarResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal Server Error"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Create a full avatar from ideation data.","tags":["Ideation"]}},"/api/v1/ideation/dashboard":{"get":{"description":"<br/>Scoped to the caller in SQL: scripts, scraped-account aggregates,<br/>avatars and tracked accounts are all filtered by `scope_query`.","operationId":"ideation_api_api_ideation_dashboard_dashboard_get","parameters":[{"in":"query","name":"min_views","required":false,"schema":{"default":0,"title":"Min Views","type":"integer"}},{"in":"query","name":"account","required":false,"schema":{"default":"","title":"Account","type":"string"}},{"in":"query","name":"sort","required":false,"schema":{"default":"views","title":"Sort","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdeationDashboardResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Ideation dashboard view (used by /ideation).","tags":["Ideation"]}},"/api/v1/ideation/draft/{draft_id}":{"get":{"operationId":"ideation_api_api_ideation_get_draft_draft__int_draft_id__get","parameters":[{"in":"path","name":"draft_id","required":true,"schema":{"title":"Draft Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DraftResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Retrieve a single ideation draft by ID (owner / admin only).","tags":["Ideation"]}},"/api/v1/ideation/draft/{draft_id}/delete":{"post":{"operationId":"ideation_api_api_ideation_delete_draft_draft__int_draft_id__delete_post","parameters":[{"in":"path","name":"draft_id","required":true,"schema":{"title":"Draft Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteDraftResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Delete an ideation draft by ID (owner / admin only).","tags":["Ideation"]}},"/api/v1/ideation/drafts":{"get":{"operationId":"ideation_api_api_ideation_drafts_drafts_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DraftsListResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal Server Error"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"List ideation drafts visible to the caller (scoped to owner).","tags":["Ideation"]}},"/api/v1/ideation/expand-story":{"post":{"operationId":"ideation_api_api_ideation_expand_story_expand_story_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExpandStoryRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExpandStoryResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal Server Error"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Expand a story summary into a full character backstory.","tags":["Ideation"]}},"/api/v1/ideation/generate-face":{"post":{"description":"<br/>Billed exactly like the SPA face path so no route hands out free vendor<br/>spend: a free account's first images use the free allowance (over the cap<br/>is a 402); a paid account is charged 1 image credit via the meter<br/>(reserved before the model call, settled on success, released on failure);<br/>admins bypass.","operationId":"ideation_api_api_ideation_generate_face_generate_face_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateFaceRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateFaceResponse"}}},"description":"OK"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Payment Required"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal Server Error"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Generate the initial face reference photo for an avatar persona.","tags":["Ideation"]}},"/api/v1/ideation/hooks":{"post":{"operationId":"ideation_api_api_ideation_hooks_hooks_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HooksRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HooksResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal Server Error"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Generate viral hook variations from a topic/niche. Stateless (persists nothing).","tags":["Ideation"]}},"/api/v1/ideation/names":{"post":{"operationId":"ideation_api_api_ideation_names_names_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NamesRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NamesResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal Server Error"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Generate culturally authentic name suggestions.","tags":["Ideation"]}},"/api/v1/ideation/save-draft":{"post":{"operationId":"ideation_api_api_ideation_save_draft_save_draft_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveDraftRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveDraftResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal Server Error"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Save or update an ideation draft (ownership-enforced for updates).","tags":["Ideation"]}},"/api/v1/ideation/stories":{"post":{"operationId":"ideation_api_api_ideation_stories_stories_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StoriesRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StoriesResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal Server Error"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Generate story concept summaries for a character persona.","tags":["Ideation"]}},"/api/v1/ideation/trending-ideas":{"post":{"operationId":"ideation_api_api_ideation_trending_ideas_trending_ideas_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrendingIdeasRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrendingIdeasResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal Server Error"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Generate trending idea concepts for an avatar persona.","tags":["Ideation"]}},"/api/v1/integrations/elevenlabs":{"delete":{"operationId":"integrations_api_api_elevenlabs_disconnect_elevenlabs_delete","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrationStatusResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Remove the stored connection. Dependent avatars keep voice_id and show a reconnect state.","tags":["Integrations"]},"get":{"operationId":"integrations_api_api_elevenlabs_status_elevenlabs_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrationStatusResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Connection status. The stored key is never returned.","tags":["Integrations"]},"post":{"operationId":"integrations_api_api_elevenlabs_connect_elevenlabs_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrationStatusResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Verify the pasted key live and store it encrypted. 422 when rejected.","tags":["Integrations"]}},"/api/v1/integrations/elevenlabs/voices":{"get":{"operationId":"integrations_api_api_elevenlabs_voices_elevenlabs_voices_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoicesResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The caller's own ElevenLabs voices, fetched with the caller's stored key.","tags":["Integrations"]}},"/api/v1/marketing-showcase/admin/config":{"put":{"description":"<br/>400 is a slug that is not in the roster. 422 is a payload that broke<br/>a bound in SaveConfigRequest (an over-long note, more than 500<br/>entries): flask-openapi3 rejects those at the boundary, before this<br/>handler runs. 503 is an empty roster, which means the YAML folder is<br/>missing from the deployment and nothing was written.","operationId":"marketing_showcase_api_api_admin_save_config_admin_config_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveConfigRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveConfigResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Store the working order and flags. One transaction, all or nothing.","tags":["Marketing"]}},"/api/v1/marketing-showcase/admin/publish":{"post":{"description":"<br/>409 is a build already running, ours or another one holding<br/>CodeBuild's single concurrent slot. 503 is everything else that<br/>stopped the build from starting (build project unset, throttling,<br/>IAM, connectivity), never a 500.","operationId":"marketing_showcase_api_api_admin_publish_admin_publish_post","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublishResponse"}}},"description":"OK"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Rebuild the marketing site with the saved order.","tags":["Marketing"]}},"/api/v1/marketing-showcase/admin/publish-status":{"get":{"operationId":"marketing_showcase_api_api_admin_publish_status_admin_publish_status_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublishStatusResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Live CodeBuild status of the last publish started from this page.","tags":["Marketing"]}},"/api/v1/marketing-showcase/admin/regen":{"get":{"operationId":"marketing_showcase_api_api_admin_regen_admin_regen_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegenListResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Portraits flagged as needing a regenerated image.","tags":["Marketing"]}},"/api/v1/marketing-showcase/admin/showcase":{"get":{"operationId":"marketing_showcase_api_api_admin_showcase_admin_showcase_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShowcaseResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The roster merged with the saved overrides, as three lists.","tags":["Marketing"]}},"/api/v1/marketing-showcase/config":{"get":{"operationId":"marketing_showcase_api_api_public_config_config_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicConfigResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Saved rail order and visibility. Empty until an admin saves.","tags":["Marketing"]}},"/api/v1/marketing/admin/assets":{"post":{"operationId":"marketing_content_api_api_admin_upload_asset_admin_assets_post","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetUploadResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal Server Error"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Upload one marketing image (multipart: file + path form field).","tags":["Marketing"]}},"/api/v1/marketing/admin/guides":{"get":{"operationId":"marketing_content_api_api_admin_list_guides_admin_guides_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuideListResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Every guide row including drafts. Admin only.","tags":["Marketing"]},"post":{"operationId":"marketing_content_api_api_admin_create_guide_admin_guides_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuideUpsertRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuideResponse"}}},"description":"Created"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Create a guide. Always lands as a draft. Admin only.","tags":["Marketing"]}},"/api/v1/marketing/admin/guides/{slug}":{"delete":{"operationId":"marketing_content_api_api_admin_delete_guide_admin_guides__slug__delete","parameters":[{"in":"path","name":"slug","required":true,"schema":{"title":"Slug","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RebuildResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Delete a guide row; rebuilds if it was live.","tags":["Marketing"]},"put":{"description":"debounced rebuild. Admin only.","operationId":"marketing_content_api_api_admin_update_guide_admin_guides__slug__put","parameters":[{"in":"path","name":"slug","required":true,"schema":{"title":"Slug","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuideUpsertRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuideResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Update a guide. Published guides get updated_date bumped and a","tags":["Marketing"]}},"/api/v1/marketing/admin/guides/{slug}/publish":{"post":{"operationId":"marketing_content_api_api_admin_publish_guide_admin_guides__slug__publish_post","parameters":[{"in":"path","name":"slug","required":true,"schema":{"title":"Slug","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuideResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Run the publish gates; on success flip to published + rebuild.","tags":["Marketing"]}},"/api/v1/marketing/admin/guides/{slug}/unpublish":{"post":{"operationId":"marketing_content_api_api_admin_unpublish_guide_admin_guides__slug__unpublish_post","parameters":[{"in":"path","name":"slug","required":true,"schema":{"title":"Slug","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuideResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Flip a guide back to draft (removes it on the next rebuild).","tags":["Marketing"]}},"/api/v1/marketing/admin/rebuild":{"post":{"operationId":"marketing_content_api_api_admin_rebuild_admin_rebuild_post","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RebuildResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal Server Error"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Start a content rebuild immediately, superseding any debounce.","tags":["Marketing"]}},"/api/v1/marketing/guides":{"get":{"description":"<br/>With include_drafts=1 the response gains a second `drafts` array:<br/>each draft's full payload PLUS its previewToken. Design note: draft<br/>bodies become publicly fetchable through this param BY DESIGN. The<br/>pages they feed are public-at-unguessable-URL noindexed previews<br/>(Lior approved 2026-07-04); nothing enumerable links them, so a draft<br/>is only reachable by someone already holding its unguessable token.<br/>Drafts are never mixed into the published `guides` array.","operationId":"marketing_content_api_api_list_public_guides_guides_get","parameters":[{"in":"query","name":"include_drafts","required":false,"schema":{"default":0,"title":"Include Drafts","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuidePublicListResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"All published guides with full body (the build payload).","tags":["Marketing"]}},"/api/v1/marketing/guides/{slug}":{"get":{"operationId":"marketing_content_api_api_get_public_guide_guides__slug__get","parameters":[{"in":"path","name":"slug","required":true,"schema":{"title":"Slug","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuidePublicItem"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"One published guide (debugging / preview convenience).","tags":["Marketing"]}},"/api/v1/model-votes":{"get":{"description":"<br/>Sorted by votes descending, ties broken by ROSTER order (stable). New<br/>feature, so zero-vote models are expected and returned as votes=0.<br/><br/>An optional `?capability=` query (`video` | `image`) scopes the list to<br/>that generation kind; omitting it returns the full roster.","operationId":"model_votes_api_list_models_get","parameters":[{"in":"query","name":"capability","required":false,"schema":{"default":"","title":"Capability","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelListResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Every ROSTER model with its vote count and the caller's voted flag.","tags":["Model Votes"]}},"/api/v1/model-votes/suggest":{"post":{"operationId":"model_votes_api_suggest_model_suggest_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuggestRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Record a free-text model suggestion for the caller (1 to 120 chars).","tags":["Model Votes"]}},"/api/v1/model-votes/{key}/toggle":{"post":{"operationId":"model_votes_api_toggle_vote__key__toggle_post","parameters":[{"in":"path","name":"key","required":true,"schema":{"title":"Key","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToggleResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Toggle the caller's vote for a ROSTER model. 404 if the key is unknown.","tags":["Model Votes"]}},"/api/v1/notifications/recent":{"get":{"description":"sidebar Notifications panel (B62).","operationId":"notifications_api_api_recent_notifications_recent_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecentNotificationsResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Recent notifications (newest first) + unseen count, for the","tags":["Notifications"]}},"/api/v1/notifications/seen":{"post":{"operationId":"notifications_api_api_mark_seen_seen_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkSeenRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkSeenResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Mark displayed notifications seen (idempotent, owner-scoped).","tags":["Notifications"]}},"/api/v1/notifications/unseen":{"get":{"operationId":"notifications_api_api_unseen_notifications_unseen_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnseenNotificationsResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The caller's unseen notifications, oldest first (toast stack order).","tags":["Notifications"]}},"/api/v1/onboarding":{"get":{"operationId":"onboarding_api_api_get_onboarding_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingStatusResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Return the current user's onboarding state.","tags":["Onboarding"]},"post":{"operationId":"onboarding_api_api_save_onboarding_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingSaveRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingStatusResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Persist the funnel answers and mark the current user onboarded.","tags":["Onboarding"]}},"/api/v1/onboarding/reset":{"post":{"description":"<br/>Admin-only. Resets the current admin's OWN account (scoped strictly to<br/>`current_user()`, there is no target-id param, so there is no<br/>cross-user reset path). Two things happen:<br/><br/>1. The funnel row is cleared so `whoami` reports not-onboarded and the<br/>   gate re-runs the two intake questions.<br/>2. The Getting Started baselines are re-captured at the CURRENT asset<br/>   counts, so the home-page checklist reads 0/3, and the system behaves<br/>   as if the admin has zero avatars without deleting anything.<br/><br/>Non-admins get 403; anonymous callers get 401.","operationId":"onboarding_api_api_reset_onboarding_reset_post","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingStatusResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Reset the caller back to the FULL new-user onboarding experience.","tags":["Onboarding"]}},"/api/v1/onboarding/setup":{"get":{"operationId":"onboarding_api_api_get_setup_setup_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupStatusResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Return the caller's Getting Started checklist state.","tags":["Onboarding"]}},"/api/v1/onboarding/setup/complete":{"post":{"operationId":"onboarding_api_api_complete_setup_setup_complete_post","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupStatusResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Stamp the caller's Getting Started checklist as complete.","tags":["Onboarding"]}},"/api/v1/posts":{"get":{"description":"<br/>Scoped to the caller in SQL via `scope_query`: every user, admins<br/>included, sees only their own posts (default-own scoping, spec<br/>\u00a73.5, 2026-08-11).","operationId":"posts_api_api_list_posts_get","parameters":[{"in":"query","name":"status","required":false,"schema":{"default":"","title":"Status","type":"string"}},{"in":"query","name":"avatar_id","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Avatar Id"}},{"in":"query","name":"all","required":false,"schema":{"default":0,"title":"All","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostListView"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Posts list view used by /posts.","tags":["Posts"]}},"/api/v1/posts/publish-video":{"post":{"description":"<br/>Ownership-scoped to the caller. Generates a caption when none is supplied<br/>and returns it. A missing/unrendered video 404s; a missing social account<br/>comes back as a 200 with success=False and a connect instruction.","operationId":"posts_api_publish_video_publish_video_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublishVideoRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublishVideoResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Publish a rendered video to a connected social account (video -> post).","tags":["Posts"]}},"/api/v1/posts/{post_id}/generate-caption":{"post":{"operationId":"posts_api_generate_caption__int_post_id__generate_caption_post","parameters":[{"in":"path","name":"post_id","required":true,"schema":{"title":"Post Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateCaptionResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal Server Error"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Regenerate the caption via AI for a post.","tags":["Posts"]}},"/api/v1/posts/{post_id}/publish/{platform}":{"post":{"operationId":"posts_api_publish_post__int_post_id__publish__platform__post","parameters":[{"in":"path","name":"post_id","required":true,"schema":{"title":"Post Id","type":"integer"}},{"in":"path","name":"platform","required":true,"schema":{"title":"Platform","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublishResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal Server Error"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Publish a post to Instagram or TikTok.","tags":["Posts"]}},"/api/v1/posts/{post_id}/update-caption":{"post":{"operationId":"posts_api_update_caption__int_post_id__update_caption_post","parameters":[{"in":"path","name":"post_id","required":true,"schema":{"title":"Post Id","type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCaptionRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCaptionResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Update the Instagram caption on a post.","tags":["Posts"]}},"/api/v1/prefs/favorites":{"get":{"operationId":"user_prefs_api_api_list_favorites_favorites_get","parameters":[{"in":"query","name":"kind","required":true,"schema":{"title":"Kind","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FavoritesListResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The caller's favorited ref_ids for a `kind` (for hydrating stars).","tags":["User Prefs"]},"post":{"description":"<br/>Idempotent per (user, kind, ref): favoriting an already-favorited item<br/>un-favorites it. Returns the new `favorited` state. 400 for an unknown<br/>`kind`. Emits `favorite_changed`.","operationId":"user_prefs_api_api_toggle_favorite_favorites_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToggleFavoriteRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToggleFavoriteResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Toggle the caller's favorite mark on one item (kind + ref_id).","tags":["User Prefs"]}},"/api/v1/prefs/marketing-emails":{"get":{"operationId":"lifecycle_prefs_get_marketing_emails_marketing_emails_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketingEmailsResponse"}}},"description":"OK"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"tags":["Lifecycle Email"]},"put":{"description":"<br/>Turning emails back ON is a clear of the opt-out. If the stored reason is<br/>a vendor signal (`bounce` / `complaint` / `suppression`) rather than the<br/>user's own choice, the clear is refused with a 422: that address is<br/>known-bad and only support can re-enable it. A user-set opt-out (or any<br/>other reason) can always be cleared.","operationId":"lifecycle_prefs_put_marketing_emails_marketing_emails_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketingEmailsRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketingEmailsResponse"}}},"description":"OK"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Acts on current_user() only; takes no user id, so no resource-access decorator applies.","tags":["Lifecycle Email"]}},"/api/v1/prefs/views/{page_key}":{"get":{"operationId":"user_prefs_api_api_get_view_prefs_views__page_key__get","parameters":[{"in":"path","name":"page_key","required":true,"schema":{"title":"Page Key","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ViewPrefsResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The caller's saved default filters for a page, or null if none.","tags":["User Prefs"]},"put":{"description":"<br/>400 for an unknown page, a non-object blob, or one over the size cap.","operationId":"user_prefs_api_api_save_view_prefs_views__page_key__put","parameters":[{"in":"path","name":"page_key","required":true,"schema":{"title":"Page Key","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveViewPrefsRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveViewPrefsResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Save the caller's default filters for a page (opaque validated blob).","tags":["User Prefs"]}},"/api/v1/preview/avatar-templates":{"get":{"operationId":"preview_api_avatar_templates_list_avatar_templates_get","parameters":[{"in":"query","name":"niche","required":false,"schema":{"default":"","title":"Niche","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AvatarTemplatesResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"List all avatar templates, optionally filtered by niche.","tags":["Preview"]}},"/api/v1/preview/create/submit":{"post":{"operationId":"preview_api_create_submit_create_submit_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSubmitRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSubmitResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Queue a preview video creation run.","tags":["Preview"]}},"/api/v1/qa/check/{video_id}":{"post":{"operationId":"qa_api_api_qa_check_check__int_video_id__post","parameters":[{"in":"path","name":"video_id","required":true,"schema":{"title":"Video Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QaCheckResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Run Instagram QA analysis on a finished video.","tags":["QA"]}},"/api/v1/qa/history":{"get":{"description":"<br/>Regular users are scoped by the post-fetch owner filter below (this<br/>route does NOT go through `scope_query`). Admins currently still see<br/>every run: QA runs are an ops/diagnostics surface, a deliberate<br/>carve-out from the default-own scoping flip (spec \u00a73.5, 2026-08-11).","operationId":"qa_api_api_qa_history_history_get","parameters":[{"in":"query","name":"limit","required":false,"schema":{"default":20,"title":"Limit","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QaHistoryResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Recent QA history as JSON (default limit=20, max 200).","tags":["QA"]}},"/api/v1/qa/run":{"post":{"operationId":"qa_api_api_run_qa_run_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriggerSourceRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QaRunStartResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Trigger a QA run asynchronously. Returns immediately.","tags":["QA"]}},"/api/v1/qa/run-sync":{"post":{"operationId":"qa_api_api_run_qa_sync_run_sync_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriggerSourceRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QaRunSyncResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Trigger a QA run synchronously and return the full result.","tags":["QA"]}},"/api/v1/qa/runs/{run_id}":{"get":{"operationId":"qa_api_api_qa_run_detail_runs__int_run_id__get","parameters":[{"in":"path","name":"run_id","required":true,"schema":{"title":"Run Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QaRunDetailResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Return detail for a specific QA run.","tags":["QA"]}},"/api/v1/scripts":{"get":{"description":"<br/>Scoped to the caller's own scripts, admins included (default-own<br/>scoping, spec \u00a73.5, 2026-08-11). Filtering happens in SQL via<br/>`scope_query` inside the repository, with no post-fetch list<br/>comprehension.","operationId":"scripts_api_api_list_scripts_get","parameters":[{"in":"query","name":"status","required":false,"schema":{"default":"","title":"Status","type":"string"}},{"in":"query","name":"avatar_id","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Avatar Id"}},{"in":"query","name":"source","required":false,"schema":{"default":"","title":"Source","type":"string"}},{"in":"query","name":"account","required":false,"schema":{"default":"","title":"Account","type":"string"}},{"in":"query","name":"category_id","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Category Id"}},{"in":"query","name":"q","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Q"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScriptListView"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Scripts list view used by /scripts and the campaign wizard.","tags":["Scripts"]}},"/api/v1/scripts/generate":{"post":{"description":"<br/>Note: this creates a new script owned by the calling user. The<br/>`avatar_id` in the body must belong to the caller (or caller is<br/>admin); enforcement of this body-side check is a follow-up \u2014 the<br/>decorator currently only verifies the caller is logged in.","operationId":"scripts_api_script_generate_generate_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateScriptBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal Server Error"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Generate a new script for an avatar.","tags":["Scripts"]}},"/api/v1/scripts/{script_id}":{"get":{"operationId":"scripts_api_api_get_script__int_script_id__get","parameters":[{"in":"path","name":"script_id","required":true,"schema":{"title":"Script Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScriptDetailResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Script form data for the edit page.","tags":["Scripts"]}},"/api/v1/scripts/{script_id}/auto-delivery-notes":{"post":{"operationId":"scripts_api_script_auto_delivery_notes__int_script_id__auto_delivery_notes_post","parameters":[{"in":"path","name":"script_id","required":true,"schema":{"title":"Script Id","type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutoDeliveryNotesBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal Server Error"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Generate delivery notes for a script.","tags":["Scripts"]}},"/api/v1/scripts/{script_id}/polish":{"post":{"operationId":"scripts_api_script_polish__int_script_id__polish_post","parameters":[{"in":"path","name":"script_id","required":true,"schema":{"title":"Script Id","type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolishBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal Server Error"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Polish a script with a given style.","tags":["Scripts"]}},"/api/v1/scripts/{script_id}/rewrite":{"post":{"operationId":"scripts_api_script_rewrite__int_script_id__rewrite_post","parameters":[{"in":"path","name":"script_id","required":true,"schema":{"title":"Script Id","type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RewriteScriptBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal Server Error"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Rewrite an existing script.","tags":["Scripts"]}},"/api/v1/settings":{"get":{"description":"<br/>Identity comes from `current_user()` (the auth gate's resolved user,<br/>which is the TARGET while impersonating), never from the Flask<br/>session: the session read ignored Bearer-JWT callers and leaked the<br/>ADMIN's settings into an impersonated view (spec \u00a73.7, 2026-08-11).","operationId":"settings_api_api_settings_view_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsViewResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Settings page payload (used by /settings).","tags":["Settings"]}},"/api/v1/stock/search":{"get":{"operationId":"stock_media_api_api_stock_search_search_get","parameters":[{"in":"query","name":"type","required":true,"schema":{"enum":["music","footage"],"title":"Type","type":"string"}},{"in":"query","name":"q","required":true,"schema":{"maxLength":200,"minLength":1,"title":"Q","type":"string"}},{"in":"query","name":"page","required":false,"schema":{"default":1,"maximum":100,"minimum":1.0,"title":"Page","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StockSearchResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Proxied provider search; previews are free and unlicensed.","tags":["Stock Media"]}},"/api/v1/support/business-lead":{"post":{"description":"<br/>Same guard order as `/contact`: the free honeypot first (answered with<br/>the same 200 and reference shape as a real send), then the per-ip limit<br/>in its own bucket, then the human check and the mail.","operationId":"support_api_api_support_business_lead_business_lead_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessLeadRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessLeadResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Send one business lead to Partnerships and record `business_lead_created`.","tags":["Support"]}},"/api/v1/support/contact":{"post":{"description":"<br/>Answers 200 with the reference the customer keeps. A honeypot hit gets the<br/>same 200 and the same shape of reference with nothing sent, because a bot<br/>that could tell the two apart would drop the field on the next pass.","operationId":"support_api_api_support_contact_contact_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactResponse"}}},"description":"OK"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Request Entity Too Large"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Send one contact-form submission to the support inbox.","tags":["Support"]}},"/api/v1/support/screenshot":{"post":{"description":"<br/>Multipart, because the app already has the File in hand and base64 in a<br/>JSON body would cost a third more bytes on a phone. The key is namespaced<br/>by user id, which is what lets `POST /contact` prove the object belongs to<br/>the caller before it mails it out.","operationId":"support_api_api_support_screenshot_screenshot_post","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScreenshotResponse"}}},"description":"OK"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Request Entity Too Large"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Store one screenshot for the in-app form and answer its key.","tags":["Support"]}},"/api/v1/template-jobs/{draft_id}":{"get":{"operationId":"template_jobs_api_api_read_job__int_draft_id__get","parameters":[{"in":"path","name":"draft_id","required":true,"schema":{"title":"Draft Id","type":"integer"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The job as authored so far, re-validated (issues field-keyed).","tags":["Video Templates"]},"patch":{"description":"the template's validate: refusals come back field-keyed, never<br/>restated by this layer.","operationId":"template_jobs_api_api_patch_job__int_draft_id__patch","parameters":[{"in":"path","name":"draft_id","required":true,"schema":{"title":"Draft Id","type":"integer"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Merge authored fields into the job (a null deletes a key) and run","tags":["Video Templates"]}},"/api/v1/template-jobs/{draft_id}/broll/suggest":{"post":{"description":"(Lior, 2026-09-02). Free: suggestions spend nothing.","operationId":"template_jobs_api_api_suggest_broll__int_draft_id__broll_suggest_post","parameters":[{"in":"path","name":"draft_id","required":true,"schema":{"title":"Draft Id","type":"integer"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Per-chapter stock query + AI prompt, derived from script + avatar","tags":["Video Templates"]}},"/api/v1/template-jobs/{draft_id}/quote":{"get":{"description":"rate, source seconds, the rate, and the edited script's sentence fit).","operationId":"template_jobs_api_api_quote_job__int_draft_id__quote_get","parameters":[{"in":"path","name":"draft_id","required":true,"schema":{"title":"Draft Id","type":"integer"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The template's price for the job as authored (copy_auto: credits at the copy","tags":["Video Templates"]}},"/api/v1/template-jobs/{draft_id}/render":{"post":{"description":"the job onto a pending Video -> queue the lifecycle; returns 202 with<br/>the video id and redirect. Nothing spends on a refusal. The template's<br/>plan floor is checked first (403 naming the floor): the paywall sits at<br/>Generate, so this is where a plan below the floor meets it.<br/><br/>Trial gate (2026-09-30): this is the SECOND render entry point (the<br/>Studio's Animate, the split window's, the copy flow's), so it carries<br/>the same `require_paid_creation` as the UGC finalize. Until the wall<br/>moved to the last click only the SPA kept a trialing user away from<br/>here; the product rule now lives on the route, where a hand-made<br/>request meets it too.","operationId":"template_jobs_api_api_render_job__int_draft_id__render_post","parameters":[{"in":"path","name":"draft_id","required":true,"schema":{"title":"Draft Id","type":"integer"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Validate (free) -> reserve the estimate (402 when short) -> snapshot","tags":["Video Templates"]}},"/api/v1/template-jobs/{draft_id}/script/fix":{"post":{"operationId":"template_jobs_api_api_fix_script__int_draft_id__script_fix_post","parameters":[{"in":"path","name":"draft_id","required":true,"schema":{"title":"Draft Id","type":"integer"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"A single targeted rewrite against one named violation.","tags":["Video Templates"]}},"/api/v1/template-jobs/{draft_id}/script/generate":{"post":{"description":"feedback loop; unconverged returns 422 with the surviving refusals<br/>(the last attempt is persisted either way, so the editor can hand-fix).","operationId":"template_jobs_api_api_generate_script__int_draft_id__script_generate_post","parameters":[{"in":"path","name":"draft_id","required":true,"schema":{"title":"Draft Id","type":"integer"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Write the script under the template's rules with the violation","tags":["Video Templates"]}},"/api/v1/template-jobs/{draft_id}/studio/chat":{"post":{"description":"podcast's \"Generate New Studio\" drawer). Decides only: generate, refine<br/>or ask. It never renders, so a turn costs no image credits.<br/>Body: {message, history?: [{role, text}], has_image?: bool}.","operationId":"template_jobs_api_api_studio_chat__int_draft_id__studio_chat_post","parameters":[{"in":"path","name":"draft_id","required":true,"schema":{"title":"Draft Id","type":"integer"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"One turn of the studio's room director (the Image Studio in the","tags":["Video Templates"]}},"/api/v1/template-jobs/{draft_id}/studio/generate":{"post":{"description":"a scene image), store it, and record it on the job.","operationId":"template_jobs_api_api_generate_studio__int_draft_id__studio_generate_post","parameters":[{"in":"path","name":"draft_id","required":true,"schema":{"title":"Draft Id","type":"integer"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Render one studio plate preview from the description (metered like","tags":["Video Templates"]}},"/api/v1/template-jobs/{draft_id}/studio/options":{"get":{"description":"their scene libraries, and the shipped preset studios.","operationId":"template_jobs_api_api_studio_options__int_draft_id__studio_options_get","parameters":[{"in":"path","name":"draft_id","required":true,"schema":{"title":"Draft Id","type":"integer"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The Studio step's pick lists: this cast's prior episode plates,","tags":["Video Templates"]}},"/api/v1/template-jobs/{draft_id}/studio/seat":{"post":{"description":"own plates discipline; the render adopts the approved pair (no double<br/>spend). Body: {reseat?: \"host\"|\"guest\"} regenerates one side.","operationId":"template_jobs_api_api_seat_cast__int_draft_id__studio_seat_post","parameters":[{"in":"path","name":"draft_id","required":true,"schema":{"title":"Draft Id","type":"integer"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Generate the seated pair in the chosen studio through the engine's","tags":["Video Templates"]}},"/api/v1/template-videos/{video_id}/segments/{index}/rerun":{"post":{"description":"segment price (that model's copy rate times the part's seconds). The new clip lands as<br/>a candidate take, so the video keeps playing what it ships. 409 while a fix is running<br/>or a take is waiting; 422 for a model outside the copy tiers.","operationId":"template_videos_api_api_rerun_segment__int_video_id__segments__int_index__rerun_post","parameters":[{"in":"path","name":"video_id","required":true,"schema":{"title":"Video Id","type":"integer"}},{"in":"path","name":"index","required":true,"schema":{"title":"Index","type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_SegmentRerunBody"}}},"required":true},"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Copy Video v2: render one part again on the chosen model with the user's note, at","tags":["Video Templates"]}},"/api/v1/template-videos/{video_id}/segments/{index}/resolve":{"post":{"description":"clip and queues the rebuild of the video around it; `keep=\"old\"` leaves the video as<br/>it plays. Nothing is refunded either way. 409 when no take is waiting.","operationId":"template_videos_api_api_resolve_segment__int_video_id__segments__int_index__resolve_post","parameters":[{"in":"path","name":"video_id","required":true,"schema":{"title":"Video Id","type":"integer"}},{"in":"path","name":"index","required":true,"schema":{"title":"Index","type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_SegmentResolveBody"}}},"required":true},"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Keep or discard the take waiting on a fixed part. `keep=\"new\"` makes it the part's","tags":["Video Templates"]}},"/api/v1/template-videos/{video_id}/status":{"get":{"operationId":"template_videos_api_api_template_video_status__int_video_id__status_get","parameters":[{"in":"path","name":"video_id","required":true,"schema":{"title":"Video Id","type":"integer"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The video row + the step ledger (what ran, cost kind, refusals).","tags":["Video Templates"]}},"/api/v1/video-templates":{"get":{"description":"caller's server-computed eligibility.","operationId":"video_templates_api_api_list_templates_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The gallery catalog: serialized manifests + price band + the","tags":["Video Templates"]}},"/api/v1/video-templates/co-hosts":{"get":{"operationId":"video_templates_api_api_list_cohosts_co_hosts_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The AvatarFactory house co-hosts (castable as guest, any plan).","tags":["Video Templates"]}},"/api/v1/video-templates/{template_id}/jobs":{"post":{"description":"roles). Any plan opens one; the plan floor is enforced at the render.","operationId":"video_templates_api_api_create_job__template_id__jobs_post","parameters":[{"in":"path","name":"template_id","required":true,"schema":{"title":"Template Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Open a template job draft (casting seeded from the manifest's","tags":["Video Templates"]}},"/api/v1/videos/caption-styles":{"get":{"description":"<br/>Declared BEFORE the `/<int:video_id>` routes so \"caption-styles\" is<br/>never read as a video id. Not user-scoped: the catalog is the same for<br/>everyone, so there is no row here to own and nothing to scope, but it<br/>is still a signed-in surface: anonymous calls get a 401<br/>(test_auth_gate_parametric, test_captions_template_gate).","operationId":"videos_api_api_caption_style_catalog_caption_styles_get","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaptionStyleCatalogResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The caption presets the picker offers, and where each one lands.","tags":["Videos"]}},"/api/v1/videos/gallery":{"get":{"description":"<br/>Scoped to the caller's own videos, admins included (default-own<br/>scoping, spec \u00a73.5, 2026-08-11). Owner, avatar, and search filtering,<br/>the seven chip counts, and the page slice all happen in SQL<br/>(repository.list_gallery), so a request costs O(page), not O(the<br/>caller's videos). The counts and `total` still describe the full<br/>filtered set; `has_more` tells the client whether to fetch the next<br/>page, and a page past the end echoes the requested page number.<br/><br/>Backwards compat: when the legacy `limit` is set (1 to 100, same<br/>bounds as `page_size`), it means page 1 of size `limit`.","operationId":"videos_api_api_video_gallery_gallery_get","parameters":[{"in":"query","name":"avatar_id","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Avatar Id"}},{"in":"query","name":"q","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Q"}},{"in":"query","name":"limit","required":false,"schema":{"anyOf":[{"maximum":100,"minimum":1.0,"type":"integer"},{"type":"null"}],"default":null,"title":"Limit"}},{"in":"query","name":"page","required":false,"schema":{"default":1,"minimum":1.0,"title":"Page","type":"integer"}},{"in":"query","name":"page_size","required":false,"schema":{"default":24,"maximum":100,"minimum":1.0,"title":"Page Size","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VideoGalleryResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Video gallery used by /videos.","tags":["Videos"]}},"/api/v1/videos/{video_id}":{"delete":{"description":"<br/>Storage cleanup of the underlying mp4 is intentionally NOT done<br/>here \u00b7 the storage GC sweeps stranded files separately so the<br/>user-facing delete is fast and never blocks on S3. The Posts row<br/>survives (with `video_id=NULL`) so audit history is preserved.","operationId":"videos_api_api_video_delete__int_video_id__delete","parameters":[{"in":"path","name":"video_id","required":true,"schema":{"title":"Video Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteVideoResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Delete the video row and nullify dependent FKs.","tags":["Videos"]},"get":{"operationId":"videos_api_api_video_detail__int_video_id__get","parameters":[{"in":"path","name":"video_id","required":true,"schema":{"title":"Video Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VideoDetailResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Full video bundle for the detail / qa pages.","tags":["Videos"]}},"/api/v1/videos/{video_id}/caption":{"post":{"operationId":"videos_api_api_video_save_caption__int_video_id__caption_post","parameters":[{"in":"path","name":"video_id","required":true,"schema":{"title":"Video Id","type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveCaptionRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveCaptionResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Persist a user-edited Instagram caption.","tags":["Videos"]}},"/api/v1/videos/{video_id}/captions":{"get":{"description":"list for videos rendered before capture shipped).","operationId":"videos_api_api_video_captions__int_video_id__captions_get","parameters":[{"in":"path","name":"video_id","required":true,"schema":{"title":"Video Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VideoCaptionsResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Burn-time word timings for the editor's seeded subtitles (empty","tags":["Videos"]}},"/api/v1/videos/{video_id}/captions/rebuild":{"post":{"description":"path for \"Download with captions\" when no honest subtitled cut exists).<br/><br/>Async on celery: status flips to `burning_captions`, then the fresh<br/>subtitled cut + `captions_ready=true` arrive via the detail poll.<br/>409 while a burn is running, mid-render, or while `needs_rebuild` is<br/>set (rebuild burns its own captions).","operationId":"videos_api_api_video_captions_rebuild__int_video_id__captions_rebuild_post","parameters":[{"in":"path","name":"video_id","required":true,"schema":{"title":"Video Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RebuildVideoResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Re-burn Instagram-style captions from the clean Full Cut (repair","tags":["Videos"]}},"/api/v1/videos/{video_id}/downloaded":{"post":{"description":"<br/>The file itself is fetched straight from the CDN by the browser, so the<br/>server never sees the transfer: this beacon is the only seam where \"the<br/>customer took the finished video away\" becomes a fact we can cite in a<br/>dispute. Ownership is enforced like every other video route, so nobody can<br/>stamp a download onto somebody else's trail.<br/><br/>It is also where ``video_downloaded`` fires, attributed to the CALLER (an<br/>admin reaching another tenant's video is who downloaded it). Full rationale:<br/>``docs/ANALYTICS_EVENTS.md``.","operationId":"videos_api_api_video_downloaded__int_video_id__downloaded_post","parameters":[{"in":"path","name":"video_id","required":true,"schema":{"title":"Video Id","type":"integer"}}],"responses":{"204":{"description":"No Content"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Record that the owner downloaded this video, for the chargeback trail.","tags":["Videos"]}},"/api/v1/videos/{video_id}/edit":{"delete":{"operationId":"video_edits_api_api_delete_edit_draft__int_video_id__edit_delete","parameters":[{"description":"Video id","in":"path","name":"video_id","required":true,"schema":{"description":"Video id","title":"Video Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EditDraftDeleteResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Discard the video's draft (idempotent).","tags":["Video Edits"]},"get":{"description":"then seeds the timeline from the video detail payload).","operationId":"video_edits_api_api_get_edit_draft__int_video_id__edit_get","parameters":[{"description":"Video id","in":"path","name":"video_id","required":true,"schema":{"description":"Video id","title":"Video Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EditDraftResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The video's editor draft; 404 when none exists yet (the client","tags":["Video Edits"]},"put":{"description":"`base_updated_at` is refused with 409 so a second tab cannot<br/>silently clobber newer work.","operationId":"video_edits_api_api_put_edit_draft__int_video_id__edit_put","parameters":[{"description":"Video id","in":"path","name":"video_id","required":true,"schema":{"description":"Video id","title":"Video Id","type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EditDraftPutRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EditDraftResponse"}}},"description":"OK"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Upsert the video's draft (debounced autosave). A stale","tags":["Video Edits"]}},"/api/v1/videos/{video_id}/edit/export":{"post":{"description":"`poster` JPEG, optional `duration_seconds` form field) as the<br/>video's newest edited cut.","operationId":"video_edits_api_api_export_edit__int_video_id__edit_export_post","parameters":[{"description":"Video id","in":"path","name":"video_id","required":true,"schema":{"description":"Video id","title":"Video Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Persist the browser-exported MP4 (multipart `file`, optional","tags":["Video Edits"]}},"/api/v1/videos/{video_id}/edit/license-assets":{"post":{"operationId":"stock_media_edit_api_api_start_license_job__int_video_id__edit_license_assets_post","parameters":[{"description":"Video id","in":"path","name":"video_id","required":true,"schema":{"description":"Video id","title":"Video Id","type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LicenseAssetsRequest"}}},"required":true},"responses":{"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LicenseJobStartResponse"}}},"description":"Accepted"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Start the pre-export licensing job for this video's stock refs.","tags":["Stock Media"]}},"/api/v1/videos/{video_id}/edit/license-assets/{job_id}":{"get":{"operationId":"stock_media_edit_api_api_license_job_status__int_video_id__edit_license_assets__job_id__get","parameters":[{"in":"path","name":"video_id","required":true,"schema":{"title":"Video Id","type":"integer"}},{"in":"path","name":"job_id","required":true,"schema":{"title":"Job Id","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LicenseJobStatusResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Per-asset progress of a licensing job (client polls during export).","tags":["Stock Media"]}},"/api/v1/videos/{video_id}/generate-caption":{"post":{"description":"avatar's voice, and persist it to `Video.ig_caption`.","operationId":"videos_api_api_video_generate_caption__int_video_id__generate_caption_post","parameters":[{"in":"path","name":"video_id","required":true,"schema":{"title":"Video Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateCaptionResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Write an Instagram caption for the video from its script, in the","tags":["Videos"]}},"/api/v1/videos/{video_id}/generate-thumbnail":{"post":{"description":"persist it as the video's thumbnail.","operationId":"videos_api_api_video_generate_thumbnail__int_video_id__generate_thumbnail_post","parameters":[{"in":"path","name":"video_id","required":true,"schema":{"title":"Video Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateThumbnailResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Use the video's opening frame as its cover image (free, no AI) and","tags":["Videos"]}},"/api/v1/videos/{video_id}/qa-report":{"get":{"operationId":"videos_api_api_video_qa_report__int_video_id__qa_report_get","parameters":[{"in":"path","name":"video_id","required":true,"schema":{"title":"Video Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QaReportResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Cached or fresh QA report for a video.","tags":["Videos"]}},"/api/v1/videos/{video_id}/rating":{"get":{"operationId":"videos_api_api_video_rating__int_video_id__rating_get","parameters":[{"in":"path","name":"video_id","required":true,"schema":{"title":"Video Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VideoRatingResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"The caller's rating of this video, or null when they have not rated it.","tags":["Videos"]},"put":{"operationId":"videos_api_api_video_rate__int_video_id__rating_put","parameters":[{"in":"path","name":"video_id","required":true,"schema":{"title":"Video Id","type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateVideoRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VideoRatingResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Save a 1 to 5 star click. Fires `video_rating_created` on every click.","tags":["Videos"]}},"/api/v1/videos/{video_id}/rating/feedback":{"post":{"operationId":"videos_api_api_video_rating_feedback__int_video_id__rating_feedback_post","parameters":[{"in":"path","name":"video_id","required":true,"schema":{"title":"Video Id","type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VideoFeedbackRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VideoRatingResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Send or skip the reason picker. Fires `video_feedback_created`.","tags":["Videos"]}},"/api/v1/videos/{video_id}/rebuild":{"post":{"description":"captions into a fresh Subtitled cut (Shot Quality Feedback Loop).<br/><br/>Repoints `final_video_file`, refreshes the two cut assets, and clears<br/>`needs_rebuild`. Async: the new file arrives via the status/detail poll.<br/>409 if a re-roll is still running.","operationId":"videos_api_api_video_rebuild__int_video_id__rebuild_post","parameters":[{"in":"path","name":"video_id","required":true,"schema":{"title":"Video Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RebuildVideoResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Re-stitch the current per-shot clips into a fresh Full Cut and re-burn","tags":["Videos"]}},"/api/v1/videos/{video_id}/regenerate":{"post":{"description":"<br/>Reuses the same `Video.id` (URLs, share links, analytics all keep<br/>pointing at the same conceptual video). The \"make me a similar but<br/>different video\" flow is handled client-side by opening the wizard<br/>with a `?from=<id>` prefill param \u00b7 no backend mutation needed for<br/>that path.","operationId":"videos_api_api_video_regenerate__int_video_id__regenerate_post","parameters":[{"in":"path","name":"video_id","required":true,"schema":{"title":"Video Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegenerateVideoResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Re-render the existing video with the same inputs.","tags":["Videos"]}},"/api/v1/videos/{video_id}/shot/{shot_index}/reroll":{"post":{"description":"Feedback Loop, Loop A).<br/><br/>Validates the artifact tags against the fixed taxonomy and the optional<br/>`edits` (transcript, cinematic action prompt, scene swap; the scene id<br/>arrives in the body, so ownership is checked in the service), reserves<br/>the credit cost upfront (402 before any vendor call), and renders the<br/>shot into a CANDIDATE take next to the current one. Emits<br/>`shot_reroll_started`. Async: the candidate arrives via the status/detail<br/>poll; the user then keeps or discards it via the resolve endpoint.","operationId":"videos_api_api_video_shot_reroll__int_video_id__shot__int_shot_index__reroll_post","parameters":[{"in":"path","name":"video_id","required":true,"schema":{"title":"Video Id","type":"integer"}},{"in":"path","name":"shot_index","required":true,"schema":{"title":"Shot Index","type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RerollShotRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RerollShotResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Payment Required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Regenerate ONE shot, optionally with input edits (Shot Quality","tags":["Videos"]}},"/api/v1/videos/{video_id}/shot/{shot_index}/resolve":{"post":{"description":"<br/>`keep=\"new\"` promotes the candidate (repoints the shot's scene asset and<br/>marks the final cut stale for the rebuild); `keep=\"old\"` discards it and<br/>deletes the orphaned clip. Emits `shot_take_changed`.","operationId":"videos_api_api_video_shot_resolve__int_video_id__shot__int_shot_index__resolve_post","parameters":[{"in":"path","name":"video_id","required":true,"schema":{"title":"Video Id","type":"integer"}},{"in":"path","name":"shot_index","required":true,"schema":{"title":"Shot Index","type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResolveShotTakeRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResolveShotTakeResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Keep or discard the waiting candidate take of one shot.","tags":["Videos"]}},"/api/v1/videos/{video_id}/status":{"get":{"description":"video library's rendering-card poll (progress + label + ETA).","operationId":"videos_api_api_video_status_summary__int_video_id__status_get","parameters":[{"in":"path","name":"video_id","required":true,"schema":{"title":"Video Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VideoStatusResponse"}}},"description":"OK"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Lightweight status read used by /generate/<id>/status and the","tags":["Videos"]}},"/api/v1/videos/{video_id}/subtitle-status":{"get":{"operationId":"videos_api_video_subtitle_status__int_video_id__subtitle_status_get","parameters":[{"in":"path","name":"video_id","required":true,"schema":{"title":"Video Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubtitleStatusResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Poll captioning job status.","tags":["Videos"]}},"/api/v1/videos/{video_id}/subtitles":{"post":{"operationId":"videos_api_video_add_subtitles__int_video_id__subtitles_post","parameters":[{"in":"path","name":"video_id","required":true,"schema":{"title":"Video Id","type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddSubtitlesRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddSubtitlesResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Start subtitle burn for a completed video.","tags":["Videos"]}},"/api/v1/videos/{video_id}/subtitles/revert":{"post":{"operationId":"videos_api_video_revert_subtitles__int_video_id__subtitles_revert_post","parameters":[{"in":"path","name":"video_id","required":true,"schema":{"title":"Video Id","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevertSubtitlesResponse"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"session_auth":[]},{"bearer_jwt":[]}],"summary":"Revert a captioned video to its original.","tags":["Videos"]}},"/email/unsubscribe":{"post":{"operationId":"lifecycle_email_api_one_click_unsubscribe_unsubscribe_post","parameters":[{"in":"query","name":"token","required":false,"schema":{"default":"","title":"Token","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookAck"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"RFC 8058 one-click target. Idempotent. No auth: the signed token is the auth.","tags":["Lifecycle Email"]}},"/telegram/setup":{"post":{"operationId":"telegram_api_telegram_setup_telegram_setup_post","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TelegramSendResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal Server Error"}},"summary":"Set up the Telegram webhook. Call this once after deployment.","tags":["Telegram"]}},"/telegram/webhook":{"post":{"operationId":"telegram_api_telegram_webhook_telegram_webhook_post","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TelegramOkResponse"}}},"description":"OK"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Receive Telegram webhook updates and dispatch them to the agent.","tags":["Telegram"]}},"/webhooks/heygen":{"post":{"description":"<br/>Called by HeyGen after avatar video rendering finishes or fails.<br/>The request body is verified with HMAC-SHA256 before dispatch.","operationId":"webhooks_api_heygen_webhook_heygen_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEventRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookResponse"}}},"description":"OK"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal Server Error"}},"summary":"HeyGen video-completion webhook.","tags":["Webhooks"]}},"/webhooks/resend":{"post":{"operationId":"lifecycle_webhook_resend_webhook_resend_post","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookAck"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Inbound Resend webhook. Verified by signature, deduped by svix-id.","tags":["Lifecycle Email"]}},"/webhooks/stripe":{"post":{"operationId":"billing_webhook_stripe_webhook_stripe_post","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookAck"}}},"description":"OK"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Inbound Stripe webhook. Verified by signature, deduped by event id.","tags":["Billing"]}}},"tags":[{"description":"Per-user activity feed","name":"Activity"},{"description":"Instagram reel tracking and account analytics","name":"Analytics"},{"description":"SPA auth endpoints (Cognito-backed)","name":"Auth"},{"description":"Account settings (email, password, identities)","name":"Account"},{"description":"Admin support tooling (impersonation)","name":"Admin"},{"description":"Avatar pipeline triggering and run status tracking","name":"Automation"},{"description":"Avatar list, detail, categories and metadata read endpoints","name":"Avatars"},{"description":"System health checks, environment validation and admin utilities","name":"Diagnostics"},{"description":"Instagram account tracking, scanning, categories and tags","name":"Followed Accounts"},{"description":"Maintenance sweeps over tracked accounts","name":"Followed Accounts Admin"},{"description":"Avatar concept creation, story generation and draft management","name":"Ideation"},{"description":"Per-user third-party connections","name":"Integrations"},{"description":"Video processing, subtitles and gallery management","name":"Videos"},{"description":"The template gallery and template jobs","name":"Video Templates"},{"description":"In-app video editor drafts and exported cuts","name":"Video Edits"},{"description":"Storyblocks search and export licensing","name":"Stock Media"},{"description":"The contact form, on the marketing site and in the app","name":"Support"},{"description":"Inbound webhook callbacks from HeyGen and other providers","name":"Webhooks"},{"description":"AI background image generation","name":"Backgrounds"},{"description":"Subscriptions, trial, credits, and checkout","name":"Billing"},{"description":"Programmatic marketing guides","name":"Marketing"},{"description":"Admin metrics dashboard (BigQuery)","name":"Metrics Admin"},{"description":"Resend webhook, unsubscribe, marketing preference","name":"Lifecycle Email"},{"description":"Post caption editing, AI generation and social publishing","name":"Posts"},{"description":"Avatar template browsing and video creation submission","name":"Preview"},{"description":"Video quality assurance runs, history and status checks","name":"QA"},{"description":"AI script generation, rewriting, polishing and brainstorming","name":"Scripts"},{"description":"Campaign creation, scene management and publishing workflow","name":"Campaign Studio"},{"description":"Avatar-consistent carousel generation","name":"Carousels"},{"description":"Copy extraction from URLs and file uploads","name":"Copy Ingest"},{"description":"Telegram bot webhook, setup and message sending","name":"Telegram"},{"description":"Admin log of failed AI image generations","name":"AI Failures"},{"description":"Chargeback evidence trail (admin)","name":"Evidence"},{"description":"Home dashboard summary","name":"Dashboard"},{"description":"Video generation wizard reads (drafts + bootstrap)","name":"Generate"},{"description":"Upvote coming-soon AI video models and suggest new ones","name":"Model Votes"},{"description":"Post-signup onboarding answers + completion state","name":"Onboarding"},{"description":"App-wide settings + AI model preferences","name":"Settings"},{"description":"Per-user favorites and saved page filter defaults","name":"User Prefs"},{"description":"Digital product store picks from the ads funnel","name":"Funnel Store"},{"description":"In-app toast notifications","name":"Notifications"},{"description":"The affiliate's own program view: link, referrals, payouts","name":"Affiliate"},{"description":"The affiliate queue, decisions, payout runs and marketing assets","name":"Affiliate Admin"},{"description":"Site-wide video views for admins","name":"Videos Admin"}]}
