{"openapi":"3.1.0","info":{"title":"TextOnFlow API","description":"API pública de TextOnFlow — personalización dinámica de imágenes para ManyChat.\n\n**Autenticación:** Bearer JWT (`Authorization: Bearer <token>`) obtenido en `/api/auth/login`.\n\n**Uso rápido:** `POST /generate-multi` con el JSON exportado desde el editor.","contact":{"name":"TextOnFlow Support","url":"https://textonflow.com/","email":"hola@textonflow.com"},"license":{"name":"Privativo — solo clientes TextOnFlow"},"version":"7.0.0"},"paths":{"/user/register":{"post":{"summary":"User Register","description":"Registra un usuario nuevo con plan trial (20 renders).","operationId":"user_register_user_register_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_UserRegisterBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/user/login":{"post":{"summary":"User Login","description":"Login de usuario — devuelve JWT válido por 7 días.","operationId":"user_login_user_login_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_UserLoginBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/user/me":{"get":{"summary":"User Me","description":"Devuelve los datos del usuario autenticado.","operationId":"user_me_user_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"put":{"summary":"User Update","description":"Actualiza datos del usuario (gemini_api_key, etc.).","operationId":"user_update_user_me_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_UserUpdateBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/me":{"delete":{"tags":["Usuarios"],"summary":"Eliminar cuenta (GDPR)","description":"Elimina permanentemente la cuenta del usuario autenticado y todos sus datos asociados.\nCancela la suscripción activa en Stripe si existe.\nCumplimiento GDPR Art. 17 — Derecho de supresión.","operationId":"delete_user_me_api_user_me_delete","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/user/usage":{"get":{"summary":"User Usage","description":"Devuelve el uso actual de renders del usuario autenticado.","operationId":"user_usage_user_usage_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/user/webhook":{"get":{"tags":["webhooks"],"summary":"Obtener webhook URL configurado","description":"Devuelve el webhook_url configurado para el usuario autenticado.","operationId":"get_user_webhook_user_webhook_get","responses":{"200":{"description":"URL de webhook del usuario o null","content":{"application/json":{"schema":{}}}}}},"put":{"tags":["webhooks"],"summary":"Configurar webhook URL","description":"Guarda o borra el webhook_url del usuario.\nTextOnFlow hará POST a esa URL tras cada render exitoso con el payload:\n`{\"event\":\"render.done\",\"image_url\":\"...\",\"template\":\"...\",\"ts\":\"...\"}`","operationId":"set_user_webhook_user_webhook_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_WebhookBody"}}},"required":true},"responses":{"200":{"description":"Confirmación de actualización","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/projects":{"post":{"tags":["projects"],"summary":"Crear proyecto","description":"Crea un nuevo proyecto guardando el estado completo del canvas.","operationId":"create_project_projects_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_ProjectCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["projects"],"summary":"Listar proyectos del usuario","description":"Devuelve los proyectos del usuario ordenados por actualización desc.","operationId":"list_projects_projects_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/projects/{project_id}":{"get":{"tags":["projects"],"summary":"Obtener proyecto con canvas completo","description":"Devuelve el proyecto completo incluyendo canvas_json para restaurar el editor.","operationId":"get_project_projects__project_id__get","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["projects"],"summary":"Actualizar proyecto","description":"Actualiza nombre, canvas o imagen de un proyecto existente.","operationId":"update_project_projects__project_id__put","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_ProjectUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["projects"],"summary":"Eliminar proyecto","description":"Elimina un proyecto del usuario.","operationId":"delete_project_projects__project_id__delete","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/user/forgot-password":{"post":{"summary":"User Forgot Password","description":"Genera token de reset y envía email. Siempre responde OK (no revela si email existe).","operationId":"user_forgot_password_user_forgot_password_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_ForgotPasswordBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/user/reset-password":{"post":{"summary":"User Reset Password","description":"Valida el token y actualiza la contraseña.","operationId":"user_reset_password_user_reset_password_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_ResetPasswordBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/user/can-export":{"get":{"summary":"User Can Export","description":"Indica si el usuario puede exportar JSON (solo planes pagados).","operationId":"user_can_export_user_can_export_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/user/track-copy":{"post":{"summary":"User Track Copy","description":"Registra que el usuario dio clic en 'Copiar JSON'. Requiere JWT.","operationId":"user_track_copy_user_track_copy_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/user/session/open":{"post":{"summary":"Image Session Open","description":"Registra apertura de una sesión de imagen (anónimo o autenticado).","operationId":"image_session_open_user_session_open_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_SessionOpenBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/user/session/close":{"post":{"summary":"Image Session Close","description":"Registra cierre de una sesión de imagen y calcula duración.","operationId":"image_session_close_user_session_close_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_SessionCloseBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/image-sessions":{"get":{"summary":"Admin Image Sessions","description":"Reporte de sesiones por imagen — solo superadmin.","operationId":"admin_image_sessions_api_admin_image_sessions_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/users":{"get":{"summary":"Admin List Users","description":"Lista todos los usuarios con stats completas (solo superadmin).","operationId":"admin_list_users_api_admin_users_get","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","default":1,"title":"Page"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":200,"title":"Limit"}}],"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":"Admin Global Stats","description":"Estadísticas globales del sistema (solo superadmin).","operationId":"admin_global_stats_api_admin_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/users/toggle-active":{"post":{"summary":"Admin Toggle Active","description":"Activa o desactiva la cuenta de un usuario (superadmin).","operationId":"admin_toggle_active_api_admin_users_toggle_active_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_AdminUserActionBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/users/toggle-paused":{"post":{"summary":"Admin Toggle Paused","description":"Pausa o reanuda la cuenta de un usuario sin desactivarla (superadmin).","operationId":"admin_toggle_paused_api_admin_users_toggle_paused_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_AdminUserActionBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/users/delete":{"delete":{"summary":"Admin Delete User","description":"Elimina permanentemente un usuario (superadmin). El propio superadmin no puede eliminarse.","operationId":"admin_delete_user_api_admin_users_delete_delete","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_AdminUserActionBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/users/toggle-watermark":{"post":{"summary":"Admin Toggle Watermark","description":"Otorga o revoca la exención de watermark a un usuario (superadmin).","operationId":"admin_toggle_watermark_api_admin_users_toggle_watermark_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_AdminUserActionBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/users/reset-renders":{"post":{"summary":"Admin Reset Renders","description":"Reinicia el contador de renders de un usuario (superadmin).","operationId":"admin_reset_renders_api_admin_users_reset_renders_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_AdminUserActionBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/stripe/checkout":{"post":{"summary":"Stripe Checkout","description":"Crea una Stripe Checkout Session y devuelve la URL de pago.","operationId":"stripe_checkout_stripe_checkout_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_CheckoutBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/stripe/success":{"get":{"summary":"Stripe Success","description":"Redirige al dashboard con flag de éxito.","operationId":"stripe_success_stripe_success_get","parameters":[{"name":"session_id","in":"query","required":false,"schema":{"type":"string","default":"","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/stripe/webhook":{"post":{"summary":"Stripe Webhook","description":"Recibe eventos de Stripe y actualiza el plan del usuario en BD.","operationId":"stripe_webhook_stripe_webhook_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/stripe/config":{"get":{"summary":"Stripe Config","description":"Devuelve la clave pública y los price IDs (para el frontend).","operationId":"stripe_config_stripe_config_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/auth/login":{"post":{"summary":"Admin Login","description":"Login de superadmin — devuelve un token de sesión de 30 días.","operationId":"admin_login_api_auth_login_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_AdminLoginBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/logout":{"post":{"summary":"Admin Logout","operationId":"admin_logout_api_auth_logout_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/auth/me":{"get":{"summary":"Admin Me","operationId":"admin_me_api_auth_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/settings":{"get":{"summary":"Admin Get Settings","description":"Devuelve la configuración editable (solo superadmin).","operationId":"admin_get_settings_api_admin_settings_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Admin Set Settings","description":"Actualiza la configuración en caliente (solo superadmin).","operationId":"admin_set_settings_api_admin_settings_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_AdminSettingsBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/generate-multi":{"post":{"summary":"Generate Multi Text","operationId":"generate_multi_text_generate_multi_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MultiTextRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/render-async":{"post":{"tags":["render"],"summary":"Enviar render a la cola (respuesta inmediata)","description":"Encola el render y devuelve un **job_id** de inmediato (HTTP 202).  \nUsa `GET /render-jobs/{job_id}` para obtener el resultado cuando esté listo.  \nÚtil para integraciones Make/Zapier donde el tiempo de respuesta es limitado.","operationId":"render_async_endpoint_render_async_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MultiTextRequest"}}},"required":true},"responses":{"202":{"description":"job_id para consultar el estado luego","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/render-jobs/{job_id}":{"get":{"tags":["render"],"summary":"Consultar estado de un render asíncrono","description":"Devuelve el estado del job: `queued` → `processing` → `done` | `error`.  \nCuando `status == \"done\"`, el campo `result` contiene `{image_url, usage}`.","operationId":"get_render_job_render_jobs__job_id__get","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/templates":{"get":{"summary":"List Api Templates","description":"Lista todos los templates de API guardados.","operationId":"list_api_templates_api_templates_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Save Api Template","description":"Guarda el diseño actual como template de API. Devuelve ID + URL de render.","operationId":"save_api_template_api_templates_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiTemplateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/templates/{template_id}":{"put":{"summary":"Update Api Template","description":"Actualiza el diseño completo de un template existente (template_name, textos, formas, etc.).","operationId":"update_api_template_api_templates__template_id__put","parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","title":"Template Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiTemplateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Delete Api Template","description":"Elimina un template de API por su ID.","operationId":"delete_api_template_api_templates__template_id__delete","parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","title":"Template Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/templates/{template_id}/stats":{"get":{"summary":"Get Template Stats","description":"Devuelve estadísticas de uso de un template.","operationId":"get_template_stats_api_templates__template_id__stats_get","parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","title":"Template Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/templates/{template_id}/rotate-key":{"post":{"summary":"Rotate Template Key","description":"Genera una nueva API key para el template.","operationId":"rotate_template_key_api_templates__template_id__rotate_key_post","parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","title":"Template Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/templates/{template_id}/settings":{"patch":{"summary":"Update Template Settings","description":"Actualiza require_api_key y rate_limit_per_hour del template.","operationId":"update_template_settings_api_templates__template_id__settings_patch","parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","title":"Template Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/render/{template_id}":{"get":{"summary":"Render Api Template","description":"Endpoint público de render dinámico.\nAcepta variables como query params: /render/{id}?nombre=Juan&descuento=30\nDevuelve imagen JPEG directamente (sin guardar en disco).","operationId":"render_api_template_render__template_id__get","parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","title":"Template Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/webhook/render":{"post":{"summary":"Webhook Render","description":"Webhook POST para integraciones Make / Zapier / CRM.\nCuerpo: {\"template_id\":\"abc\",\"variables\":{\"nombre\":\"Juan\",\"descuento\":\"30\"}}\nDevuelve JSON con image_url y metadatos — NO requiere API key.","operationId":"webhook_render_webhook_render_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookRenderRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/templates/{template_id}/secret":{"post":{"summary":"Set Template Secret","description":"Establece o actualiza el webhook_secret de un template.","operationId":"set_template_secret_api_templates__template_id__secret_post","parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","title":"Template Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/image/{filename}":{"get":{"summary":"Get Image","operationId":"get_image_image__filename__get","parameters":[{"name":"filename","in":"path","required":true,"schema":{"type":"string","title":"Filename"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/stats":{"get":{"summary":"Get Stats","description":"Devuelve estadísticas públicas de uso de TextOnFlow.","operationId":"get_stats_api_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/gif/generate":{"post":{"summary":"Generate Gif","description":"Genera un GIF animado (typewriter o fade) a partir de un diseño TextOnFlow.","operationId":"generate_gif_api_gif_generate_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/_GifRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/generate-image":{"post":{"summary":"Generate Image","description":"Inicia la generación en segundo plano y devuelve job_id de inmediato.\nEl cliente hace polling a /api/image-job/{job_id} cada 2 s.\nEsto evita que Railway corte la conexión por timeout.","operationId":"generate_image_api_generate_image_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateImageRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/image-job/{job_id}":{"get":{"summary":"Get Image Job","description":"Devuelve el estado del job. El cliente hace polling aquí.","operationId":"get_image_job_api_image_job__job_id__get","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/generate-text":{"post":{"summary":"Generate Text","operationId":"generate_text_api_generate_text_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateTextRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/enhance-prompt":{"post":{"summary":"Enhance Prompt","operationId":"enhance_prompt_api_enhance_prompt_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnhancePromptRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/storage/{filename}":{"get":{"summary":"Serve Storage File","description":"Sirve archivos desde el directorio de almacenamiento persistente.","operationId":"serve_storage_file_storage__filename__get","parameters":[{"name":"filename","in":"path","required":true,"schema":{"type":"string","title":"Filename"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/save-ai-image":{"post":{"summary":"Save Ai Image","description":"Guarda una imagen AI — intenta Supabase Storage primero (URL permanente),\ncae a disco local solo si Supabase falla.","operationId":"save_ai_image_api_save_ai_image_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveAIImageRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/edit-image":{"post":{"summary":"Edit Image","description":"Toma una imagen existente (base64) y una instrucción en texto,\nllama a Gemini en modo imagen→imagen y devuelve la imagen editada.\nAcepta imágenes de referencia opcionales para guiar la edición.","operationId":"edit_image_api_edit_image_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EditImageRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/upload-image":{"post":{"summary":"Upload Image","description":"Sube una imagen desde el cliente y devuelve su URL pública persistente.","operationId":"upload_image_api_upload_image_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_image_api_upload_image_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/qr":{"post":{"summary":"Generate Qr","description":"Genera un QR como PNG base64 con fondo de color y padding.","operationId":"generate_qr_api_qr_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QRRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/feedback":{"post":{"summary":"Submit Feedback","operationId":"submit_feedback_api_feedback_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/timer/save":{"post":{"summary":"Save Timer Template","description":"Guarda un template de contador y devuelve las URLs listas para usar en ManyChat.","operationId":"save_timer_template_api_timer_save_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TimerTemplateCreate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TimerTemplateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/live/{template_id}.jpg":{"get":{"summary":"Render Live Timer","description":"Renderiza la imagen con el contador en tiempo real.\nCada vez que se carga esta URL, el servidor calcula el tiempo restante exacto.","operationId":"render_live_timer_live__template_id__jpg_get","parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","title":"Template Id"}},{"name":"s","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"S"}},{"name":"uid","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Uid"}},{"name":"user_start","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Start"}},{"name":"_t","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":" T"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/timer/{template_id}":{"get":{"summary":"Get Timer Template","description":"Devuelve la configuración de un template de timer (para el editor).","operationId":"get_timer_template_api_timer__template_id__get","parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","title":"Template Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/configurador":{"get":{"summary":"Configurador","operationId":"configurador_configurador_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/assistant":{"post":{"summary":"Flowbot Chat","operationId":"flowbot_chat_api_assistant_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssistantRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/assistant/transcript":{"post":{"summary":"Send Assistant Transcript","operationId":"send_assistant_transcript_api_assistant_transcript_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranscriptRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/inpaint":{"post":{"summary":"Inpaint Image","description":"Borrador Mágico IA — recibe imagen ORIGINAL + máscara B&W separada.\nLa máscara tiene blanco donde borrar, negro donde mantener.\nGemini recibe ambas imágenes y rellena el área blanca con fondo natural.\nBody: { \"original\": \"<base64 JPEG>\", \"mask\": \"<base64 PNG>\" }\nReturns: { \"result\": \"<base64>\", \"mime\": \"image/jpeg\" }","operationId":"inpaint_image_api_inpaint_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/assistant/rating":{"post":{"summary":"Submit Assistant Rating","operationId":"submit_assistant_rating_api_assistant_rating_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RatingRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/ai/design-layout":{"post":{"summary":"Ai Design Layout","operationId":"ai_design_layout_api_ai_design_layout_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DesignLayoutRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/ai/copy-suggestions":{"post":{"summary":"Ai Copy Suggestions","operationId":"ai_copy_suggestions_api_ai_copy_suggestions_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CopySuggestionsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/ai/brand-kit":{"post":{"summary":"Ai Brand Kit","operationId":"ai_brand_kit_api_ai_brand_kit_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandKitRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/ai/ab-variants":{"post":{"summary":"Ai Ab Variants","operationId":"ai_ab_variants_api_ai_ab_variants_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ABVariantsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/batch/preview-columns":{"post":{"summary":"Preview Columns","description":"Descarga la hoja y devuelve headers + primeras 5 filas para mapear columnas.","operationId":"preview_columns_api_batch_preview_columns_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreviewColumnsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/batch/from-url":{"post":{"summary":"Batch From Url","description":"Genera imágenes para cada fila de un CSV / Google Sheet y devuelve un ZIP.","operationId":"batch_from_url_api_batch_from_url_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchFromUrlRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mc/template":{"post":{"tags":["manychat"],"summary":"Save Mc Template","description":"Guarda el diseño actual como plantilla ManyChat.\nDevuelve una URL lista para pegar en el HTTP Request de ManyChat.","operationId":"save_mc_template_api_mc_template_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveTemplateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mc/{template_id}/render":{"get":{"tags":["manychat"],"summary":"Render Mc Template","description":"Renderiza una plantilla guardada reemplazando las variables de ManyChat.\nManyChat llama este endpoint como HTTP Request (GET).\nDevuelve: {\"success\": true, \"image_url\": \"https://...\"}","operationId":"render_mc_template_api_mc__template_id__render_get","parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","title":"Template Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/":{"get":{"summary":"Root","operationId":"root__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/dashboard":{"get":{"summary":"Dashboard","operationId":"dashboard_dashboard_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/status":{"get":{"summary":"Status","operationId":"status_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/health":{"get":{"summary":"Health","description":"Health check rápido — solo verifica que la app esté viva.","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/usage":{"get":{"summary":"Get Usage","description":"Uso diario de la IP actual (rate limiting).","operationId":"get_usage_api_usage_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/manual":{"get":{"summary":"Manual Page","operationId":"manual_page_manual_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/privacidad":{"get":{"summary":"Privacidad Page","operationId":"privacidad_page_privacidad_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/terminos":{"get":{"summary":"Terminos Page","operationId":"terminos_page_terminos_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/docs":{"get":{"summary":"Docs Page","operationId":"docs_page_docs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/faq":{"get":{"summary":"Faq Page","operationId":"faq_page_faq_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/precios":{"get":{"summary":"Precios Page","operationId":"precios_page_precios_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/casos":{"get":{"summary":"Casos Page","operationId":"casos_page_casos_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/.well-known/sg-hosted-ping":{"get":{"summary":"Sg Ping","operationId":"sg_ping__well_known_sg_hosted_ping_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/robots.txt":{"get":{"summary":"Robots","operationId":"robots_robots_txt_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/sitemap.xml":{"get":{"summary":"Sitemap","operationId":"sitemap_sitemap_xml_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/proxy-image":{"get":{"summary":"Proxy Image","operationId":"proxy_image_proxy_image_get","parameters":[{"name":"url","in":"query","required":true,"schema":{"type":"string","title":"Url"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/download":{"get":{"summary":"Download Index","operationId":"download_index_api_download_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/download/{filepath}":{"get":{"summary":"Download Static","description":"Sirve archivos estáticos para que Railway los descargue en startup.","operationId":"download_static_api_download__filepath__get","parameters":[{"name":"filepath","in":"path","required":true,"schema":{"type":"string","title":"Filepath"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"ABVariantsRequest":{"properties":{"texts":{"items":{},"type":"array","title":"Texts"},"context":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Context"}},"type":"object","required":["texts"],"title":"ABVariantsRequest"},"ApiTemplateRequest":{"properties":{"name":{"type":"string","title":"Name"},"template_name":{"type":"string","title":"Template Name"},"texts":{"items":{"$ref":"#/components/schemas/TextField"},"type":"array","title":"Texts","default":[]},"shapes":{"anyOf":[{"items":{"$ref":"#/components/schemas/CanvasShape"},"type":"array"},{"type":"null"}],"title":"Shapes","default":[]},"overlays":{"anyOf":[{"items":{"$ref":"#/components/schemas/ImageOverlay"},"type":"array"},{"type":"null"}],"title":"Overlays","default":[]},"filter_name":{"type":"string","title":"Filter Name","default":"none"},"render_scale":{"type":"integer","title":"Render Scale","default":2},"watermark":{"type":"boolean","title":"Watermark","default":false},"vignette_enabled":{"type":"boolean","title":"Vignette Enabled","default":false},"vignette_color":{"type":"string","title":"Vignette Color","default":"#000000"},"vignette_opacity":{"type":"number","title":"Vignette Opacity","default":0.6},"vignette_size":{"type":"number","title":"Vignette Size","default":50.0},"vignette_sides":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Vignette Sides"},"vignette_filter":{"type":"string","title":"Vignette Filter","default":"none"},"format_width":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Format Width"},"format_height":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Format Height"},"img_pan_x":{"type":"number","title":"Img Pan X","default":0.0},"img_pan_y":{"type":"number","title":"Img Pan Y","default":0.0},"img_zoom":{"type":"number","title":"Img Zoom","default":1.0}},"type":"object","required":["name","template_name"],"title":"ApiTemplateRequest"},"AssistantMessage":{"properties":{"role":{"type":"string","title":"Role"},"content":{"type":"string","title":"Content"}},"type":"object","required":["role","content"],"title":"AssistantMessage"},"AssistantRequest":{"properties":{"message":{"type":"string","title":"Message"},"history":{"items":{"$ref":"#/components/schemas/AssistantMessage"},"type":"array","title":"History","default":[]}},"type":"object","required":["message"],"title":"AssistantRequest"},"BatchFromUrlRequest":{"properties":{"source_url":{"type":"string","title":"Source Url"},"template_json":{"type":"object","title":"Template Json"},"column_map":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Column Map","default":{}},"output_prefix":{"type":"string","title":"Output Prefix","default":"imagen"},"max_rows":{"type":"integer","title":"Max Rows","default":100}},"type":"object","required":["source_url","template_json"],"title":"BatchFromUrlRequest"},"Body_upload_image_api_upload_image_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_image_api_upload_image_post"},"BrandKitRequest":{"properties":{"image_url":{"type":"string","title":"Image Url"}},"type":"object","required":["image_url"],"title":"BrandKitRequest"},"CanvasShape":{"properties":{"id":{"type":"string","title":"Id","default":""},"shape_type":{"type":"string","title":"Shape Type","default":"rect"},"x":{"type":"integer","title":"X","default":0},"y":{"type":"integer","title":"Y","default":0},"width":{"type":"integer","title":"Width","default":100},"height":{"type":"integer","title":"Height","default":100},"rotation":{"type":"number","title":"Rotation","default":0},"fill_color":{"type":"string","title":"Fill Color","default":"#667eea"},"fill_opacity":{"type":"number","title":"Fill Opacity","default":0.8},"stroke_color":{"type":"string","title":"Stroke Color","default":"#000000"},"stroke_width":{"type":"integer","title":"Stroke Width","default":0},"stroke_opacity":{"type":"number","title":"Stroke Opacity","default":1.0},"z_index":{"type":"integer","title":"Z Index","default":0},"cover_blur":{"type":"integer","title":"Cover Blur","default":0}},"type":"object","title":"CanvasShape"},"CopySuggestionsRequest":{"properties":{"current_text":{"type":"string","title":"Current Text"},"context":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Context"}},"type":"object","required":["current_text"],"title":"CopySuggestionsRequest"},"DesignLayoutRequest":{"properties":{"description":{"type":"string","title":"Description"},"canvas_width":{"type":"integer","title":"Canvas Width","default":1080},"canvas_height":{"type":"integer","title":"Canvas Height","default":1080},"context":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Context"}},"type":"object","required":["description"],"title":"DesignLayoutRequest"},"EditImageRequest":{"properties":{"image_b64":{"type":"string","title":"Image B64"},"mime_type":{"type":"string","title":"Mime Type","default":"image/png"},"instruction":{"type":"string","title":"Instruction"},"reference_images":{"items":{},"type":"array","title":"Reference Images","default":[]}},"type":"object","required":["image_b64","instruction"],"title":"EditImageRequest"},"EnhancePromptRequest":{"properties":{"prompt":{"type":"string","title":"Prompt"},"no_text":{"type":"boolean","title":"No Text","default":false}},"type":"object","required":["prompt"],"title":"EnhancePromptRequest"},"FeedbackRequest":{"properties":{"name":{"type":"string","title":"Name"},"email":{"type":"string","title":"Email"},"message":{"type":"string","title":"Message"}},"type":"object","required":["name","email","message"],"title":"FeedbackRequest"},"GenerateImageRequest":{"properties":{"prompt":{"type":"string","title":"Prompt"},"aspect_ratio":{"type":"string","title":"Aspect Ratio","default":"1:1"},"style":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Style"},"reference_images":{"anyOf":[{"items":{"$ref":"#/components/schemas/RefImage"},"type":"array"},{"type":"null"}],"title":"Reference Images","default":[]}},"type":"object","required":["prompt"],"title":"GenerateImageRequest"},"GenerateTextRequest":{"properties":{"text":{"type":"string","title":"Text"},"tone":{"type":"string","title":"Tone","default":"Profesional"}},"type":"object","required":["text"],"title":"GenerateTextRequest"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ImageOverlay":{"properties":{"src":{"type":"string","title":"Src"},"x":{"type":"integer","title":"X","default":0},"y":{"type":"integer","title":"Y","default":0},"width":{"type":"integer","title":"Width","default":100},"height":{"type":"integer","title":"Height","default":100},"opacity":{"type":"number","title":"Opacity","default":1.0},"rotation":{"type":"number","title":"Rotation","default":0},"mask_type":{"type":"string","title":"Mask Type","default":"none"},"mask_auto_fit":{"type":"boolean","title":"Mask Auto Fit","default":true},"mask_radius":{"type":"integer","title":"Mask Radius","default":0},"mask_border_width":{"type":"integer","title":"Mask Border Width","default":0},"mask_border_color":{"type":"string","title":"Mask Border Color","default":"#ffffff"},"mask_border_opacity":{"type":"integer","title":"Mask Border Opacity","default":100},"mask_shadow_enabled":{"type":"boolean","title":"Mask Shadow Enabled","default":false},"mask_shadow_color":{"type":"string","title":"Mask Shadow Color","default":"#000000"},"mask_shadow_opacity":{"type":"integer","title":"Mask Shadow Opacity","default":70},"mask_shadow_blur":{"type":"integer","title":"Mask Shadow Blur","default":8},"mask_shadow_x":{"type":"integer","title":"Mask Shadow X","default":0},"mask_shadow_y":{"type":"integer","title":"Mask Shadow Y","default":4}},"type":"object","required":["src"],"title":"ImageOverlay"},"MultiTextRequest":{"properties":{"template_name":{"type":"string","title":"Template Name"},"texts":{"items":{"$ref":"#/components/schemas/TextField"},"type":"array","title":"Texts"},"vars":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Vars"},"overlays":{"anyOf":[{"items":{"$ref":"#/components/schemas/ImageOverlay"},"type":"array"},{"type":"null"}],"title":"Overlays","default":[]},"shapes":{"anyOf":[{"items":{"$ref":"#/components/schemas/CanvasShape"},"type":"array"},{"type":"null"}],"title":"Shapes","default":[]},"filter_name":{"type":"string","title":"Filter Name","default":"none"},"render_scale":{"type":"integer","title":"Render Scale","default":1},"watermark":{"type":"boolean","title":"Watermark","default":false},"wm_corner":{"type":"string","title":"Wm Corner","default":"br"},"wm_size":{"type":"integer","title":"Wm Size","default":22},"wm_opacity":{"type":"integer","title":"Wm Opacity","default":55},"wm_color":{"type":"string","title":"Wm Color","default":"#ffffff"},"vignette_enabled":{"type":"boolean","title":"Vignette Enabled","default":false},"vignette_color":{"type":"string","title":"Vignette Color","default":"#000000"},"vignette_opacity":{"type":"number","title":"Vignette Opacity","default":0.6},"vignette_size":{"type":"number","title":"Vignette Size","default":50.0},"vignette_sides":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Vignette Sides"},"vignette_filter":{"type":"string","title":"Vignette Filter","default":"none"},"format_width":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Format Width"},"format_height":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Format Height"},"img_pan_x":{"type":"number","title":"Img Pan X","default":0.0},"img_pan_y":{"type":"number","title":"Img Pan Y","default":0.0},"img_zoom":{"type":"number","title":"Img Zoom","default":1.0},"template_image_b64":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Template Image B64"},"project_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Name"}},"type":"object","required":["template_name","texts"],"title":"MultiTextRequest"},"PreviewColumnsRequest":{"properties":{"source_url":{"type":"string","title":"Source Url"}},"type":"object","required":["source_url"],"title":"PreviewColumnsRequest"},"QRRequest":{"properties":{"text":{"type":"string","title":"Text"},"dark_color":{"type":"string","title":"Dark Color","default":"#000000"},"light_color":{"type":"string","title":"Light Color","default":"#ffffff"},"bg_color":{"type":"string","title":"Bg Color","default":"#ffffff"},"padding":{"type":"integer","title":"Padding","default":20}},"type":"object","required":["text"],"title":"QRRequest"},"RatingRequest":{"properties":{"rating":{"type":"integer","title":"Rating"}},"type":"object","required":["rating"],"title":"RatingRequest"},"RefImage":{"properties":{"data":{"type":"string","title":"Data"},"mime_type":{"type":"string","title":"Mime Type"}},"type":"object","required":["data","mime_type"],"title":"RefImage"},"SaveAIImageRequest":{"properties":{"image_b64":{"type":"string","title":"Image B64"},"mime_type":{"type":"string","title":"Mime Type","default":"image/png"}},"type":"object","required":["image_b64"],"title":"SaveAIImageRequest"},"SaveTemplateRequest":{"properties":{"payload":{"type":"object","title":"Payload"}},"type":"object","required":["payload"],"title":"SaveTemplateRequest"},"TextField":{"properties":{"text":{"type":"string","title":"Text"},"x":{"type":"integer","title":"X"},"y":{"type":"integer","title":"Y"},"font_size":{"type":"integer","title":"Font Size","default":60},"font_color":{"type":"string","title":"Font Color","default":"#FFFFFF"},"rotation":{"type":"integer","title":"Rotation","default":0},"skew_x":{"type":"number","title":"Skew X","default":0},"skew_y":{"type":"number","title":"Skew Y","default":0},"background_color_type":{"type":"string","title":"Background Color Type","default":"solid"},"background_gradient_color2":{"type":"string","title":"Background Gradient Color2","default":"#FFFFFF"},"background_gradient_angle":{"type":"integer","title":"Background Gradient Angle","default":135},"background_stroke_type":{"type":"string","title":"Background Stroke Type","default":"solid"},"background_stroke_gradient_color2":{"type":"string","title":"Background Stroke Gradient Color2","default":"#FFFFFF"},"background_stroke_gradient_angle":{"type":"integer","title":"Background Stroke Gradient Angle","default":135},"background_stroke_dash":{"type":"string","title":"Background Stroke Dash","default":"solid"},"line_spacing":{"type":"integer","title":"Line Spacing","default":10},"alignment":{"type":"string","title":"Alignment","default":"left"},"text_align":{"type":"string","title":"Text Align","default":"center"},"font_name":{"type":"string","title":"Font Name","default":"Arial-Bold"},"shadow_enabled":{"type":"boolean","title":"Shadow Enabled","default":false},"shadow_color":{"type":"string","title":"Shadow Color","default":"#000000"},"shadow_opacity":{"type":"integer","title":"Shadow Opacity","default":100},"shadow_offset_x":{"type":"integer","title":"Shadow Offset X","default":2},"shadow_offset_y":{"type":"integer","title":"Shadow Offset Y","default":2},"shadow_blur":{"type":"integer","title":"Shadow Blur","default":0},"shadow_blend_mode":{"type":"string","title":"Shadow Blend Mode","default":"normal"},"stroke_enabled":{"type":"boolean","title":"Stroke Enabled","default":false},"stroke_color":{"type":"string","title":"Stroke Color","default":"#000000"},"stroke_opacity":{"type":"integer","title":"Stroke Opacity","default":100},"stroke_width":{"type":"integer","title":"Stroke Width","default":2},"background_enabled":{"type":"boolean","title":"Background Enabled","default":false},"background_color":{"type":"string","title":"Background Color","default":"#000000"},"background_opacity":{"type":"integer","title":"Background Opacity","default":80},"background_padding_top":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Background Padding Top","default":10},"background_padding_right":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Background Padding Right","default":10},"background_padding_bottom":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Background Padding Bottom","default":10},"background_padding_left":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Background Padding Left","default":10},"background_radius":{"type":"integer","title":"Background Radius","default":0},"background_stroke_color":{"type":"string","title":"Background Stroke Color","default":"#FFFFFF"},"background_stroke_width":{"type":"integer","title":"Background Stroke Width","default":0},"border_padding_top":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Border Padding Top","default":10},"border_padding_right":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Border Padding Right","default":20},"border_padding_bottom":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Border Padding Bottom","default":10},"border_padding_left":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Border Padding Left","default":20},"warp_style":{"type":"string","title":"Warp Style","default":"none"},"warp_bend":{"type":"integer","title":"Warp Bend","default":0},"text_wrap_enabled":{"type":"boolean","title":"Text Wrap Enabled","default":false},"text_wrap_padding":{"type":"integer","title":"Text Wrap Padding","default":60},"countdown_mode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Countdown Mode"},"countdown_event_end_utc":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Countdown Event End Utc"},"countdown_urgency_hours":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Countdown Urgency Hours"},"countdown_ts_var":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Countdown Ts Var"},"countdown_format":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Countdown Format","default":"HH:MM:SS"},"countdown_expired_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Countdown Expired Text"},"countdown_urgency_color":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Countdown Urgency Color"},"countdown_urgency_threshold_h":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Countdown Urgency Threshold H","default":3.0}},"type":"object","required":["text","x","y"],"title":"TextField"},"TimerStyle":{"properties":{"font":{"type":"string","title":"Font","default":"Doto"},"font_size":{"type":"integer","title":"Font Size","default":52},"color":{"type":"string","title":"Color","default":"#FFFFFF"},"x":{"type":"number","title":"X","default":50.0},"y":{"type":"number","title":"Y","default":50.0},"alignment":{"type":"string","title":"Alignment","default":"center"},"format":{"type":"string","title":"Format","default":"HH:MM:SS"},"expired_text":{"type":"string","title":"Expired Text","default":"¡Oferta expirada!"},"stroke_enabled":{"type":"boolean","title":"Stroke Enabled","default":true},"stroke_color":{"type":"string","title":"Stroke Color","default":"#000000"},"stroke_width":{"type":"integer","title":"Stroke Width","default":2},"shadow_enabled":{"type":"boolean","title":"Shadow Enabled","default":false},"shadow_color":{"type":"string","title":"Shadow Color","default":"#000000"},"shadow_offset_x":{"type":"number","title":"Shadow Offset X","default":2.0},"shadow_offset_y":{"type":"number","title":"Shadow Offset Y","default":2.0},"expired_wrap_enabled":{"type":"boolean","title":"Expired Wrap Enabled","default":true},"expired_wrap_padding":{"type":"integer","title":"Expired Wrap Padding","default":60},"expired_align":{"type":"string","title":"Expired Align","default":"center"}},"type":"object","title":"TimerStyle"},"TimerTemplateCreate":{"properties":{"template_name":{"type":"string","title":"Template Name"},"base_image_url":{"type":"string","title":"Base Image Url"},"mode":{"type":"string","title":"Mode"},"event_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Event Date"},"event_tz":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Event Tz","default":"America/Mexico_City"},"urgency_hours":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Urgency Hours"},"style":{"$ref":"#/components/schemas/TimerStyle","default":{"font":"Doto","font_size":52,"color":"#FFFFFF","x":50.0,"y":50.0,"alignment":"center","format":"HH:MM:SS","expired_text":"¡Oferta expirada!","stroke_enabled":true,"stroke_color":"#000000","stroke_width":2,"shadow_enabled":false,"shadow_color":"#000000","shadow_offset_x":2.0,"shadow_offset_y":2.0,"expired_wrap_enabled":true,"expired_wrap_padding":60,"expired_align":"center"}},"expired_image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Expired Image Url"}},"type":"object","required":["template_name","base_image_url","mode"],"title":"TimerTemplateCreate"},"TimerTemplateResponse":{"properties":{"template_id":{"type":"string","title":"Template Id"},"live_url_event":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Live Url Event"},"live_url_urgency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Live Url Urgency"},"preview_seconds":{"type":"integer","title":"Preview Seconds"}},"type":"object","required":["template_id","preview_seconds"],"title":"TimerTemplateResponse"},"TranscriptRequest":{"properties":{"name":{"type":"string","title":"Name"},"email":{"type":"string","title":"Email"},"history":{"items":{"$ref":"#/components/schemas/AssistantMessage"},"type":"array","title":"History","default":[]}},"type":"object","required":["name","email"],"title":"TranscriptRequest"},"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"},"WebhookRenderRequest":{"properties":{"template_id":{"type":"string","title":"Template Id"},"variables":{"additionalProperties":{"type":"string"},"type":"object","title":"Variables","default":{}},"secret":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Secret"},"output_format":{"type":"string","title":"Output Format","default":"url"}},"type":"object","required":["template_id"],"title":"WebhookRenderRequest"},"_AdminLoginBody":{"properties":{"email":{"type":"string","title":"Email"},"password":{"type":"string","title":"Password"}},"type":"object","required":["email","password"],"title":"_AdminLoginBody"},"_AdminSettingsBody":{"properties":{"free_limit":{"type":"integer","title":"Free Limit"}},"type":"object","required":["free_limit"],"title":"_AdminSettingsBody"},"_AdminUserActionBody":{"properties":{"user_id":{"type":"string","title":"User Id"}},"type":"object","required":["user_id"],"title":"_AdminUserActionBody"},"_CheckoutBody":{"properties":{"plan":{"type":"string","title":"Plan"},"success_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Success Url"},"cancel_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cancel Url"}},"type":"object","required":["plan"],"title":"_CheckoutBody"},"_ForgotPasswordBody":{"properties":{"email":{"type":"string","title":"Email"}},"type":"object","required":["email"],"title":"_ForgotPasswordBody"},"_GifRequest":{"properties":{"template_name":{"type":"string","title":"Template Name"},"texts":{"items":{"$ref":"#/components/schemas/TextField"},"type":"array","title":"Texts"},"vars":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Vars"},"overlays":{"anyOf":[{"items":{"$ref":"#/components/schemas/ImageOverlay"},"type":"array"},{"type":"null"}],"title":"Overlays","default":[]},"shapes":{"anyOf":[{"items":{"$ref":"#/components/schemas/CanvasShape"},"type":"array"},{"type":"null"}],"title":"Shapes","default":[]},"filter_name":{"type":"string","title":"Filter Name","default":"none"},"render_scale":{"type":"integer","title":"Render Scale","default":1},"watermark":{"type":"boolean","title":"Watermark","default":false},"wm_corner":{"type":"string","title":"Wm Corner","default":"br"},"wm_size":{"type":"integer","title":"Wm Size","default":22},"wm_opacity":{"type":"integer","title":"Wm Opacity","default":55},"wm_color":{"type":"string","title":"Wm Color","default":"#ffffff"},"vignette_enabled":{"type":"boolean","title":"Vignette Enabled","default":false},"vignette_color":{"type":"string","title":"Vignette Color","default":"#000000"},"vignette_opacity":{"type":"number","title":"Vignette Opacity","default":0.6},"vignette_size":{"type":"number","title":"Vignette Size","default":50.0},"vignette_sides":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Vignette Sides"},"vignette_filter":{"type":"string","title":"Vignette Filter","default":"none"},"format_width":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Format Width"},"format_height":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Format Height"},"img_pan_x":{"type":"number","title":"Img Pan X","default":0.0},"img_pan_y":{"type":"number","title":"Img Pan Y","default":0.0},"img_zoom":{"type":"number","title":"Img Zoom","default":1.0},"template_image_b64":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Template Image B64"},"project_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Name"},"animation_type":{"type":"string","title":"Animation Type","default":"typewriter"},"animated_text_index":{"type":"integer","title":"Animated Text Index","default":0},"gif_fps":{"type":"integer","title":"Gif Fps","default":12},"hold_seconds":{"type":"number","title":"Hold Seconds","default":1.5},"gif_loop":{"type":"integer","title":"Gif Loop","default":0}},"type":"object","required":["template_name","texts"],"title":"_GifRequest","description":"Igual que MultiTextRequest + parámetros de animación."},"_ProjectCreate":{"properties":{"name":{"type":"string","title":"Name","default":"Sin título"},"canvas_json":{"type":"object","title":"Canvas Json","default":{}},"image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Image Url"}},"type":"object","title":"_ProjectCreate"},"_ProjectUpdate":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"canvas_json":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Canvas Json"},"image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Image Url"}},"type":"object","title":"_ProjectUpdate"},"_ResetPasswordBody":{"properties":{"token":{"type":"string","title":"Token"},"new_password":{"type":"string","title":"New Password"}},"type":"object","required":["token","new_password"],"title":"_ResetPasswordBody"},"_SessionCloseBody":{"properties":{"session_key":{"type":"string","title":"Session Key"}},"type":"object","required":["session_key"],"title":"_SessionCloseBody"},"_SessionOpenBody":{"properties":{"session_key":{"type":"string","title":"Session Key"},"image_name":{"type":"string","title":"Image Name"},"image_type":{"type":"string","title":"Image Type","default":"url"}},"type":"object","required":["session_key","image_name"],"title":"_SessionOpenBody"},"_UserLoginBody":{"properties":{"email":{"type":"string","title":"Email"},"password":{"type":"string","title":"Password"}},"type":"object","required":["email","password"],"title":"_UserLoginBody"},"_UserRegisterBody":{"properties":{"email":{"type":"string","title":"Email"},"password":{"type":"string","title":"Password"}},"type":"object","required":["email","password"],"title":"_UserRegisterBody"},"_UserUpdateBody":{"properties":{"gemini_api_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Gemini Api Key"}},"type":"object","title":"_UserUpdateBody"},"_WebhookBody":{"properties":{"webhook_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Webhook Url"}},"type":"object","title":"_WebhookBody"}}},"tags":[{"name":"render","description":"Generación y renderizado de imágenes"},{"name":"projects","description":"Proyectos guardados del usuario"},{"name":"auth","description":"Autenticación y registro"},{"name":"user","description":"Perfil y uso del usuario"},{"name":"admin","description":"Panel de superadministrador"},{"name":"webhooks","description":"Webhooks de salida por usuario"}]}