{"openapi":"3.1.0","info":{"title":"MotionFy API","description":"Automated product ad generation system","version":"1.0.0"},"paths":{"/api/stripe/create-checkout":{"post":{"tags":["billing"],"summary":"Api Create Checkout","description":"Create a Stripe Checkout session for subscription purchase.\n\nREQUIRES AUTHENTICATION - user must be logged in.\n\nThe checkout session will:\n- Use the exact price ID provided (must be one of our valid plan IDs)\n- Prefill the customer email from the authenticated user\n- Store user_id in metadata for webhook linking\n\nReturns:\n    URL to redirect the user to Stripe Checkout","operationId":"api_create_checkout_api_stripe_create_checkout_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCheckoutRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCheckoutResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/stripe/user-credits":{"get":{"tags":["billing"],"summary":"Api Get User Credits","description":"Get current user's credit balance and plan info.\n\nREQUIRES AUTHENTICATION.\n\nADMIN OVERRIDE: Admin users see plan=\"Admin\" with unlimited credits.","operationId":"api_get_user_credits_api_stripe_user_credits_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserCreditsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/stripe/register-user":{"post":{"tags":["billing"],"summary":"Api Register User","description":"Register a user and attempt to grant free credits based on fingerprint.\n\nCRITICAL: This is the ONLY place free credits are ever granted.\n\nFREE CREDIT RULES:\n- Each real person gets EXACTLY 20 free credits, ONCE, EVER (= 2x 5s generations)\n- Person identity = fingerprint (device_id + cookie_id + IP)\n- UNIQUE constraint prevents race conditions and double grants\n- Subsequent accounts by same person get 0 credits\n- Stripe payments are completely independent\n\nCalled by frontend after successful Firebase signup/login.\n\nReturns:\n    User info with credit grant status","operationId":"api_register_user_api_stripe_register_user_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterUserRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterUserResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/stripe/webhook":{"post":{"tags":["billing"],"summary":"Api Stripe Webhook","description":"Stripe webhook endpoint.\n\nCRITICAL: This must NEVER crash. All handlers use safe attribute access.\n\nEvent priority for plan assignment:\n1. checkout.session.completed - PRIMARY (has all info, assigns plan)\n2. customer.subscription.created - BACKUP (assigns plan if not done)\n3. invoice.paid - CONFIRMATION (updates billing cycle, grants credits)\n\nAll operations are idempotent - duplicate events are ignored.\nSignature verification is required.","operationId":"api_stripe_webhook_api_stripe_webhook_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/user/{user_id}/billing":{"get":{"tags":["admin"],"summary":"Api Admin User Billing","description":"Get user billing info for admin/debugging.\n\nREQUIRES AUTHENTICATION + ADMIN role.","operationId":"api_admin_user_billing_admin_user__user_id__billing_get","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gallery/capabilities":{"get":{"tags":["gallery"],"summary":"Get User Capabilities","operationId":"get_user_capabilities_api_gallery_capabilities_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gallery":{"get":{"tags":["gallery"],"summary":"List Gallery","operationId":"list_gallery_api_gallery_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GalleryListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gallery/{project_id}":{"get":{"tags":["gallery"],"summary":"Get Project Detail","operationId":"get_project_detail_api_gallery__project_id__get","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["gallery"],"summary":"Delete Project Endpoint","operationId":"delete_project_endpoint_api_gallery__project_id__delete","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gallery/{project_id}/assets/{asset_id}":{"get":{"tags":["gallery"],"summary":"Get Asset Detail","operationId":"get_asset_detail_api_gallery__project_id__assets__asset_id__get","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"asset_id","in":"path","required":true,"schema":{"type":"string","title":"Asset Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["gallery"],"summary":"Delete Asset Endpoint","operationId":"delete_asset_endpoint_api_gallery__project_id__assets__asset_id__delete","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"asset_id","in":"path","required":true,"schema":{"type":"string","title":"Asset Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gallery/{project_id}/primary":{"post":{"tags":["gallery"],"summary":"Set Primary Asset","operationId":"set_primary_asset_api_gallery__project_id__primary_post","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetPrimaryAssetRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gallery/{project_id}/motion":{"post":{"tags":["gallery"],"summary":"Change Motion","operationId":"change_motion_api_gallery__project_id__motion_post","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeMotionRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeMotionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/":{"get":{"summary":"Landing Page","description":"Render the landing page.","operationId":"landing_page__get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/create":{"get":{"summary":"Create Page","description":"Render the create flow page.","operationId":"create_page_create_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/privacy":{"get":{"summary":"Privacy Page","description":"Render the privacy policy page.","operationId":"privacy_page_privacy_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/terms":{"get":{"summary":"Terms Page","description":"Render the terms of service page.","operationId":"terms_page_terms_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/pricing":{"get":{"summary":"Pricing Page","description":"Render the pricing page.","operationId":"pricing_page_pricing_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/billing/success":{"get":{"summary":"Billing Success Page","description":"Render the billing success page.\n\nThis page is shown after successful Stripe checkout.\nThe ?session_id query param is available for verification if needed.","operationId":"billing_success_page_billing_success_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/billing/cancel":{"get":{"summary":"Billing Cancel Page","description":"Render the billing cancel page.","operationId":"billing_cancel_page_billing_cancel_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/gallery":{"get":{"summary":"Gallery Page","description":"Render the gallery page.","operationId":"gallery_page_gallery_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/s/{brand_slug}":{"get":{"summary":"Sample Delivery Page","description":"Render a per-brand sample delivery page.\n\nContent is driven entirely by the SAMPLES dict, keyed by brand_slug.\nUnknown slugs return 404.","operationId":"sample_delivery_page_s__brand_slug__get","parameters":[{"name":"brand_slug","in":"path","required":true,"schema":{"type":"string","title":"Brand Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/reset-password":{"get":{"summary":"Reset Password Page","description":"Custom password reset page for Firebase Authentication.\n\nFirebase emails link here with URL params:\n- mode: Should be 'resetPassword'\n- oobCode: The one-time verification code","operationId":"reset_password_page_reset_password_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/admin":{"get":{"summary":"Admin Page","description":"Render the admin dashboard page.\n\nThe page itself is served to everyone, but the JavaScript\nchecks Firebase auth and redirects non-admin users.\nServer-side API endpoints verify admin status independently.","operationId":"admin_page_admin_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/admin/sample-views":{"get":{"summary":"Admin Sample Views Page","description":"Render the sample-view analytics page (which lead opened which /s/ page,\nhow often, and when).\n\nLike /admin, the HTML shell is served to everyone but contains no data;\nall data is fetched from an admin-authenticated API, so it stays private.","operationId":"admin_sample_views_page_admin_sample_views_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/api/admin/generations":{"get":{"summary":"Api Admin Generations","description":"Get all generation jobs for the admin dashboard.\n\nReturns jobs with user email, status, provider task ID, video URL, and credits.\nSorted by created_at descending (most recent first).","operationId":"api_admin_generations_api_admin_generations_get","parameters":[{"name":"filter","in":"query","required":false,"schema":{"type":"string","description":"Date filter: today, 7days, all","default":"all","title":"Filter"},"description":"Date filter: today, 7days, all"},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/stats":{"get":{"summary":"Api Admin Stats","description":"Get summary statistics for the admin dashboard.\n\nReturns:\n- Total registered users\n- Total generations (all time)\n- Generations today\n- Most active user (by generation count)","operationId":"api_admin_stats_api_admin_stats_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/sample-views":{"get":{"summary":"Api Admin Sample Views","description":"Sample-page view analytics for the admin dashboard (admin-only).\n\nReturns:\n    summary: per-lead aggregates (slug, brand_name, product, total_views,\n             unique_ips, first_viewed, last_viewed), sorted by total views.\n    recent:  the most recent individual views (timestamp, slug, ip,\n             referrer, user_agent).\n    totals:  overall totals across all tracked pages.","operationId":"api_admin_sample_views_api_admin_sample_views_get","parameters":[{"name":"filter","in":"query","required":false,"schema":{"type":"string","description":"Date filter: today, 7days, all","default":"all","title":"Filter"},"description":"Date filter: today, 7days, all"},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/test-mode/enable":{"post":{"summary":"Api Admin Test Mode Enable","description":"Enable test-as-free-user mode for the calling admin.\nResets DB record to free plan with given credits.\nAdmin dashboard access is preserved.","operationId":"api_admin_test_mode_enable_api_admin_test_mode_enable_post","parameters":[{"name":"credits","in":"query","required":false,"schema":{"type":"integer","description":"Credits to grant (default 20)","default":20,"title":"Credits"},"description":"Credits to grant (default 20)"},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/test-mode/disable":{"post":{"summary":"Api Admin Test Mode Disable","description":"Disable test mode and restore full admin privileges.","operationId":"api_admin_test_mode_disable_api_admin_test_mode_disable_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/test-mode/status":{"get":{"summary":"Api Admin Test Mode Status","description":"Check current test mode status.","operationId":"api_admin_test_mode_status_api_admin_test_mode_status_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/create/start":{"post":{"summary":"Api Create Start","description":"Start a new generation job.\n\nREQUIRES AUTHENTICATION - user must be logged in.\nREQUIRES SUFFICIENT CREDITS - enforced server-side.\n\nCredit costs:\n- 5s generation = 10 credits\n- 10s generation = 15 credits\n\nAccepts structured inputs from the frontend, validates them,\ncreates a job record, and enqueues it for processing.\n\nReturns:\n    job_id: Unique identifier for tracking\n    status: Initial status (ANALYZING)\n\nRaises:\n    402: Insufficient credits\n    401: Not authenticated","operationId":"api_create_start_api_create_start_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateJobResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/create/status/{job_id}":{"get":{"summary":"Api Create Status","description":"Get the current status of a generation job.\n\nReturns state-dependent payload:\n- ANALYZING: Basic status\n- IMAGE_GENERATING: Basic status with progress\n- IMAGE_READY: Includes hero_image_url\n- VIDEO_GENERATING: Includes hero_image_url\n- COMPLETED: Includes hero_image_url, video_url, and metadata\n- FAILED: Includes error message\n\nQuery params:\n    speed: \"fast\" for accelerated mock delays (testing only)\n\nStale job detection:\n    If a job is stuck in an intermediate state (ANALYZING, IMAGE_GENERATING,\n    IMAGE_READY, VIDEO_GENERATING) for more than 14 minutes without any\n    update, it is automatically marked as FAILED. This handles cases where\n    the worker thread/process died (server restart, OOM, deployment) and\n    the job would otherwise stay stuck forever.","operationId":"api_create_status_api_create_status__job_id__get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"speed","in":"query","required":false,"schema":{"type":"string","description":"Speed mode for testing: fast, normal","default":"normal","title":"Speed"},"description":"Speed mode for testing: fast, normal"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/create/cancel/{job_id}":{"post":{"summary":"Api Create Cancel","description":"Cancel a generation job.\n\nSets the cancelled flag so the worker will stop at the next safe point.\nCannot cancel already completed or failed jobs.","operationId":"api_create_cancel_api_create_cancel__job_id__post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/upload":{"post":{"summary":"Api Upload Images","description":"Upload images to Catbox for public accessibility.\n\nThis endpoint receives user-uploaded images, uploads them to Catbox,\nand returns public URLs that can be used with AI providers.\n\nArgs:\n    files: List of image files (max 5, max 10MB each)\n    \nReturns:\n    urls: List of public Catbox URLs","operationId":"api_upload_images_api_upload_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_api_upload_images_api_upload_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/health":{"get":{"summary":"Health Check","description":"Health check endpoint.","operationId":"health_check_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/debug/config":{"get":{"summary":"Debug Config","description":"Debug endpoint showing current configuration.\nOnly available in mock mode.","operationId":"debug_config_api_debug_config_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"AssetResponse":{"properties":{"id":{"type":"string","title":"Id"},"asset_type":{"type":"string","title":"Asset Type"},"generation_type":{"type":"string","title":"Generation Type"},"generation_label":{"type":"string","title":"Generation Label"},"parent_asset_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Parent Asset Id"},"source_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Description"},"url":{"type":"string","title":"Url"},"source_image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Image Url"},"camera_motion":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Camera Motion"},"duration":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Duration"},"aspect_ratio":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Aspect Ratio"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"source_job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Job Id"},"is_multi_motion_variant":{"type":"boolean","title":"Is Multi Motion Variant","default":false},"multi_motion_group_size":{"type":"integer","title":"Multi Motion Group Size","default":1}},"type":"object","required":["id","asset_type","generation_type","generation_label","parent_asset_id","source_description","url","source_image_url","camera_motion","duration","aspect_ratio","created_at"],"title":"AssetResponse"},"Body_api_upload_images_api_upload_post":{"properties":{"files":{"items":{"type":"string","format":"binary"},"type":"array","title":"Files"}},"type":"object","required":["files"],"title":"Body_api_upload_images_api_upload_post"},"ChangeMotionRequest":{"properties":{"camera_motion":{"type":"string","title":"Camera Motion","description":"New camera motion"},"duration":{"type":"string","title":"Duration","description":"Duration: 5s or 10s"}},"type":"object","required":["camera_motion","duration"],"title":"ChangeMotionRequest"},"ChangeMotionResponse":{"properties":{"job_id":{"type":"string","title":"Job Id"},"project_id":{"type":"string","title":"Project Id"},"status":{"type":"string","title":"Status"},"credits_used":{"type":"integer","title":"Credits Used"}},"type":"object","required":["job_id","project_id","status","credits_used"],"title":"ChangeMotionResponse"},"CreateCheckoutRequest":{"properties":{"priceId":{"type":"string","title":"Priceid","description":"Stripe price ID for the plan"}},"type":"object","required":["priceId"],"title":"CreateCheckoutRequest","description":"Request body for creating a checkout session."},"CreateCheckoutResponse":{"properties":{"url":{"type":"string","title":"Url","description":"Stripe Checkout URL to redirect to"}},"type":"object","required":["url"],"title":"CreateCheckoutResponse","description":"Response for checkout session creation."},"CreateJobResponse":{"properties":{"job_id":{"type":"string","title":"Job Id"},"status":{"type":"string","title":"Status"}},"type":"object","required":["job_id","status"],"title":"CreateJobResponse","description":"Response model for job creation."},"CreateRequest":{"properties":{"ad_type":{"type":"string","title":"Ad Type","description":"Ad type: product_highlight, fresh_natural, premium_luxury, editorial_lifestyle, cinematic_closeup, vivid_color, hydration"},"images":{"items":{"type":"string"},"type":"array","maxItems":5,"minItems":1,"title":"Images","description":"List of uploaded image filenames"},"preset_tags":{"items":{"type":"string"},"type":"array","title":"Preset Tags","description":"Preset tags (max 2)","default":[]},"mini_descriptor":{"type":"string","title":"Mini Descriptor","description":"Mini descriptor (max 30 chars)","default":""},"camera_motion":{"type":"string","title":"Camera Motion","description":"Camera motion: subtle_hover, slow_push, slow_pull, slow_orbit"},"duration":{"type":"string","title":"Duration","description":"Duration: 5s or 10s"},"aspect_ratio":{"type":"string","title":"Aspect Ratio","description":"Aspect ratio: 16:9, 9:16, or 1:1","default":"16:9"},"auto_analysis":{"type":"boolean","title":"Auto Analysis","description":"Enable auto product analysis","default":true},"mode":{"type":"string","title":"Mode","description":"Generation mode: normal, recreate, change_motion","default":"normal"},"project_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Id","description":"Source project ID for re-create/change_motion modes"},"motion_variants":{"type":"integer","maximum":3.0,"minimum":0.0,"title":"Motion Variants","description":"Additional motion variants (0-3, Scale/Admin only)","default":0}},"type":"object","required":["ad_type","images","camera_motion","duration"],"title":"CreateRequest","description":"Request body for job creation."},"FingerprintData":{"properties":{"device_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Id"},"cookie_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cookie Id"},"screen_resolution":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Screen Resolution"},"timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Timezone"},"language":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Language"},"platform":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Platform"},"timestamp":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Timestamp"}},"type":"object","title":"FingerprintData","description":"Fingerprint data from the client for free credit tracking."},"GalleryListResponse":{"properties":{"projects":{"items":{"$ref":"#/components/schemas/ProjectSummaryResponse"},"type":"array","title":"Projects"},"total":{"type":"integer","title":"Total"},"has_more":{"type":"boolean","title":"Has More"},"has_expired":{"type":"boolean","title":"Has Expired","default":false},"retention_days":{"type":"integer","title":"Retention Days","default":0}},"type":"object","required":["projects","total","has_more"],"title":"GalleryListResponse"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ImageAssetResponse":{"properties":{"id":{"type":"string","title":"Id"},"url":{"type":"string","title":"Url"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","url","created_at"],"title":"ImageAssetResponse"},"JobResponse":{"properties":{"job_id":{"type":"string","title":"Job Id"},"state":{"type":"string","title":"State"},"progress":{"type":"integer","title":"Progress","description":"Progress percentage (0-100)","default":0},"messages":{"items":{"type":"string"},"type":"array","title":"Messages"},"hero_image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hero Image Url"},"video_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Video Url"},"video_variants":{"items":{"type":"string"},"type":"array","title":"Video Variants","description":"Additional motion variant video URLs"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"credits_used":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Credits Used"},"credits_remaining":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Credits Remaining"},"project_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Id"}},"type":"object","required":["job_id","state"],"title":"JobResponse","description":"Response model for job status endpoint."},"ProjectDetailResponse":{"properties":{"id":{"type":"string","title":"Id"},"ad_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ad Type"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"plan_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Plan Type"},"primary_asset_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Primary Asset Id"},"assets":{"items":{"$ref":"#/components/schemas/AssetResponse"},"type":"array","title":"Assets"},"image":{"anyOf":[{"$ref":"#/components/schemas/ImageAssetResponse"},{"type":"null"}]},"videos":{"items":{"$ref":"#/components/schemas/VideoAssetResponse"},"type":"array","title":"Videos"},"recipe":{"anyOf":[{"$ref":"#/components/schemas/RecipeResponse"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"can_recreate":{"type":"boolean","title":"Can Recreate"},"can_change_motion":{"type":"boolean","title":"Can Change Motion"},"gallery_can_download":{"type":"boolean","title":"Gallery Can Download","default":false},"gallery_can_view_detail":{"type":"boolean","title":"Gallery Can View Detail","default":true},"is_multi_motion_run":{"type":"boolean","title":"Is Multi Motion Run","default":false},"multi_motion_variant_count":{"type":"integer","title":"Multi Motion Variant Count","default":0}},"type":"object","required":["id","ad_type","title","plan_type","primary_asset_id","assets","image","videos","recipe","created_at","updated_at","can_recreate","can_change_motion"],"title":"ProjectDetailResponse"},"ProjectSummaryResponse":{"properties":{"id":{"type":"string","title":"Id"},"ad_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ad Type"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"image_url":{"type":"string","title":"Image Url"},"has_video":{"type":"boolean","title":"Has Video"},"video_count":{"type":"integer","title":"Video Count"},"asset_count":{"type":"integer","title":"Asset Count"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"is_multi_motion_run":{"type":"boolean","title":"Is Multi Motion Run","default":false},"multi_motion_variant_count":{"type":"integer","title":"Multi Motion Variant Count","default":0}},"type":"object","required":["id","ad_type","title","image_url","has_video","video_count","asset_count","created_at"],"title":"ProjectSummaryResponse"},"RecipeResponse":{"properties":{"ad_type":{"type":"string","title":"Ad Type"},"camera_motion":{"type":"string","title":"Camera Motion"},"duration":{"type":"string","title":"Duration"},"aspect_ratio":{"type":"string","title":"Aspect Ratio","default":"16:9"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"mini_descriptor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mini Descriptor"},"source_images":{"items":{"type":"string"},"type":"array","title":"Source Images"},"auto_analysis":{"type":"boolean","title":"Auto Analysis"}},"type":"object","required":["ad_type","camera_motion","duration","tags","mini_descriptor","source_images","auto_analysis"],"title":"RecipeResponse"},"RegisterUserRequest":{"properties":{"fingerprint":{"$ref":"#/components/schemas/FingerprintData"}},"type":"object","required":["fingerprint"],"title":"RegisterUserRequest","description":"Request body for user registration with fingerprint."},"RegisterUserResponse":{"properties":{"user_id":{"type":"string","title":"User Id"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"credits_remaining":{"type":"integer","title":"Credits Remaining","default":0},"free_credits_granted":{"type":"boolean","title":"Free Credits Granted","default":false},"free_credits_amount":{"type":"integer","title":"Free Credits Amount","default":0},"grant_reason":{"type":"string","title":"Grant Reason","default":""},"plan":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Plan"},"subscription_status":{"type":"string","title":"Subscription Status","default":"inactive"}},"type":"object","required":["user_id"],"title":"RegisterUserResponse","description":"Response for user registration."},"SetPrimaryAssetRequest":{"properties":{"asset_id":{"type":"string","title":"Asset Id","description":"Asset ID to set as primary"}},"type":"object","required":["asset_id"],"title":"SetPrimaryAssetRequest"},"UserCreditsResponse":{"properties":{"plan":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Plan"},"credits_remaining":{"type":"integer","title":"Credits Remaining","default":0},"subscription_status":{"type":"string","title":"Subscription Status","default":"inactive"},"billing_cycle_end":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Billing Cycle End"}},"type":"object","title":"UserCreditsResponse","description":"Response for user credits query."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"VideoAssetResponse":{"properties":{"id":{"type":"string","title":"Id"},"url":{"type":"string","title":"Url"},"camera_motion":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Camera Motion"},"duration":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Duration"},"is_primary":{"type":"boolean","title":"Is Primary"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","url","camera_motion","duration","is_primary","created_at"],"title":"VideoAssetResponse"}}}}