{
  "openapi": "3.1.0",
  "info": {
    "title": "Reportia API",
    "description": "API REST para generar documentos profesionales desde JSON. Formatos: PDF, Excel (XLSX), CSV, HTML, Markdown, PNG, DOCX. Plantillas listas: facturas CFDI 4.0, reportes de ventas, balances, cotizaciones. Gratis: 50 documentos/mes. Pro $9/mes. Scale $29/mes. Lifetime $49.",
    "contact": {
      "name": "Reportia",
      "url": "https://reportia.4l3.org/",
      "email": "hola@4l3.org"
    },
    "license": {
      "name": "Proprietary"
    },
    "version": "0.1.0"
  },
  "servers": [
    {
      "url": "https://reportia.4l3.org"
    }
  ],
  "paths": {
    "/pay/status": {
      "get": {
        "summary": "Pay Status",
        "operationId": "pay_status_pay_status_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/pay/checkout/{plan}": {
      "get": {
        "summary": "Pay Checkout",
        "operationId": "pay_checkout_pay_checkout__plan__get",
        "parameters": [
          {
            "name": "plan",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Plan"
            }
          },
          {
            "name": "ref",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Ref"
            }
          },
          {
            "name": "coupon",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Coupon"
            }
          },
          {
            "name": "email",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Email"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "303": {
            "description": "Redirect a Stripe Checkout"
          },
          "404": {
            "description": "Plan inválido (esperado: pro, scale, lifetime)"
          },
          "503": {
            "description": "Pagos no configurados"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/pay/success": {
      "get": {
        "summary": "Pay Success",
        "operationId": "pay_success_pay_success_get",
        "parameters": [
          {
            "name": "session_id",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Session Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/pay/webhook": {
      "post": {
        "summary": "Stripe Webhook",
        "description": "Verifica firma Stripe + procesa eventos.\n\nEventos manejados:\n- checkout.session.completed → crea api_key, manda email con magic link\n- customer.subscription.deleted → revoca api_key",
        "operationId": "stripe_webhook_pay_webhook_post",
        "responses": {
          "200": {
            "description": "Evento procesado",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Firma inválida o body no es JSON"
          }
        }
      }
    },
    "/portal": {
      "get": {
        "summary": "Portal Home",
        "description": "Pantalla principal del portal. Si hay session válida → dashboard, sino → form.",
        "operationId": "portal_home_portal_get",
        "parameters": [
          {
            "name": "reportia_session",
            "in": "cookie",
            "required": false,
            "schema": {
              "type": "string",
              "title": "Reportia Session"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/portal/request-login": {
      "post": {
        "summary": "Portal Request Login",
        "operationId": "portal_request_login_portal_request_login_post",
        "responses": {
          "200": {
            "description": "Si la cuenta existe, se envía email con magic link (respuesta idéntica para no leak)",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Email inválido o JSON malformado"
          }
        }
      }
    },
    "/portal/login": {
      "get": {
        "summary": "Portal Login",
        "description": "Valida token, setea cookie, redirect a /portal.",
        "operationId": "portal_login_portal_login_get",
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Token"
            }
          },
          {
            "name": "key",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "303": {
            "description": "Login exitoso, redirect a /portal con cookie de sesión"
          },
          "403": {
            "description": "Token expirado o ya usado"
          },
          "404": {
            "description": "Token no encontrado"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/portal/login-password": {
      "post": {
        "summary": "Portal Login Password",
        "description": "Login con email+password (alternativa al magic link).\n\nValida contra `reportia_ai_users` (la tabla que crea AI signup). Si el email\ntambién tiene API key en `api_keys`, lo carga al dashboard. Si solo tiene\ncuenta IA (no compró), lo dejamos entrar con plan free al builder.",
        "operationId": "portal_login_password_portal_login_password_post",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "303": {
            "description": "Login OK, cookie + redirect a /portal"
          },
          "401": {
            "description": "Email o contraseña incorrectos"
          }
        }
      }
    },
    "/portal/logout": {
      "post": {
        "summary": "Portal Logout",
        "operationId": "portal_logout_portal_logout_post",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/portal/forgot-password": {
      "post": {
        "summary": "Portal Forgot Password",
        "description": "Manda email con token de reset password. Funciona para cuentas AI users.",
        "operationId": "portal_forgot_password_portal_forgot_password_post",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/portal/reset-password": {
      "get": {
        "summary": "Portal Reset Password Form",
        "description": "Muestra form para nueva password.",
        "operationId": "portal_reset_password_form_portal_reset_password_get",
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Token"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/portal/reset-password-submit": {
      "post": {
        "summary": "Portal Reset Password Submit",
        "operationId": "portal_reset_password_submit_portal_reset_password_submit_post",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/sheets/oauth/start": {
      "get": {
        "summary": "Oauth Start",
        "operationId": "oauth_start_sheets_oauth_start_get",
        "parameters": [
          {
            "name": "return_url",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "default": "/integraciones/google-sheets.html",
              "title": "Return Url"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "302": {
            "description": "Redirect a Google consent screen"
          },
          "503": {
            "description": "Google OAuth no configurado"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/sheets/oauth/callback": {
      "get": {
        "summary": "Oauth Callback",
        "operationId": "oauth_callback_sheets_oauth_callback_get",
        "parameters": [
          {
            "name": "code",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "default": "",
              "title": "Code"
            }
          },
          {
            "name": "state",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "default": "",
              "title": "State"
            }
          },
          {
            "name": "error",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Error"
            }
          },
          {
            "name": "reportia_sheets_state",
            "in": "cookie",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Reportia Sheets State"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "302": {
            "description": "Redirect a return_url"
          },
          "400": {
            "description": "Code/state inválido"
          },
          "503": {
            "description": "Google OAuth no configurado"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/sheets/list": {
      "get": {
        "summary": "List Connections",
        "operationId": "list_connections_sheets_list_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/sheets/{connection_id}/spreadsheets": {
      "get": {
        "summary": "List Spreadsheets",
        "operationId": "list_spreadsheets_sheets__connection_id__spreadsheets_get",
        "parameters": [
          {
            "name": "connection_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "title": "Connection Id"
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 50,
              "title": "Page Size"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/sheets/{connection_id}/spreadsheets/{sheet_id}/data": {
      "get": {
        "summary": "Get Sheet Data",
        "operationId": "get_sheet_data_sheets__connection_id__spreadsheets__sheet_id__data_get",
        "parameters": [
          {
            "name": "connection_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "title": "Connection Id"
            }
          },
          {
            "name": "sheet_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Sheet Id"
            }
          },
          {
            "name": "range",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "default": "A1:Z1000",
              "title": "Range"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/sheets/{connection_id}/refresh": {
      "post": {
        "summary": "Refresh Endpoint",
        "operationId": "refresh_endpoint_sheets__connection_id__refresh_post",
        "parameters": [
          {
            "name": "connection_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "title": "Connection Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/sheets/{connection_id}": {
      "delete": {
        "summary": "Revoke Connection",
        "operationId": "revoke_connection_sheets__connection_id__delete",
        "parameters": [
          {
            "name": "connection_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "title": "Connection Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/render-from-sheet": {
      "post": {
        "summary": "Render From Sheet",
        "operationId": "render_from_sheet_v1_render_from_sheet_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RenderFromSheetReq"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/sheets/status": {
      "get": {
        "summary": "Sheets Status",
        "operationId": "sheets_status_sheets_status_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/v1/whatsapp/send-document": {
      "post": {
        "tags": [
          "whatsapp"
        ],
        "summary": "Send Document",
        "description": "Envía PDF generado por Reportia al WhatsApp del cliente.\n\nCasos típicos:\n- Generar factura → mandar al WhatsApp del cliente con caption + link de pago.\n- Cotización → cliente la recibe en su chat y puede compartirla con su equipo.\n- Reporte semanal → tú lo recibes cada lunes en tu WA, sin abrir email.",
        "operationId": "send_document_v1_whatsapp_send_document_post",
        "parameters": [
          {
            "name": "authorization",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WhatsAppDoc"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Mensaje encolado en WhatsApp Cloud API",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Número o URL inválida"
          },
          "401": {
            "description": "API key Reportia inválida"
          },
          "503": {
            "description": "WhatsApp Cloud API no configurada en el servidor"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/whatsapp/send-text": {
      "post": {
        "tags": [
          "whatsapp"
        ],
        "summary": "Send Text",
        "description": "Mensaje de texto simple (utilidad para acompañar PDFs o follow-ups).",
        "operationId": "send_text_v1_whatsapp_send_text_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WhatsAppText"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/whatsapp/health": {
      "get": {
        "tags": [
          "whatsapp"
        ],
        "summary": "Wa Health",
        "operationId": "wa_health_v1_whatsapp_health_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/v1/builder/me": {
      "get": {
        "tags": [
          "builder"
        ],
        "summary": "Builder Me",
        "description": "Devuelve plan actual del usuario (cookie o Bearer). Para UI mostrar badge correcto.",
        "operationId": "builder_me_v1_builder_me_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/v1/builder/schemas": {
      "get": {
        "tags": [
          "builder"
        ],
        "summary": "List Schemas",
        "description": "Lista resumen de las 9 plantillas con icono/título/descripción.",
        "operationId": "list_schemas_v1_builder_schemas_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/v1/builder/schemas/full": {
      "get": {
        "tags": [
          "builder"
        ],
        "summary": "List Schemas Full",
        "description": "Devuelve el dict FORM_SCHEMAS completo (frontend lo usa para generar forms).",
        "operationId": "list_schemas_full_v1_builder_schemas_full_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/v1/builder/schemas/{slug}": {
      "get": {
        "tags": [
          "builder"
        ],
        "summary": "Get Schema",
        "operationId": "get_schema_v1_builder_schemas__slug__get",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Slug"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/builder/preview": {
      "post": {
        "tags": [
          "builder"
        ],
        "summary": "Preview Pdf",
        "description": "Genera PDF de preview. Free = con watermark sutil, paid = sin watermark.",
        "operationId": "preview_pdf_v1_builder_preview_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PreviewReq"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/builder/preview-html": {
      "post": {
        "tags": [
          "builder"
        ],
        "summary": "Preview Html",
        "description": "Devuelve HTML rendered (rápido para iframe). Free tier obtiene watermark CSS.",
        "operationId": "preview_html_v1_builder_preview_html_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PreviewReq"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/builder/custom-template": {
      "post": {
        "tags": [
          "builder"
        ],
        "summary": "Custom Template",
        "description": "Modo experto BLINDADO. Preview free con marca de agua. Sin marca = paid.\n\nBlindaje:\n- SandboxedEnvironment Jinja2 → bloquea __class__, __mro__, __subclasses__, __import__\n- url_fetcher restringido → bloquea file://, IPs internas, http://, schemes raros\n- Timeout 10s → corta loops infinitos o templates con DoS\n- Rate limit 30 req/min/IP en free",
        "operationId": "custom_template_v1_builder_custom_template_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomReq"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/builder/save-template": {
      "post": {
        "tags": [
          "builder"
        ],
        "summary": "Save Template",
        "operationId": "save_template_v1_builder_save_template_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SaveReq"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/builder/my-templates": {
      "get": {
        "tags": [
          "builder"
        ],
        "summary": "My Templates",
        "operationId": "my_templates_v1_builder_my_templates_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/v1/builder/ai-generate": {
      "post": {
        "tags": [
          "builder"
        ],
        "summary": "Ai Generate",
        "description": "Genera plantilla Jinja2 + data JSON usando LiteLLM gateway (gpt-4o-mini).\n\nREQUIERE registro previo con email+password (anti-abuso anónimo + lead capture).\nFree: 5 gen/día por cuenta. Paid: ilimitado.",
        "operationId": "ai_generate_v1_builder_ai_generate_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AIGenReq"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/builder/import-url": {
      "post": {
        "tags": [
          "builder"
        ],
        "summary": "Import Url",
        "description": "Importa template HTML/.txt desde URL pública HTTPS. Bloquea SSRF a IPs internas.",
        "operationId": "import_url_v1_builder_import_url_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/URLImportReq"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/builder/ai-usage": {
      "get": {
        "tags": [
          "builder"
        ],
        "summary": "Ai Usage",
        "description": "Dashboard de gasto IA acumulado (admin only). Visible para verificar costo real.",
        "operationId": "ai_usage_v1_builder_ai_usage_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/v1/builder/ai-signup": {
      "post": {
        "tags": [
          "builder"
        ],
        "summary": "Ai Signup",
        "description": "Registra usuario para usar AI generator. Devuelve token persistente.",
        "operationId": "ai_signup_v1_builder_ai_signup_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SignupReq"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/builder/ai-login": {
      "post": {
        "tags": [
          "builder"
        ],
        "summary": "Ai Login",
        "operationId": "ai_login_v1_builder_ai_login_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LoginReq"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/builder/ai-refine": {
      "post": {
        "tags": [
          "builder"
        ],
        "summary": "Ai Refine",
        "description": "Toma código actual + instrucción → devuelve código modificado.\n\nMisma auth + rate limit que /ai-generate. Cuenta como 1 generación contra el límite.",
        "operationId": "ai_refine_v1_builder_ai_refine_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AIRefineReq"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/builder/voice-prompt": {
      "post": {
        "tags": [
          "builder"
        ],
        "summary": "Voice Prompt",
        "description": "Recibe blob de audio, transcribe via Escribelo, usa texto como prompt\npara generar plantilla con la misma lógica de /ai-generate.\n\nDevuelve {html, data, transcribed_text, tokens, cost_usd}.\nMisma auth gate (X-Reportia-Token) que ai-generate.",
        "operationId": "voice_prompt_v1_builder_voice_prompt_post",
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/Body_voice_prompt_v1_builder_voice_prompt_post"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/publish": {
      "post": {
        "tags": [
          "published"
        ],
        "summary": "Publish Report",
        "operationId": "publish_report_v1_publish_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublishReq"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/publish/mine": {
      "get": {
        "tags": [
          "published"
        ],
        "summary": "List My Published",
        "operationId": "list_my_published_v1_publish_mine_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/v1/publish/{token}": {
      "delete": {
        "tags": [
          "published"
        ],
        "summary": "Delete Published",
        "operationId": "delete_published_v1_publish__token__delete",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Token"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/r/{token}": {
      "get": {
        "tags": [
          "published"
        ],
        "summary": "View Published",
        "operationId": "view_published_r__token__get",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Token"
            }
          },
          {
            "name": "pw",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 128,
              "default": "",
              "title": "Pw"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/r/{token}/render": {
      "get": {
        "tags": [
          "published"
        ],
        "summary": "Render Published",
        "description": "Render del reporte publicado en el formato pedido.",
        "operationId": "render_published_r__token__render_get",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Token"
            }
          },
          {
            "name": "fmt",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^(pdf|xlsx|csv|html|json|md|txt|png|docx|zip)$",
              "default": "html",
              "title": "Fmt"
            }
          },
          {
            "name": "pw",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 128,
              "default": "",
              "title": "Pw"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/data/upload": {
      "post": {
        "tags": [
          "data-upload"
        ],
        "summary": "Upload Data",
        "operationId": "upload_data_v1_data_upload_post",
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/Body_upload_data_v1_data_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"
                }
              }
            }
          }
        }
      }
    },
    "/v1/data/uploads": {
      "get": {
        "tags": [
          "data-upload"
        ],
        "summary": "List Uploads",
        "operationId": "list_uploads_v1_data_uploads_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/v1/data/uploads/{upload_id}": {
      "get": {
        "tags": [
          "data-upload"
        ],
        "summary": "Get Upload",
        "operationId": "get_upload_v1_data_uploads__upload_id__get",
        "parameters": [
          {
            "name": "upload_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "title": "Upload Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "data-upload"
        ],
        "summary": "Delete Upload",
        "operationId": "delete_upload_v1_data_uploads__upload_id__delete",
        "parameters": [
          {
            "name": "upload_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "title": "Upload Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/data-sources": {
      "get": {
        "tags": [
          "data-sources"
        ],
        "summary": "List Data Sources",
        "operationId": "list_data_sources_v1_data_sources_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "data-sources"
        ],
        "summary": "Create Data Source",
        "operationId": "create_data_source_v1_data_sources_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DataSourceCreateReq"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/data-sources/test": {
      "post": {
        "tags": [
          "data-sources"
        ],
        "summary": "Test Only",
        "operationId": "test_only_v1_data_sources_test_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DataSourceTestReq"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/data-sources/{ds_id}": {
      "get": {
        "tags": [
          "data-sources"
        ],
        "summary": "Get Data Source",
        "operationId": "get_data_source_v1_data_sources__ds_id__get",
        "parameters": [
          {
            "name": "ds_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "title": "Ds Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "data-sources"
        ],
        "summary": "Delete Data Source",
        "operationId": "delete_data_source_v1_data_sources__ds_id__delete",
        "parameters": [
          {
            "name": "ds_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "title": "Ds Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/data-sources/{ds_id}/query": {
      "post": {
        "tags": [
          "data-sources"
        ],
        "summary": "Run Query",
        "operationId": "run_query_v1_data_sources__ds_id__query_post",
        "parameters": [
          {
            "name": "ds_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "title": "Ds Id"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QueryReq"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/pricing": {
      "get": {
        "summary": "Pricing",
        "operationId": "pricing_pricing_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/v1/render": {
      "post": {
        "summary": "Render",
        "operationId": "render_v1_render_post",
        "parameters": [
          {
            "name": "download",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Download"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RenderReq"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Documento generado en el formato pedido (binario)",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Request inválido (formato no soportado, data faltante, template inválido, etc.)"
          },
          "401": {
            "description": "API key inválida o revocada"
          },
          "413": {
            "description": "Payload demasiado grande"
          },
          "422": {
            "description": "Validación de schema falló"
          },
          "429": {
            "description": "Rate limit alcanzado (free tier 50/mes o límite del plan)"
          },
          "500": {
            "description": "Error interno al renderizar"
          }
        }
      }
    },
    "/waitlist": {
      "post": {
        "summary": "Waitlist Signup",
        "description": "Captura email para early access. Compartido con tabla waitlist en vozalta_db.",
        "operationId": "waitlist_signup_waitlist_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WaitlistReq"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Email agregado al waitlist",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Email inválido o request malformado"
          },
          "422": {
            "description": "Validación de schema falló"
          },
          "500": {
            "description": "Error interno (DB)"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "AIGenReq": {
        "properties": {
          "prompt": {
            "type": "string",
            "maxLength": 500,
            "minLength": 10,
            "title": "Prompt"
          }
        },
        "type": "object",
        "required": [
          "prompt"
        ],
        "title": "AIGenReq"
      },
      "AIRefineReq": {
        "properties": {
          "code": {
            "type": "string",
            "maxLength": 1048576,
            "minLength": 10,
            "title": "Code"
          },
          "instruction": {
            "type": "string",
            "maxLength": 400,
            "minLength": 5,
            "title": "Instruction"
          },
          "is_partial": {
            "type": "boolean",
            "title": "Is Partial",
            "default": false
          }
        },
        "type": "object",
        "required": [
          "code",
          "instruction"
        ],
        "title": "AIRefineReq"
      },
      "Body_upload_data_v1_data_upload_post": {
        "properties": {
          "file": {
            "type": "string",
            "format": "binary",
            "title": "File"
          }
        },
        "type": "object",
        "required": [
          "file"
        ],
        "title": "Body_upload_data_v1_data_upload_post"
      },
      "Body_voice_prompt_v1_builder_voice_prompt_post": {
        "properties": {
          "audio": {
            "type": "string",
            "format": "binary",
            "title": "Audio"
          }
        },
        "type": "object",
        "required": [
          "audio"
        ],
        "title": "Body_voice_prompt_v1_builder_voice_prompt_post"
      },
      "CustomReq": {
        "properties": {
          "html": {
            "type": "string",
            "maxLength": 1048576,
            "title": "Html"
          },
          "data": {
            "type": "object",
            "title": "Data"
          },
          "format": {
            "type": "string",
            "pattern": "^(pdf|html)$",
            "title": "Format",
            "default": "pdf"
          }
        },
        "type": "object",
        "required": [
          "html"
        ],
        "title": "CustomReq"
      },
      "DataSourceCreateReq": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 120,
            "minLength": 1,
            "title": "Name"
          },
          "type": {
            "type": "string",
            "pattern": "^(postgres|mysql|rest)$",
            "title": "Type"
          },
          "config": {
            "type": "object",
            "title": "Config"
          },
          "test": {
            "type": "boolean",
            "title": "Test",
            "default": false
          }
        },
        "type": "object",
        "required": [
          "name",
          "type"
        ],
        "title": "DataSourceCreateReq"
      },
      "DataSourceTestReq": {
        "properties": {
          "type": {
            "type": "string",
            "pattern": "^(postgres|mysql|rest)$",
            "title": "Type"
          },
          "config": {
            "type": "object",
            "title": "Config"
          }
        },
        "type": "object",
        "required": [
          "type"
        ],
        "title": "DataSourceTestReq"
      },
      "HTTPValidationError": {
        "properties": {
          "detail": {
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array",
            "title": "Detail"
          }
        },
        "type": "object",
        "title": "HTTPValidationError"
      },
      "LoginReq": {
        "properties": {
          "email": {
            "type": "string",
            "title": "Email"
          },
          "password": {
            "type": "string",
            "title": "Password"
          }
        },
        "type": "object",
        "required": [
          "email",
          "password"
        ],
        "title": "LoginReq"
      },
      "PreviewReq": {
        "properties": {
          "template": {
            "type": "string",
            "maxLength": 80,
            "title": "Template"
          },
          "data": {
            "type": "object",
            "title": "Data"
          },
          "options": {
            "type": "object",
            "title": "Options"
          }
        },
        "type": "object",
        "required": [
          "template"
        ],
        "title": "PreviewReq"
      },
      "PublishReq": {
        "properties": {
          "title": {
            "type": "string",
            "maxLength": 200,
            "title": "Title",
            "default": ""
          },
          "template": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 80
              },
              {
                "type": "null"
              }
            ],
            "title": "Template"
          },
          "custom_html": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Custom Html"
          },
          "data": {
            "type": "object",
            "title": "Data"
          },
          "options": {
            "type": "object",
            "title": "Options"
          },
          "expires_in_days": {
            "type": "integer",
            "maximum": 365.0,
            "minimum": 1.0,
            "title": "Expires In Days",
            "default": 30
          },
          "password": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Password"
          },
          "allow_download": {
            "type": "boolean",
            "title": "Allow Download",
            "default": true
          }
        },
        "type": "object",
        "title": "PublishReq"
      },
      "QueryReq": {
        "properties": {
          "sql": {
            "type": "string",
            "maxLength": 20000,
            "minLength": 1,
            "title": "Sql"
          }
        },
        "type": "object",
        "required": [
          "sql"
        ],
        "title": "QueryReq"
      },
      "RenderFromSheetReq": {
        "properties": {
          "sheet_connection_id": {
            "type": "integer",
            "title": "Sheet Connection Id"
          },
          "spreadsheet_id": {
            "type": "string",
            "title": "Spreadsheet Id"
          },
          "range": {
            "type": "string",
            "title": "Range",
            "default": "A1:Z1000"
          },
          "template": {
            "type": "string",
            "title": "Template",
            "default": "default"
          },
          "format": {
            "type": "string",
            "pattern": "^(pdf|xlsx|csv|html)$",
            "title": "Format",
            "default": "pdf"
          },
          "title": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Title"
          },
          "columns": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Columns"
          }
        },
        "type": "object",
        "required": [
          "sheet_connection_id",
          "spreadsheet_id"
        ],
        "title": "RenderFromSheetReq"
      },
      "RenderReq": {
        "properties": {
          "template": {
            "type": "string",
            "title": "Template",
            "description": "ID del template o 'custom_html'",
            "default": "default"
          },
          "format": {
            "type": "string",
            "pattern": "^(pdf|xlsx|csv|html|json|md|markdown|txt|png|docx|zip)$",
            "title": "Format",
            "default": "pdf"
          },
          "data": {
            "type": "object",
            "title": "Data"
          },
          "options": {
            "type": "object",
            "title": "Options"
          },
          "custom_html": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 1048576
              },
              {
                "type": "null"
              }
            ],
            "title": "Custom Html"
          }
        },
        "type": "object",
        "title": "RenderReq"
      },
      "SaveReq": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 120,
            "minLength": 1,
            "title": "Name"
          },
          "html": {
            "type": "string",
            "maxLength": 1048576,
            "minLength": 10,
            "title": "Html"
          },
          "schema": {
            "type": "object",
            "title": "Schema"
          }
        },
        "type": "object",
        "required": [
          "name",
          "html"
        ],
        "title": "SaveReq"
      },
      "SignupReq": {
        "properties": {
          "email": {
            "type": "string",
            "maxLength": 255,
            "title": "Email"
          },
          "password": {
            "type": "string",
            "maxLength": 128,
            "minLength": 6,
            "title": "Password"
          }
        },
        "type": "object",
        "required": [
          "email",
          "password"
        ],
        "title": "SignupReq"
      },
      "URLImportReq": {
        "properties": {
          "url": {
            "type": "string",
            "maxLength": 2000,
            "title": "Url"
          }
        },
        "type": "object",
        "required": [
          "url"
        ],
        "title": "URLImportReq"
      },
      "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"
      },
      "WaitlistReq": {
        "properties": {
          "email": {
            "type": "string",
            "maxLength": 200,
            "title": "Email"
          },
          "source": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 120
              },
              {
                "type": "null"
              }
            ],
            "title": "Source"
          }
        },
        "type": "object",
        "required": [
          "email"
        ],
        "title": "WaitlistReq"
      },
      "WhatsAppDoc": {
        "properties": {
          "to": {
            "type": "string",
            "title": "To",
            "description": "Teléfono destino, E.164 o MX 10 dígitos"
          },
          "document_url": {
            "type": "string",
            "title": "Document Url",
            "description": "URL pública del PDF a enviar"
          },
          "filename": {
            "type": "string",
            "title": "Filename",
            "description": "Nombre que verá el cliente",
            "default": "documento.pdf"
          },
          "caption": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Caption",
            "description": "Mensaje que acompaña el documento (max 1024 chars)"
          }
        },
        "type": "object",
        "required": [
          "to",
          "document_url"
        ],
        "title": "WhatsAppDoc"
      },
      "WhatsAppText": {
        "properties": {
          "to": {
            "type": "string",
            "title": "To"
          },
          "body": {
            "type": "string",
            "maxLength": 4096,
            "title": "Body"
          }
        },
        "type": "object",
        "required": [
          "to",
          "body"
        ],
        "title": "WhatsAppText"
      }
    }
  }
}