{
  "openapi": "3.0.3",
  "info": {
    "title": "Atomicat API",
    "version": "1.0.0",
    "description": "API HTTPS de la cuenta para páginas, sitios, embudos, videos, productos, leads y webhooks.\n\nURL base: https://automation.atomicat-api.com/api/automation/v1\n\nEnvía Authorization: Bearer at_live_... en cada llamada excepto GET /openapi.json. Las claves se crean en la app de Atomicat, en Ajustes y luego Claves de API. La clave se muestra una sola vez.\n\nLas respuestas de lista y búsqueda son arreglos JSON. No hay un envoltorio { data: [] }.\n\nLímite: 5.000 solicitudes por clave cada 10 minutos. Otro límite de 60.000 solicitudes por IP cada 15 minutos aplica a todo el host.\n\nLos nombres de campos y rutas permanecen en inglés. Este documento no incluye la gestión de claves del propietario ni las rutas internas.",
    "contact": {
      "name": "Atomicat",
      "url": "https://atomicat.com.br"
    }
  },
  "servers": [
    {
      "url": "https://automation.atomicat-api.com/api/automation/v1",
      "description": "Producción"
    }
  ],
  "tags": [
    {
      "name": "Account",
      "description": "Identifica la clave y descarga esta especificación."
    },
    {
      "name": "Projects",
      "description": "Agrupa páginas, sitios, embudos y productos."
    },
    {
      "name": "Sites",
      "description": "Destinos de hosting para páginas publicadas."
    },
    {
      "name": "Pages",
      "description": "Crea, edita, publica y elimina páginas."
    },
    {
      "name": "Builder",
      "description": "Lee y edita el árbol del constructor."
    },
    {
      "name": "Quizzes",
      "description": "Páginas de quiz y registros de quiz."
    },
    {
      "name": "Funnels",
      "description": "Flujos ordenados de páginas."
    },
    {
      "name": "Videos",
      "description": "Lista videos y actualiza el reproductor."
    },
    {
      "name": "Products",
      "description": "Ofertas usadas en las páginas."
    },
    {
      "name": "Leads",
      "description": "Envíos de formularios y quizzes."
    },
    {
      "name": "Analytics",
      "description": "Conteos de la cuenta."
    },
    {
      "name": "Webhooks",
      "description": "Avisos HTTPS de eventos de la cuenta."
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "at_live",
        "description": "Clave creada en Ajustes de Atomicat. Envía la clave completa, incluido el prefijo at_live_. No envíes solo el prefijo."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error",
          "message"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Código estable, como invalid_request o page_not_found."
          },
          "message": {
            "type": "string",
            "description": "Explicación legible."
          }
        }
      },
      "Deleted": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "description": "true cuando la eliminación tuvo éxito."
          },
          "id": {
            "type": "string",
            "description": "Id del registro eliminado."
          },
          "deleted": {
            "type": "boolean",
            "description": "true cuando el registro se eliminó."
          }
        }
      },
      "Account": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Id de la cuenta."
          },
          "email": {
            "type": "string",
            "nullable": true,
            "description": "Email de la cuenta."
          },
          "name": {
            "type": "string",
            "description": "Nombre visible."
          },
          "plan": {
            "nullable": true,
            "description": "Nombre del plan cuando existe."
          },
          "workspace_id": {
            "type": "string",
            "description": "El mismo valor que id."
          }
        }
      },
      "Project": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Id del proyecto."
          },
          "name": {
            "type": "string",
            "description": "Nombre."
          },
          "description": {
            "type": "string",
            "nullable": true,
            "description": "Descripción."
          },
          "context": {
            "type": "string",
            "nullable": true,
            "description": "Brief de marca. Presente al crear y actualizar."
          },
          "active": {
            "type": "boolean",
            "description": "false cuando el proyecto está inactivo."
          },
          "created_at": {
            "type": "string",
            "nullable": true,
            "description": "Marca de tiempo ISO-8601."
          },
          "updated_at": {
            "type": "string",
            "nullable": true,
            "description": "Marca de tiempo ISO-8601."
          }
        }
      },
      "ProjectCreate": {
        "type": "object",
        "required": [
          "name",
          "description",
          "context"
        ],
        "example": {
          "name": "Spring campaign",
          "description": "Campaign assets for the spring launch across offers and traffic sources.",
          "context": "Spring campaign sells a 6-week fitness program for busy professionals. The brand voice is direct and encouraging. The offer is a starter kit plus one coaching call. Pages should speak to people who started short workouts and quit, explain the weekly plan and the support included, and state the refund window before the call to action."
        },
        "properties": {
          "name": {
            "type": "string",
            "description": "Nombre del proyecto.",
            "example": "Spring campaign"
          },
          "description": {
            "type": "string",
            "minLength": 50,
            "example": "Campaign assets for the spring launch across offers and traffic sources.",
            "description": "Al menos 50 caracteres."
          },
          "context": {
            "type": "string",
            "minLength": 200,
            "example": "Spring campaign sells a 6-week fitness program for busy professionals. The brand voice is direct and encouraging. The offer is a starter kit plus one coaching call. Pages should speak to people who started short workouts and quit, explain the weekly plan and the support included, and state the refund window before the call to action.",
            "description": "Al menos 200 caracteres sobre la marca y la oferta."
          }
        }
      },
      "ProjectUpdate": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Nuevo nombre."
          },
          "description": {
            "type": "string",
            "description": "Nueva descripción."
          },
          "context": {
            "type": "string",
            "description": "Nuevo brief."
          }
        }
      },
      "Site": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Id del sitio."
          },
          "name": {
            "type": "string",
            "description": "Nombre visible, a menudo el dominio."
          },
          "site_name": {
            "type": "string",
            "nullable": true,
            "description": "Nombre guardado en el sitio."
          },
          "domain": {
            "type": "string",
            "nullable": true,
            "description": "Dominio público."
          },
          "custom_domain": {
            "type": "string",
            "nullable": true,
            "description": "Dominio propio, si está conectado."
          },
          "atomic_domain": {
            "type": "string",
            "nullable": true,
            "description": "Dominio entregado por Atomicat."
          },
          "project_id": {
            "type": "string",
            "nullable": true,
            "description": "Id del proyecto."
          },
          "status": {
            "type": "string",
            "nullable": true,
            "description": "Estado del sitio cuando existe."
          },
          "created_at": {
            "type": "string",
            "nullable": true,
            "description": "Marca de tiempo ISO-8601."
          },
          "updated_at": {
            "type": "string",
            "nullable": true,
            "description": "Marca de tiempo ISO-8601."
          }
        }
      },
      "SiteCreated": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Id del sitio."
          },
          "site_id": {
            "type": "string",
            "description": "El mismo valor que id."
          },
          "name": {
            "type": "string",
            "nullable": true,
            "description": "Nombre del sitio."
          },
          "atomic_domain": {
            "type": "string",
            "nullable": true,
            "description": "Dominio de Atomicat."
          },
          "url": {
            "type": "string",
            "nullable": true,
            "description": "URL pública."
          },
          "project_id": {
            "type": "string",
            "nullable": true,
            "description": "Id del proyecto."
          },
          "custom_domain_instructions": {
            "nullable": true,
            "description": "Instrucciones DNS del dominio propio, cuando se devuelven."
          }
        }
      },
      "SiteCreate": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Nombre del sitio."
          },
          "description": {
            "type": "string",
            "description": "Descripción."
          },
          "project_id": {
            "type": "string",
            "description": "Proyecto al que se une el sitio."
          }
        }
      },
      "Page": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Id de la página."
          },
          "name": {
            "type": "string",
            "description": "Nombre visible. Incluye el sitio entre paréntesis cuando la página está en un sitio."
          },
          "page_name": {
            "type": "string",
            "description": "Nombre sin el sufijo del sitio."
          },
          "status": {
            "type": "string",
            "description": "published o draft."
          },
          "is_quiz": {
            "type": "boolean",
            "description": "true cuando la página es un quiz."
          },
          "project_id": {
            "type": "string",
            "nullable": true,
            "description": "Id del proyecto."
          },
          "site_id": {
            "type": "string",
            "nullable": true,
            "description": "Id del sitio cuando la página está unida a un sitio."
          },
          "site_name": {
            "type": "string",
            "nullable": true,
            "description": "Nombre del sitio."
          },
          "domain": {
            "type": "string",
            "nullable": true,
            "description": "Dominio publicado."
          },
          "slug": {
            "type": "string",
            "nullable": true,
            "description": "Ruta en el sitio. Vacío significa la raíz."
          },
          "url": {
            "type": "string",
            "nullable": true,
            "description": "URL pública después de publicar."
          },
          "edit_url": {
            "type": "string",
            "description": "Enlace a la página en el constructor."
          },
          "created_at": {
            "type": "string",
            "nullable": true,
            "description": "Marca de tiempo ISO-8601."
          },
          "updated_at": {
            "type": "string",
            "nullable": true,
            "description": "Marca de tiempo ISO-8601."
          },
          "published_at": {
            "type": "string",
            "nullable": true,
            "description": "Hora de publicación ISO-8601."
          }
        }
      },
      "PageCreate": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Nombre de la página."
          },
          "project_id": {
            "type": "string",
            "description": "Id del proyecto."
          }
        }
      },
      "PageFromTemplate": {
        "type": "object",
        "required": [
          "template_id"
        ],
        "properties": {
          "template_id": {
            "type": "string",
            "description": "Id de plantilla de GET /templates."
          },
          "name": {
            "type": "string",
            "description": "Nombre de la página nueva."
          },
          "site_id": {
            "type": "string",
            "description": "Sitio al que unirla, si aplica."
          },
          "project_id": {
            "type": "string",
            "description": "Id del proyecto."
          }
        }
      },
      "PageDuplicate": {
        "type": "object",
        "required": [
          "page_id"
        ],
        "properties": {
          "page_id": {
            "type": "string",
            "description": "Página a copiar."
          },
          "new_name": {
            "type": "string",
            "description": "Nombre de la copia."
          }
        }
      },
      "PageDuplicateResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Id de la página nueva."
          },
          "name": {
            "type": "string",
            "description": "Nombre nuevo."
          },
          "page_name": {
            "type": "string",
            "description": "Nombre nuevo."
          },
          "source_page_id": {
            "type": "string",
            "description": "Id de la página copiada."
          },
          "edit_url": {
            "type": "string",
            "description": "URL del constructor."
          }
        }
      },
      "PageMetadata": {
        "type": "object",
        "required": [
          "page_id"
        ],
        "properties": {
          "page_id": {
            "type": "string",
            "description": "Id de la página."
          },
          "name": {
            "type": "string",
            "description": "Nuevo nombre."
          },
          "project_id": {
            "type": "string",
            "description": "Nuevo id de proyecto."
          },
          "tags": {
            "description": "Arreglo de etiquetas, o texto separado por comas."
          },
          "product_label": {
            "type": "string",
            "description": "Etiqueta de producto. produkt se acepta como alias."
          }
        }
      },
      "PageMetadataResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Id de la página."
          },
          "page_id": {
            "type": "string",
            "description": "Id de la página."
          },
          "updated": {
            "type": "boolean",
            "description": "true cuando se guardó."
          },
          "name": {
            "type": "string",
            "nullable": true,
            "description": "Nombre después de la actualización."
          },
          "project_id": {
            "type": "string",
            "nullable": true,
            "description": "Id de proyecto después de la actualización."
          },
          "tags": {
            "nullable": true,
            "description": "Etiquetas después de la actualización."
          },
          "product_label": {
            "type": "string",
            "nullable": true,
            "description": "Etiqueta después de la actualización."
          }
        }
      },
      "PageIdBody": {
        "type": "object",
        "required": [
          "page_id"
        ],
        "properties": {
          "page_id": {
            "type": "string",
            "description": "Id de la página."
          }
        }
      },
      "PageContentUpdate": {
        "type": "object",
        "required": [
          "page_id",
          "updates"
        ],
        "properties": {
          "page_id": {
            "type": "string",
            "description": "Id de la página."
          },
          "updates": {
            "type": "object",
            "additionalProperties": true,
            "description": "Mapa de claves de contenido a valores nuevos. También se acepta un string JSON."
          }
        }
      },
      "PageContentResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Id de la página."
          },
          "page_id": {
            "type": "string",
            "description": "Id de la página."
          },
          "success": {
            "type": "boolean",
            "description": "true cuando la solicitud terminó."
          },
          "applied_count": {
            "type": "number",
            "description": "Cantidad de campos actualizados."
          },
          "changed_section_count": {
            "type": "number",
            "description": "Cantidad de secciones reescritas."
          },
          "missing_count": {
            "type": "number",
            "description": "Cantidad de claves no encontradas."
          },
          "applied": {
            "type": "string",
            "description": "Texto JSON de las actualizaciones aplicadas."
          },
          "missing": {
            "type": "string",
            "description": "Texto JSON de las claves no aplicadas."
          }
        }
      },
      "PageVariables": {
        "type": "object",
        "required": [
          "page_id",
          "variables"
        ],
        "properties": {
          "page_id": {
            "type": "string",
            "description": "Id de la página."
          },
          "variables": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Nombre del marcador al texto. También se acepta un string JSON."
          }
        }
      },
      "PageVariablesResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Id de la página."
          },
          "page_id": {
            "type": "string",
            "description": "Id de la página."
          },
          "success": {
            "type": "boolean",
            "description": "true cuando terminó."
          },
          "replacement_count": {
            "type": "number",
            "description": "Cantidad de reemplazos."
          },
          "changed_section_count": {
            "type": "number",
            "description": "Secciones reescritas."
          },
          "replaced_variables": {
            "type": "string",
            "description": "Texto JSON de las variables reemplazadas."
          },
          "remaining_variables": {
            "type": "string",
            "description": "Texto JSON de las variables que siguen en la página."
          },
          "remaining_variable_count": {
            "type": "number",
            "description": "Cantidad de variables restantes."
          }
        }
      },
      "PageValidation": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Id de la página."
          },
          "page_id": {
            "type": "string",
            "description": "Id de la página."
          },
          "ready_to_publish": {
            "type": "boolean",
            "description": "true cuando no hay problemas."
          },
          "issue_count": {
            "type": "number",
            "description": "Cantidad de problemas."
          },
          "issues": {
            "type": "string",
            "description": "Texto JSON de los problemas."
          },
          "field_count": {
            "type": "number",
            "description": "Cantidad de campos editables."
          },
          "remaining_variable_count": {
            "type": "number",
            "description": "Variables que siguen en la página."
          },
          "remaining_variables": {
            "type": "string",
            "description": "Texto JSON de las variables restantes."
          }
        }
      },
      "PagePublish": {
        "type": "object",
        "required": [
          "page_id",
          "site_id"
        ],
        "properties": {
          "page_id": {
            "type": "string",
            "description": "Id de la página."
          },
          "site_id": {
            "type": "string",
            "description": "Sitio que hospedará la página."
          },
          "slug": {
            "type": "string",
            "description": "Ruta en el sitio. Omite o envía vacío para la raíz."
          }
        }
      },
      "PagePublishResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Id de la página."
          },
          "page_id": {
            "type": "string",
            "description": "Id de la página."
          },
          "site_id": {
            "type": "string",
            "description": "Id del sitio."
          },
          "success": {
            "type": "boolean",
            "description": "true cuando la publicación tuvo éxito."
          },
          "url": {
            "type": "string",
            "nullable": true,
            "description": "URL pública."
          },
          "domain": {
            "type": "string",
            "nullable": true,
            "description": "Dominio publicado."
          },
          "slug": {
            "type": "string",
            "description": "Ruta publicada."
          },
          "revision_saved": {
            "type": "boolean",
            "description": "true cuando se guardó una revisión."
          },
          "revision_warning": {
            "type": "string",
            "nullable": true,
            "description": "Aviso si la revisión no se pudo guardar."
          }
        }
      },
      "PageDelay": {
        "type": "object",
        "required": [
          "page_id"
        ],
        "properties": {
          "page_id": {
            "type": "string",
            "description": "Id de la página."
          },
          "time": {
            "type": "number",
            "description": "Retraso en segundos."
          },
          "sync_with_video": {
            "type": "boolean",
            "description": "Mostrar en sincronía con un video."
          },
          "scroll_into_view": {
            "type": "boolean",
            "description": "Desplazar la sección a la vista."
          },
          "video_node_id": {
            "type": "string",
            "description": "Id del nodo de video."
          }
        }
      },
      "PageDelayResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Id de la página."
          },
          "page_id": {
            "type": "string",
            "description": "Id de la página."
          },
          "updated": {
            "type": "boolean",
            "description": "true cuando se guardó."
          },
          "delay": {
            "type": "object",
            "additionalProperties": true,
            "description": "Ajustes de retraso guardados."
          }
        }
      },
      "BuilderSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Id de la página."
          },
          "page_id": {
            "type": "string",
            "description": "Id de la página."
          },
          "builder": {
            "type": "object",
            "additionalProperties": true,
            "description": "Resumen del constructor, con el árbol si include_tree es true."
          }
        }
      },
      "BuilderNode": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Id del nodo."
          },
          "page_id": {
            "type": "string",
            "description": "Id de la página."
          },
          "node_id": {
            "type": "string",
            "description": "Id del nodo."
          },
          "path": {
            "type": "string",
            "nullable": true,
            "description": "Ubicación del nodo en el árbol."
          },
          "summary": {
            "nullable": true,
            "description": "Resumen corto cuando el constructor lo devuelve."
          },
          "node": {
            "type": "object",
            "additionalProperties": true,
            "description": "El objeto del nodo."
          }
        }
      },
      "BuilderNodeFields": {
        "type": "object",
        "required": [
          "page_id",
          "node_id",
          "updates"
        ],
        "properties": {
          "page_id": {
            "type": "string",
            "description": "Id de la página."
          },
          "node_id": {
            "type": "string",
            "description": "Id del nodo."
          },
          "node_type": {
            "type": "string",
            "description": "Tipo de nodo opcional."
          },
          "updates": {
            "type": "object",
            "description": "Debe incluir misc, style o ambos.",
            "properties": {
              "misc": {
                "type": "object",
                "additionalProperties": true
              },
              "style": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        }
      },
      "BuilderNodeUpdate": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Id del nodo."
          },
          "page_id": {
            "type": "string",
            "description": "Id de la página."
          },
          "node_id": {
            "type": "string",
            "description": "Id del nodo."
          },
          "updated": {
            "type": "boolean",
            "description": "true cuando se guardó."
          },
          "path": {
            "type": "string",
            "nullable": true,
            "description": "Ruta del nodo."
          }
        }
      },
      "BuilderNodeReplace": {
        "type": "object",
        "required": [
          "page_id",
          "node_id",
          "node"
        ],
        "properties": {
          "page_id": {
            "type": "string",
            "description": "Id de la página."
          },
          "node_id": {
            "type": "string",
            "description": "Id del nodo a reemplazar."
          },
          "node": {
            "type": "object",
            "additionalProperties": true,
            "description": "Nodo completo de reemplazo. También se acepta un string JSON."
          }
        }
      },
      "BuilderNodeReplaceResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Id del nodo."
          },
          "page_id": {
            "type": "string",
            "description": "Id de la página."
          },
          "node_id": {
            "type": "string",
            "description": "Id del nodo."
          },
          "updated": {
            "type": "boolean",
            "description": "true cuando se reemplazó."
          },
          "path": {
            "type": "string",
            "nullable": true,
            "description": "Ruta del nodo."
          },
          "builder_warnings": {
            "type": "string",
            "description": "Texto JSON de advertencias."
          }
        }
      },
      "ContentMap": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "nullable": true,
            "description": "Id de la página."
          },
          "page_id": {
            "type": "string",
            "nullable": true,
            "description": "Id de la página."
          },
          "page_name": {
            "type": "string",
            "nullable": true,
            "description": "Nombre de la página."
          },
          "field_count": {
            "type": "number",
            "description": "Cantidad de campos editables."
          },
          "variable_count": {
            "type": "number",
            "description": "Cantidad de variables."
          },
          "variables": {
            "type": "string",
            "description": "Texto JSON de los nombres de variables."
          },
          "fields": {
            "type": "string",
            "description": "Texto JSON de los campos editables."
          },
          "ready_for_variable_replacement": {
            "type": "boolean",
            "description": "true cuando la página todavía tiene variables."
          }
        }
      },
      "Template": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Id de la plantilla."
          },
          "name": {
            "type": "string",
            "description": "Nombre."
          },
          "template_name": {
            "type": "string",
            "description": "Igual que name."
          },
          "category": {
            "type": "string",
            "nullable": true,
            "description": "Categoría."
          },
          "type": {
            "type": "string",
            "description": "Tipo, normalmente page."
          },
          "description": {
            "type": "string",
            "nullable": true,
            "description": "Descripción."
          },
          "preview_url": {
            "type": "string",
            "nullable": true,
            "description": "URL de vista previa."
          },
          "image_url": {
            "type": "string",
            "nullable": true,
            "description": "URL de la miniatura."
          }
        }
      },
      "Quiz": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Id del quiz (qid)."
          },
          "name": {
            "type": "string",
            "description": "Nombre visible, con el nombre de la página si se conoce."
          },
          "quiz_name": {
            "type": "string",
            "description": "Nombre del quiz."
          },
          "page_id": {
            "type": "string",
            "nullable": true,
            "description": "Página que hospeda el quiz."
          },
          "page_name": {
            "type": "string",
            "nullable": true,
            "description": "Nombre de la página."
          },
          "site_id": {
            "type": "string",
            "nullable": true,
            "description": "Id del sitio."
          },
          "project_id": {
            "type": "string",
            "nullable": true,
            "description": "Id del proyecto."
          },
          "created_at": {
            "type": "string",
            "nullable": true,
            "description": "Marca de tiempo ISO-8601."
          },
          "updated_at": {
            "type": "string",
            "nullable": true,
            "description": "Marca de tiempo ISO-8601."
          }
        }
      },
      "QuizPage": {
        "type": "object",
        "description": "Una página de quiz recién creada. id es el id de la página. Los listados posteriores devuelven el qid, que puede ser distinto.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Id de la página."
          },
          "quiz_id": {
            "type": "string",
            "description": "Igual que id al crear."
          },
          "is_quiz": {
            "type": "boolean",
            "description": "Siempre true."
          },
          "name": {
            "type": "string",
            "description": "Nombre."
          },
          "page_name": {
            "type": "string",
            "description": "Nombre."
          },
          "project_id": {
            "type": "string",
            "nullable": true,
            "description": "Id del proyecto."
          },
          "site_id": {
            "type": "string",
            "nullable": true,
            "description": "Id del sitio."
          },
          "edit_url": {
            "type": "string",
            "description": "URL del constructor."
          }
        }
      },
      "QuizCreate": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Nombre de la página de quiz."
          },
          "project_id": {
            "type": "string",
            "description": "Id del proyecto."
          },
          "site_id": {
            "type": "string",
            "description": "Id del sitio."
          }
        }
      },
      "Funnel": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Id del embudo."
          },
          "name": {
            "type": "string",
            "description": "Nombre."
          },
          "site_id": {
            "type": "string",
            "nullable": true,
            "description": "Id del sitio."
          },
          "project_id": {
            "type": "string",
            "nullable": true,
            "description": "Id del proyecto."
          },
          "status": {
            "type": "string",
            "nullable": true,
            "description": "Estado."
          },
          "pages": {
            "type": "array",
            "items": {},
            "description": "Ids de página o pasos guardados en el embudo."
          },
          "page_ids": {
            "type": "string",
            "description": "Ids separados por comas cuando pages es un arreglo de ids."
          },
          "steps": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Pasos cuando el embudo los guarda."
          },
          "created_at": {
            "type": "string",
            "nullable": true,
            "description": "Marca de tiempo ISO-8601."
          },
          "updated_at": {
            "type": "string",
            "nullable": true,
            "description": "Marca de tiempo ISO-8601."
          }
        }
      },
      "FunnelPage": {
        "type": "object",
        "properties": {
          "pageId": {
            "type": "string",
            "description": "Id de una página existente."
          },
          "url": {
            "type": "string",
            "description": "URL externa, cuando no hay pageId."
          },
          "pageType": {
            "type": "string",
            "description": "Tipo de paso, como presell, sales o thankyou."
          }
        }
      },
      "FunnelCreate": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Nombre del embudo."
          },
          "project_id": {
            "type": "string",
            "description": "Id del proyecto."
          },
          "pages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FunnelPage"
            },
            "description": "Pasos. Cada uno necesita pageId o url."
          }
        }
      },
      "FunnelUpdate": {
        "type": "object",
        "required": [
          "funnel_id"
        ],
        "properties": {
          "funnel_id": {
            "type": "string",
            "description": "Id del embudo."
          },
          "name": {
            "type": "string",
            "description": "Nuevo nombre."
          },
          "pages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FunnelPage"
            }
          }
        }
      },
      "Video": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "nullable": true,
            "description": "Id del video."
          },
          "video_id": {
            "type": "string",
            "nullable": true,
            "description": "Igual que id."
          },
          "name": {
            "type": "string",
            "nullable": true,
            "description": "Nombre."
          },
          "title": {
            "type": "string",
            "nullable": true,
            "description": "Título del reproductor."
          },
          "status": {
            "type": "string",
            "nullable": true,
            "description": "Estado de codificación o reproducción."
          },
          "duration": {
            "nullable": true,
            "description": "Duración en segundos cuando el reproductor la devuelve."
          },
          "thumbnail_url": {
            "type": "string",
            "nullable": true,
            "description": "URL de la miniatura."
          },
          "project_id": {
            "type": "string",
            "nullable": true,
            "description": "Id del proyecto."
          },
          "created_at": {
            "type": "string",
            "nullable": true,
            "description": "Fecha de creación."
          },
          "updated_at": {
            "type": "string",
            "nullable": true,
            "description": "Fecha de actualización."
          }
        }
      },
      "VideoUpdate": {
        "type": "object",
        "required": [
          "video_id"
        ],
        "properties": {
          "video_id": {
            "type": "string",
            "description": "Id del video."
          },
          "name": {
            "type": "string",
            "description": "Nombre en la biblioteca."
          },
          "title": {
            "type": "string",
            "description": "Título del reproductor."
          },
          "language": {
            "type": "string",
            "description": "Idioma del reproductor."
          },
          "project_id": {
            "type": "string",
            "description": "Id del proyecto."
          },
          "primary_color": {
            "type": "string",
            "description": "Color de acento del reproductor."
          },
          "controls": {
            "type": "boolean",
            "description": "Mostrar controles."
          },
          "autoplay": {
            "type": "boolean",
            "description": "Iniciar reproducción automáticamente."
          },
          "muted": {
            "type": "boolean",
            "description": "Iniciar silenciado."
          },
          "loop": {
            "type": "boolean",
            "description": "Repetir la reproducción."
          }
        }
      },
      "Product": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Id del producto."
          },
          "name": {
            "type": "string",
            "description": "Nombre."
          },
          "type": {
            "type": "string",
            "description": "simple o bundle."
          },
          "sku": {
            "type": "string",
            "nullable": true,
            "description": "SKU."
          },
          "description": {
            "type": "string",
            "nullable": true,
            "description": "Descripción."
          },
          "image": {
            "type": "string",
            "nullable": true,
            "description": "URL de la imagen."
          },
          "show_full_product": {
            "type": "boolean",
            "description": "Mostrar el bloque completo del producto."
          },
          "price": {
            "type": "number",
            "description": "Precio."
          },
          "compare_price": {
            "type": "number",
            "description": "Precio de comparación."
          },
          "rating": {
            "type": "string",
            "nullable": true,
            "description": "Etiqueta de valoración."
          },
          "rating_count": {
            "type": "string",
            "nullable": true,
            "description": "Etiqueta de cantidad de valoraciones."
          },
          "project_id": {
            "type": "string",
            "nullable": true,
            "description": "Id del proyecto."
          },
          "cta_text": {
            "type": "string",
            "nullable": true,
            "description": "Texto del botón."
          },
          "cta_url": {
            "type": "string",
            "nullable": true,
            "description": "URL del botón."
          },
          "cta_target": {
            "type": "boolean",
            "description": "Abrir la URL en una pestaña nueva."
          },
          "use_single_cta_link": {
            "type": "boolean",
            "description": "Usar un solo enlace de llamada a la acción."
          },
          "bundle_discount": {
            "type": "number",
            "description": "Descuento del bundle."
          },
          "bundle_item_count": {
            "type": "number",
            "description": "Cantidad de ítems del bundle."
          },
          "tiers_enabled": {
            "type": "boolean",
            "description": "Los niveles de cantidad están activos."
          },
          "subscription_enabled": {
            "type": "boolean",
            "description": "La opción de suscripción está activa."
          },
          "created_at": {
            "type": "string",
            "nullable": true,
            "description": "Marca de tiempo ISO-8601."
          },
          "updated_at": {
            "type": "string",
            "nullable": true,
            "description": "Marca de tiempo ISO-8601."
          }
        }
      },
      "ProductWrite": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Nombre."
          },
          "type": {
            "type": "string",
            "enum": [
              "simple",
              "bundle"
            ],
            "description": "Predeterminado simple."
          },
          "project_id": {
            "type": "string",
            "description": "Id del proyecto."
          },
          "sku": {
            "type": "string",
            "description": "SKU."
          },
          "description": {
            "type": "string",
            "description": "Descripción."
          },
          "image": {
            "type": "string",
            "description": "URL de la imagen."
          },
          "price": {
            "type": "number",
            "description": "Precio."
          },
          "compare_price": {
            "type": "number",
            "description": "Precio de comparación."
          },
          "cta_text": {
            "type": "string",
            "description": "Texto del botón."
          },
          "cta_url": {
            "type": "string",
            "description": "URL del botón."
          },
          "show_full_product": {
            "type": "boolean",
            "description": "Mostrar el bloque completo."
          },
          "cta_target": {
            "type": "boolean",
            "description": "Abrir la URL en una pestaña nueva."
          },
          "use_single_cta_link": {
            "type": "boolean",
            "description": "Usar un solo enlace."
          },
          "rating": {
            "type": "string",
            "description": "Etiqueta de valoración. Predeterminado 4.9 si se envía vacío."
          },
          "rating_count": {
            "type": "string",
            "description": "Etiqueta de cantidad."
          },
          "trust_badges_json": {
            "description": "Arreglo de etiquetas, o un string JSON."
          },
          "variants_json": {
            "description": "Arreglo de { id, name, image }, o un string JSON."
          },
          "tiers_enabled": {
            "type": "boolean",
            "description": "Activar niveles de cantidad."
          },
          "tiers_json": {
            "description": "Objetos de nivel, o un string JSON."
          },
          "bundle_items_json": {
            "description": "Obligatorio cuando type es bundle."
          },
          "bundle_discount": {
            "type": "number",
            "description": "Descuento del bundle."
          },
          "subscription_json": {
            "description": "Objeto con enabled, discountPercent y benefits."
          }
        }
      },
      "ProductUpdate": {
        "type": "object",
        "required": [
          "product_id"
        ],
        "properties": {
          "product_id": {
            "type": "string",
            "description": "Id del producto."
          },
          "name": {
            "type": "string",
            "description": "Nuevo nombre."
          },
          "type": {
            "type": "string",
            "enum": [
              "simple",
              "bundle"
            ]
          },
          "sku": {
            "type": "string",
            "description": "SKU."
          },
          "description": {
            "type": "string",
            "description": "Descripción."
          },
          "image": {
            "type": "string",
            "description": "URL de la imagen."
          },
          "price": {
            "type": "number",
            "description": "Precio."
          },
          "compare_price": {
            "type": "number",
            "description": "Precio de comparación."
          },
          "project_id": {
            "type": "string",
            "description": "Id del proyecto."
          },
          "cta_text": {
            "type": "string",
            "description": "Texto del botón."
          },
          "cta_url": {
            "type": "string",
            "description": "URL del botón."
          },
          "show_full_product": {
            "type": "boolean",
            "description": "Mostrar el bloque completo."
          },
          "cta_target": {
            "type": "boolean",
            "description": "Abrir en una pestaña nueva."
          },
          "use_single_cta_link": {
            "type": "boolean",
            "description": "Usar un solo enlace."
          },
          "rating": {
            "type": "string",
            "description": "Etiqueta de valoración."
          },
          "rating_count": {
            "type": "string",
            "description": "Etiqueta de cantidad."
          },
          "trust_badges_json": {
            "description": "Etiquetas."
          },
          "variants_json": {
            "description": "Objetos de variante."
          },
          "tiers_enabled": {
            "type": "boolean",
            "description": "Activar niveles."
          },
          "tiers_json": {
            "description": "Objetos de nivel."
          },
          "bundle_items_json": {
            "description": "Ítems del bundle."
          },
          "bundle_discount": {
            "type": "number",
            "description": "Descuento."
          },
          "subscription_json": {
            "description": "Ajustes de suscripción."
          }
        }
      },
      "Lead": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Id del lead."
          },
          "lead_id": {
            "type": "string",
            "description": "Igual que id."
          },
          "type": {
            "type": "string",
            "description": "form o quiz."
          },
          "name": {
            "type": "string",
            "nullable": true,
            "description": "Nombre."
          },
          "first_name": {
            "type": "string",
            "nullable": true,
            "description": "Nombre."
          },
          "last_name": {
            "type": "string",
            "nullable": true,
            "description": "Apellido."
          },
          "email": {
            "type": "string",
            "nullable": true,
            "description": "Email."
          },
          "phone": {
            "type": "string",
            "nullable": true,
            "description": "Teléfono."
          },
          "form_id": {
            "type": "string",
            "nullable": true,
            "description": "Id del formulario. Presente en leads de formulario."
          },
          "form_name": {
            "type": "string",
            "nullable": true,
            "description": "Nombre del formulario."
          },
          "quiz_id": {
            "type": "string",
            "nullable": true,
            "description": "Id del quiz. Presente en leads de quiz."
          },
          "quiz_name": {
            "type": "string",
            "nullable": true,
            "description": "Nombre del quiz."
          },
          "page_id": {
            "type": "string",
            "nullable": true,
            "description": "Id de la página."
          },
          "page_url": {
            "type": "string",
            "nullable": true,
            "description": "URL de la página."
          },
          "project_id": {
            "type": "string",
            "nullable": true,
            "description": "Id del proyecto."
          },
          "site_id": {
            "type": "string",
            "nullable": true,
            "description": "Id del sitio."
          },
          "abandoned": {
            "type": "boolean",
            "description": "true cuando un lead de formulario fue abandonado."
          },
          "is_completed": {
            "type": "boolean",
            "description": "Presente en leads de quiz."
          },
          "fields": {
            "type": "object",
            "additionalProperties": true,
            "description": "Campos crudos del formulario."
          },
          "answers": {
            "type": "object",
            "additionalProperties": true,
            "description": "Respuestas crudas del quiz."
          },
          "created_at": {
            "type": "string",
            "nullable": true,
            "description": "Marca de tiempo ISO-8601."
          }
        }
      },
      "Analytics": {
        "type": "object",
        "properties": {
          "pages": {
            "type": "number",
            "description": "Cantidad de páginas."
          },
          "sites": {
            "type": "number",
            "description": "Cantidad de sitios."
          },
          "funnels": {
            "type": "number",
            "description": "Cantidad de embudos."
          },
          "products": {
            "type": "number",
            "description": "Cantidad de productos."
          },
          "projects": {
            "type": "number",
            "description": "Cantidad de proyectos."
          },
          "form_leads": {
            "type": "number",
            "description": "Cantidad de leads de formulario."
          },
          "quiz_leads": {
            "type": "number",
            "description": "Cantidad de leads de quiz."
          }
        }
      },
      "HookCreate": {
        "type": "object",
        "required": [
          "target_url",
          "event_type"
        ],
        "properties": {
          "target_url": {
            "type": "string",
            "format": "uri",
            "description": "URL HTTPS pública que recibe el evento."
          },
          "event_type": {
            "type": "string",
            "enum": [
              "form_lead.created",
              "quiz_lead.created",
              "page.published",
              "page.created",
              "product.created",
              "funnel.created",
              "site.created",
              "project.created"
            ],
            "description": "Evento al que suscribirse."
          },
          "filters": {
            "type": "object",
            "additionalProperties": true,
            "description": "Objeto de filtro opcional guardado con la suscripción."
          }
        }
      },
      "HookSubscription": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Id de la suscripción. Envíalo a DELETE /hooks/{subscriptionId}."
          },
          "event_type": {
            "type": "string",
            "description": "Evento suscrito."
          },
          "active": {
            "type": "boolean",
            "description": "true hasta que se desactiva."
          },
          "created_at": {
            "type": "string",
            "description": "Marca de tiempo ISO-8601."
          }
        }
      }
    }
  },
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/me": {
      "get": {
        "operationId": "getAccount",
        "tags": [
          "Account"
        ],
        "summary": "Obtener la cuenta autenticada",
        "description": "Devuelve la cuenta de Atomicat dueña de la clave. El id del espacio de trabajo es el mismo que el id de la cuenta.\n\nAlcance requerido: account:read.",
        "responses": {
          "200": {
            "description": "La cuenta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Account"
                },
                "example": {
                  "id": "user_123",
                  "email": "owner@example.com",
                  "name": "Ada Lovelace",
                  "plan": "pro",
                  "workspace_id": "user_123"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/openapi.json": {
      "get": {
        "operationId": "getOpenApiDocument",
        "tags": [
          "Account"
        ],
        "summary": "Descargar el documento OpenAPI",
        "description": "Documento público. No requiere clave. Es la misma especificación con la que se construye este sitio.",
        "responses": {
          "200": {
            "description": "JSON de OpenAPI 3.0.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/projects": {
      "get": {
        "operationId": "listProjects",
        "tags": [
          "Projects"
        ],
        "summary": "Listar proyectos",
        "description": "Los proyectos agrupan páginas, sitios, embudos y productos.\n\nAlcance requerido: projects:read.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "description": "Cantidad máxima de registros. El valor predeterminado es 50 y el máximo es 100."
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            },
            "description": "Índice de página que empieza en cero. La API devuelve limit registros a partir de page × limit."
          }
        ],
        "responses": {
          "200": {
            "description": "Registros coincidentes. El cuerpo es un arreglo JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Project"
                  }
                },
                "example": [
                  {
                    "id": "project_123",
                    "name": "Spring campaign",
                    "description": "Campaign assets for the spring launch across offers and traffic sources.",
                    "active": true,
                    "created_at": "2026-09-26T12:00:00.000Z",
                    "updated_at": "2026-09-26T12:00:00.000Z"
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      },
      "post": {
        "operationId": "createProject",
        "tags": [
          "Projects"
        ],
        "summary": "Crear un proyecto",
        "description": "name es obligatorio. description debe tener al menos 50 caracteres. context debe tener al menos 200 caracteres. Se requiere un plan de pago.\n\nAlcance requerido: projects:write.",
        "responses": {
          "201": {
            "description": "El proyecto creado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Project"
                },
                "example": {
                  "id": "project_123",
                  "name": "Spring campaign",
                  "description": "Campaign assets for the spring launch across offers and traffic sources.",
                  "active": true,
                  "created_at": "2026-09-26T12:00:00.000Z",
                  "updated_at": "2026-09-26T12:00:00.000Z",
                  "context": "Spring campaign sells a 6-week fitness program for busy professionals. The brand voice is direct and encouraging. The offer is a starter kit plus one coaching call. Pages should speak to people who started short workouts and quit, explain the weekly plan and the support included, and state the refund window before the call to action."
                }
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProjectCreate"
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/search/projects": {
      "get": {
        "operationId": "searchProjects",
        "tags": [
          "Projects"
        ],
        "summary": "Buscar proyectos",
        "description": "Pasa project_id para uno, o query para nombre y descripción. Siempre devuelve un arreglo.\n\nAlcance requerido: projects:read.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "description": "Cantidad máxima de registros. El valor predeterminado es 50 y el máximo es 100."
          },
          {
            "name": "query",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Texto sin distinción de mayúsculas que se compara con el nombre y los campos relacionados."
          },
          {
            "name": "project_id",
            "in": "query",
            "required": false,
            "description": "Id exacto del proyecto.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Registros coincidentes. El cuerpo es un arreglo JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Project"
                  }
                },
                "example": [
                  {
                    "id": "project_123",
                    "name": "Spring campaign",
                    "description": "Campaign assets for the spring launch across offers and traffic sources.",
                    "active": true,
                    "created_at": "2026-09-26T12:00:00.000Z",
                    "updated_at": "2026-09-26T12:00:00.000Z"
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/projects/{projectId}": {
      "get": {
        "operationId": "getProject",
        "tags": [
          "Projects"
        ],
        "summary": "Obtener un proyecto",
        "description": "Alcance requerido: projects:read.",
        "parameters": [
          {
            "name": "projectId",
            "in": "path",
            "required": true,
            "description": "Id del proyecto.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "El proyecto.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Project"
                },
                "example": {
                  "id": "project_123",
                  "name": "Spring campaign",
                  "description": "Campaign assets for the spring launch across offers and traffic sources.",
                  "active": true,
                  "created_at": "2026-09-26T12:00:00.000Z",
                  "updated_at": "2026-09-26T12:00:00.000Z"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "El registro no existe o pertenece a otra cuenta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      },
      "patch": {
        "operationId": "updateProject",
        "tags": [
          "Projects"
        ],
        "summary": "Actualizar un proyecto",
        "description": "Envía solo los campos que quieres cambiar.\n\nAlcance requerido: projects:write.",
        "parameters": [
          {
            "name": "projectId",
            "in": "path",
            "required": true,
            "description": "Id del proyecto.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "El proyecto actualizado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Project"
                },
                "example": {
                  "id": "project_123",
                  "name": "Spring campaign",
                  "description": "Campaign assets for the spring launch across offers and traffic sources.",
                  "active": true,
                  "created_at": "2026-09-26T12:00:00.000Z",
                  "updated_at": "2026-09-26T12:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "El registro no existe o pertenece a otra cuenta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProjectUpdate"
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      },
      "delete": {
        "operationId": "deleteProject",
        "tags": [
          "Projects"
        ],
        "summary": "Eliminar un proyecto sin uso",
        "description": "Elimina el proyecto solo si ninguna página, producto, sitio o embudo lo referencia. Si no, responde 409 project_in_use.\n\nAlcance requerido: projects:write.",
        "parameters": [
          {
            "name": "projectId",
            "in": "path",
            "required": true,
            "description": "Id del proyecto.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "El registro fue eliminado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                },
                "example": {
                  "success": true,
                  "id": "record_123",
                  "deleted": true
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "El registro no existe o pertenece a otra cuenta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "El registro no se puede eliminar porque otros registros todavía lo usan.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/sites": {
      "get": {
        "operationId": "listSites",
        "tags": [
          "Sites"
        ],
        "summary": "Listar sitios",
        "description": "Un sitio es el host donde se publica una página. Esta API no elimina sitios.\n\nAlcance requerido: sites:read.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "description": "Cantidad máxima de registros. El valor predeterminado es 50 y el máximo es 100."
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            },
            "description": "Índice de página que empieza en cero. La API devuelve limit registros a partir de page × limit."
          },
          {
            "name": "project_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Solo registros de este proyecto."
          },
          {
            "name": "query",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Texto sin distinción de mayúsculas que se compara con el nombre y los campos relacionados."
          }
        ],
        "responses": {
          "200": {
            "description": "Registros coincidentes. El cuerpo es un arreglo JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Site"
                  }
                },
                "example": [
                  {
                    "id": "site_123",
                    "name": "example.com",
                    "site_name": "Main site",
                    "domain": "example.com",
                    "custom_domain": "example.com",
                    "atomic_domain": "main.atomicat.net",
                    "project_id": "project_123",
                    "status": null,
                    "created_at": "2026-09-26T12:00:00.000Z",
                    "updated_at": "2026-09-26T12:00:00.000Z"
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      },
      "post": {
        "operationId": "createSite",
        "tags": [
          "Sites"
        ],
        "summary": "Crear un sitio",
        "description": "Crea un sitio y devuelve su dominio de Atomicat. Incluye instrucciones de DNS del dominio propio cuando existen.\n\nAlcance requerido: sites:write.",
        "responses": {
          "201": {
            "description": "El sitio creado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SiteCreated"
                },
                "example": {
                  "id": "site_123",
                  "site_id": "site_123",
                  "name": "Main site",
                  "atomic_domain": "main.atomicat.net",
                  "url": "https://main.atomicat.net",
                  "project_id": "project_123",
                  "custom_domain_instructions": null
                }
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SiteCreate"
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/search/sites": {
      "get": {
        "operationId": "searchSites",
        "tags": [
          "Sites"
        ],
        "summary": "Buscar sitios",
        "description": "Alcance requerido: sites:read.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "description": "Cantidad máxima de registros. El valor predeterminado es 50 y el máximo es 100."
          },
          {
            "name": "query",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Texto sin distinción de mayúsculas que se compara con el nombre y los campos relacionados."
          },
          {
            "name": "project_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Solo registros de este proyecto."
          },
          {
            "name": "site_id",
            "in": "query",
            "required": false,
            "description": "Id exacto. Devuelve un arreglo de un elemento.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Registros coincidentes. El cuerpo es un arreglo JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Site"
                  }
                },
                "example": [
                  {
                    "id": "site_123",
                    "name": "example.com",
                    "site_name": "Main site",
                    "domain": "example.com",
                    "custom_domain": "example.com",
                    "atomic_domain": "main.atomicat.net",
                    "project_id": "project_123",
                    "status": null,
                    "created_at": "2026-09-26T12:00:00.000Z",
                    "updated_at": "2026-09-26T12:00:00.000Z"
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/sites/{siteId}": {
      "get": {
        "operationId": "getSite",
        "tags": [
          "Sites"
        ],
        "summary": "Obtener un sitio",
        "description": "Alcance requerido: sites:read.",
        "parameters": [
          {
            "name": "siteId",
            "in": "path",
            "required": true,
            "description": "Id del sitio.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "El sitio.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Site"
                },
                "example": {
                  "id": "site_123",
                  "name": "example.com",
                  "site_name": "Main site",
                  "domain": "example.com",
                  "custom_domain": "example.com",
                  "atomic_domain": "main.atomicat.net",
                  "project_id": "project_123",
                  "status": null,
                  "created_at": "2026-09-26T12:00:00.000Z",
                  "updated_at": "2026-09-26T12:00:00.000Z"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "El registro no existe o pertenece a otra cuenta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/pages": {
      "get": {
        "operationId": "listPages",
        "tags": [
          "Pages"
        ],
        "summary": "Listar páginas",
        "description": "Alcance requerido: pages:read.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "description": "Cantidad máxima de registros. El valor predeterminado es 50 y el máximo es 100."
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            },
            "description": "Índice de página que empieza en cero. La API devuelve limit registros a partir de page × limit."
          },
          {
            "name": "project_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Solo registros de este proyecto."
          },
          {
            "name": "site_id",
            "in": "query",
            "required": false,
            "description": "Solo páginas de este sitio.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "published",
            "in": "query",
            "required": false,
            "description": "true para publicadas, false para borradores.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "is_quiz",
            "in": "query",
            "required": false,
            "description": "true para devolver solo quizzes.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "has_element",
            "in": "query",
            "required": false,
            "description": "Solo páginas cuyo constructor contiene este tipo de elemento.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "available_for_funnel",
            "in": "query",
            "required": false,
            "description": "true para ocultar páginas que ya están en un embudo.",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Registros coincidentes. El cuerpo es un arreglo JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Page"
                  }
                },
                "example": [
                  {
                    "id": "page_123",
                    "name": "Main Offer",
                    "page_name": "Main Offer",
                    "status": "draft",
                    "is_quiz": false,
                    "project_id": "project_123",
                    "site_id": null,
                    "site_name": null,
                    "domain": null,
                    "slug": "",
                    "url": null,
                    "edit_url": "https://app.atomicat.com.br/builder/page_123",
                    "created_at": "2026-09-26T12:00:00.000Z",
                    "updated_at": "2026-09-26T12:00:00.000Z",
                    "published_at": null
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      },
      "post": {
        "operationId": "createPage",
        "tags": [
          "Pages"
        ],
        "summary": "Crear una página en blanco",
        "description": "Crea un borrador. Publícalo después con POST /pages/publish.\n\nAlcance requerido: pages:write.",
        "responses": {
          "201": {
            "description": "La página creada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Page"
                },
                "example": {
                  "id": "page_123",
                  "name": "Main Offer",
                  "page_name": "Main Offer",
                  "status": "draft",
                  "is_quiz": false,
                  "project_id": "project_123",
                  "site_id": null,
                  "site_name": null,
                  "domain": null,
                  "slug": "",
                  "url": null,
                  "edit_url": "https://app.atomicat.com.br/builder/page_123",
                  "created_at": "2026-09-26T12:00:00.000Z",
                  "updated_at": "2026-09-26T12:00:00.000Z",
                  "published_at": null
                }
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PageCreate"
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/pages/from-template": {
      "post": {
        "operationId": "createPageFromTemplate",
        "tags": [
          "Pages"
        ],
        "summary": "Crear una página desde una plantilla",
        "description": "Alcance requerido: pages:write.",
        "responses": {
          "201": {
            "description": "La página clonada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Page"
                },
                "example": {
                  "id": "page_123",
                  "name": "Main Offer",
                  "page_name": "Main Offer",
                  "status": "draft",
                  "is_quiz": false,
                  "project_id": "project_123",
                  "site_id": null,
                  "site_name": null,
                  "domain": null,
                  "slug": "",
                  "url": null,
                  "edit_url": "https://app.atomicat.com.br/builder/page_123",
                  "created_at": "2026-09-26T12:00:00.000Z",
                  "updated_at": "2026-09-26T12:00:00.000Z",
                  "published_at": null,
                  "template_id": "template_123",
                  "from_template": true
                }
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PageFromTemplate"
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/pages/duplicate": {
      "post": {
        "operationId": "duplicatePage",
        "tags": [
          "Pages"
        ],
        "summary": "Duplicar una página",
        "description": "Alcance requerido: pages:write.",
        "responses": {
          "201": {
            "description": "La página duplicada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageDuplicateResult"
                },
                "example": {
                  "id": "page_456",
                  "name": "Main Offer copy",
                  "page_name": "Main Offer copy",
                  "source_page_id": "page_123",
                  "edit_url": "https://app.atomicat.com.br/builder/page_456"
                }
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PageDuplicate"
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/pages/metadata": {
      "patch": {
        "operationId": "updatePageMetadata",
        "tags": [
          "Pages"
        ],
        "summary": "Actualizar metadatos de la página",
        "description": "page_id es obligatorio, más al menos uno de name, project_id, tags o product_label. tags puede ser un arreglo o un texto separado por comas.\n\nAlcance requerido: pages:write.",
        "responses": {
          "200": {
            "description": "Los metadatos actualizados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageMetadataResult"
                },
                "example": {
                  "id": "page_123",
                  "page_id": "page_123",
                  "updated": true,
                  "name": "Main Offer",
                  "project_id": "project_123",
                  "tags": [
                    "sales"
                  ],
                  "product_label": "Starter kit"
                }
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PageMetadata"
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/pages/content": {
      "patch": {
        "operationId": "updatePageContent",
        "tags": [
          "Pages"
        ],
        "summary": "Actualizar contenido mapeado",
        "description": "updates es un objeto de claves del mapa de contenido. Léelas en GET /search/page-content-map. Las claves desconocidas vuelven en missing y no se aplican.\n\nAlcance requerido: pages:write.",
        "responses": {
          "200": {
            "description": "El resultado de la actualización.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageContentResult"
                },
                "example": {
                  "id": "page_123",
                  "page_id": "page_123",
                  "success": true,
                  "applied_count": 1,
                  "changed_section_count": 1,
                  "missing_count": 0,
                  "applied": "[]",
                  "missing": "[]"
                }
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PageContentUpdate"
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/pages/replace-variables": {
      "post": {
        "operationId": "replacePageVariables",
        "tags": [
          "Pages"
        ],
        "summary": "Reemplazar variables de plantilla",
        "description": "variables asigna nombres de marcadores al texto de reemplazo. Los marcadores tienen la forma {{name}}.\n\nAlcance requerido: pages:write.",
        "responses": {
          "200": {
            "description": "El resultado del reemplazo.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageVariablesResult"
                },
                "example": {
                  "id": "page_123",
                  "page_id": "page_123",
                  "success": true,
                  "replacement_count": 2,
                  "changed_section_count": 1,
                  "replaced_variables": "[\"headline\"]",
                  "remaining_variables": "[]",
                  "remaining_variable_count": 0
                }
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PageVariables"
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/pages/builder": {
      "get": {
        "operationId": "getPageBuilder",
        "tags": [
          "Builder"
        ],
        "summary": "Leer el constructor de la página",
        "description": "Requiere builder:read o pages:read. include_tree=false omite el árbol de secciones.\n\nAlcance requerido: cualquiera de builder:read, pages:read.",
        "parameters": [
          {
            "name": "page_id",
            "in": "query",
            "required": true,
            "description": "Id de la página.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "include_tree",
            "in": "query",
            "required": false,
            "description": "Incluir el árbol. Predeterminado true.",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "El resumen del constructor.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BuilderSummary"
                },
                "example": {
                  "id": "page_123",
                  "page_id": "page_123",
                  "builder": {
                    "sectionCount": 1,
                    "tree": {
                      "sections": []
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/pages/builder/node": {
      "get": {
        "operationId": "getBuilderNode",
        "tags": [
          "Builder"
        ],
        "summary": "Leer un nodo del constructor",
        "description": "Alcance requerido: cualquiera de builder:read, pages:read.",
        "parameters": [
          {
            "name": "page_id",
            "in": "query",
            "required": true,
            "description": "Id de la página.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "node_id",
            "in": "query",
            "required": true,
            "description": "Id del nodo en el árbol.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "El nodo.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BuilderNode"
                },
                "example": {
                  "id": "node_123",
                  "page_id": "page_123",
                  "node_id": "node_123",
                  "path": "sections[0]",
                  "summary": null,
                  "node": {
                    "id": "node_123"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      },
      "patch": {
        "operationId": "updateBuilderNodeFields",
        "tags": [
          "Builder"
        ],
        "summary": "Actualizar campos del nodo",
        "description": "updates debe incluir misc, style o ambos. Esto modifica esos objetos. No reemplaza el nodo completo.\n\nAlcance requerido: cualquiera de builder:write, pages:write.",
        "responses": {
          "200": {
            "description": "El resultado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BuilderNodeUpdate"
                },
                "example": {
                  "id": "node_123",
                  "page_id": "page_123",
                  "node_id": "node_123",
                  "updated": true,
                  "path": "sections[0]"
                }
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BuilderNodeFields"
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/pages/builder/node/replace": {
      "patch": {
        "operationId": "replaceBuilderNode",
        "tags": [
          "Builder"
        ],
        "summary": "Reemplazar un nodo",
        "description": "node es el objeto completo que reemplaza el nodo existente.\n\nAlcance requerido: cualquiera de builder:write, pages:write.",
        "responses": {
          "200": {
            "description": "El resultado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BuilderNodeReplaceResult"
                },
                "example": {
                  "id": "node_123",
                  "page_id": "page_123",
                  "node_id": "node_123",
                  "updated": true,
                  "path": "sections[0]",
                  "builder_warnings": "[]"
                }
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BuilderNodeReplace"
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/pages/delay": {
      "patch": {
        "operationId": "updatePageDelay",
        "tags": [
          "Builder"
        ],
        "summary": "Actualizar el retraso de aparición",
        "description": "Alcance requerido: cualquiera de pages:write, builder:write.",
        "responses": {
          "200": {
            "description": "El resultado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageDelayResult"
                },
                "example": {
                  "id": "page_123",
                  "page_id": "page_123",
                  "updated": true,
                  "delay": {
                    "time": 5
                  }
                }
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PageDelay"
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/pages/validate-before-publish": {
      "post": {
        "operationId": "validatePageBeforePublish",
        "tags": [
          "Pages"
        ],
        "summary": "Comprobar si la página se puede publicar",
        "description": "ready_to_publish es false si no hay secciones o quedan variables. Las listas se devuelven como texto JSON.\n\nAlcance requerido: pages:read.",
        "responses": {
          "200": {
            "description": "El resultado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageValidation"
                },
                "example": {
                  "id": "page_123",
                  "page_id": "page_123",
                  "ready_to_publish": true,
                  "issue_count": 0,
                  "issues": "[]",
                  "field_count": 4,
                  "remaining_variable_count": 0,
                  "remaining_variables": "[]"
                }
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PageIdBody"
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/pages/publish": {
      "post": {
        "operationId": "publishPage",
        "tags": [
          "Pages"
        ],
        "summary": "Publicar una página",
        "description": "page_id y site_id son obligatorios. slug es la ruta en el sitio. Un slug vacío publica en la raíz.\n\nAlcance requerido: cualquiera de pages:publish, pages:write.",
        "responses": {
          "200": {
            "description": "El resultado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PagePublishResult"
                },
                "example": {
                  "id": "page_123",
                  "page_id": "page_123",
                  "site_id": "site_123",
                  "success": true,
                  "url": "https://example.com/offer",
                  "domain": "example.com",
                  "slug": "offer",
                  "revision_saved": true,
                  "revision_warning": null
                }
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PagePublish"
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/pages/{pageId}": {
      "get": {
        "operationId": "getPage",
        "tags": [
          "Pages"
        ],
        "summary": "Obtener una página",
        "description": "Lee un borrador que todavía no aparece en la lista, y también páginas publicadas.\n\nAlcance requerido: pages:read.",
        "parameters": [
          {
            "name": "pageId",
            "in": "path",
            "required": true,
            "description": "Id de la página.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "La página.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Page"
                },
                "example": {
                  "id": "page_123",
                  "name": "Main Offer",
                  "page_name": "Main Offer",
                  "status": "draft",
                  "is_quiz": false,
                  "project_id": "project_123",
                  "site_id": null,
                  "site_name": null,
                  "domain": null,
                  "slug": "",
                  "url": null,
                  "edit_url": "https://app.atomicat.com.br/builder/page_123",
                  "created_at": "2026-09-26T12:00:00.000Z",
                  "updated_at": "2026-09-26T12:00:00.000Z",
                  "published_at": null
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "El registro no existe o pertenece a otra cuenta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      },
      "delete": {
        "operationId": "deletePage",
        "tags": [
          "Pages"
        ],
        "summary": "Eliminar una página",
        "description": "Un borrador sin sitio se elimina directamente. Una página publicada o ya unida a un sitio se elimina a través del sitio y debe tener site id. Una página publicada sin sitio responde 400.\n\nAlcance requerido: pages:write.",
        "parameters": [
          {
            "name": "pageId",
            "in": "path",
            "required": true,
            "description": "Id de la página.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "El registro fue eliminado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                },
                "example": {
                  "success": true,
                  "id": "record_123",
                  "deleted": true
                }
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "El registro no existe o pertenece a otra cuenta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/templates": {
      "get": {
        "operationId": "listTemplates",
        "tags": [
          "Pages"
        ],
        "summary": "Listar plantillas",
        "description": "Alcance requerido: pages:read.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "description": "Cantidad máxima de registros. El valor predeterminado es 50 y el máximo es 100."
          },
          {
            "name": "query",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Texto sin distinción de mayúsculas que se compara con el nombre y los campos relacionados."
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "description": "Categoría.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Tipo. Predeterminado page.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "template_id",
            "in": "query",
            "required": false,
            "description": "Id exacto.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Registros coincidentes. El cuerpo es un arreglo JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Template"
                  }
                },
                "example": [
                  {
                    "id": "template_123",
                    "name": "Offer",
                    "template_name": "Offer",
                    "category": "sales",
                    "type": "page",
                    "description": null,
                    "preview_url": null,
                    "image_url": null
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/search/templates": {
      "get": {
        "operationId": "searchTemplates",
        "tags": [
          "Pages"
        ],
        "summary": "Buscar plantillas",
        "description": "Los mismos filtros y la misma respuesta que GET /templates.\n\nAlcance requerido: pages:read.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "description": "Cantidad máxima de registros. El valor predeterminado es 50 y el máximo es 100."
          },
          {
            "name": "query",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Texto sin distinción de mayúsculas que se compara con el nombre y los campos relacionados."
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "description": "Categoría.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Tipo.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "template_id",
            "in": "query",
            "required": false,
            "description": "Id exacto.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Registros coincidentes. El cuerpo es un arreglo JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Template"
                  }
                },
                "example": [
                  {
                    "id": "template_123",
                    "name": "Offer",
                    "template_name": "Offer",
                    "category": "sales",
                    "type": "page",
                    "description": null,
                    "preview_url": null,
                    "image_url": null
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/search/pages": {
      "get": {
        "operationId": "searchPages",
        "tags": [
          "Pages"
        ],
        "summary": "Buscar páginas",
        "description": "Compara nombre, título, dominio y slug. page_id devuelve un arreglo de un elemento. El límite predeterminado es 100.\n\nAlcance requerido: pages:read.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "description": "Cantidad máxima de registros. El valor predeterminado es 50 y el máximo es 100."
          },
          {
            "name": "query",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Texto sin distinción de mayúsculas que se compara con el nombre y los campos relacionados."
          },
          {
            "name": "page_id",
            "in": "query",
            "required": false,
            "description": "Id exacto.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Registros coincidentes. El cuerpo es un arreglo JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Page"
                  }
                },
                "example": [
                  {
                    "id": "page_123",
                    "name": "Main Offer",
                    "page_name": "Main Offer",
                    "status": "draft",
                    "is_quiz": false,
                    "project_id": "project_123",
                    "site_id": null,
                    "site_name": null,
                    "domain": null,
                    "slug": "",
                    "url": null,
                    "edit_url": "https://app.atomicat.com.br/builder/page_123",
                    "created_at": "2026-09-26T12:00:00.000Z",
                    "updated_at": "2026-09-26T12:00:00.000Z",
                    "published_at": null
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/search/page-content-map": {
      "get": {
        "operationId": "getPageContentMap",
        "tags": [
          "Builder"
        ],
        "summary": "Leer campos de contenido editables",
        "description": "fields y variables son texto JSON. Usa las claves con PATCH /pages/content.\n\nAlcance requerido: pages:read.",
        "parameters": [
          {
            "name": "page_id",
            "in": "query",
            "required": true,
            "description": "Id de la página.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "El mapa de contenido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContentMap"
                },
                "example": {
                  "id": "page_123",
                  "page_id": "page_123",
                  "page_name": "Main Offer",
                  "field_count": 1,
                  "variable_count": 1,
                  "variables": "[\"headline\"]",
                  "fields": "[]",
                  "ready_for_variable_replacement": true
                }
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/quizzes": {
      "get": {
        "operationId": "listQuizzes",
        "tags": [
          "Quizzes"
        ],
        "summary": "Listar quizzes",
        "description": "Los ids de quiz vienen del registro (qid) y no siempre coinciden con el id de la página.\n\nAlcance requerido: pages:read.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "description": "Cantidad máxima de registros. El valor predeterminado es 50 y el máximo es 100."
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            },
            "description": "Índice de página que empieza en cero. La API devuelve limit registros a partir de page × limit."
          },
          {
            "name": "query",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Texto sin distinción de mayúsculas que se compara con el nombre y los campos relacionados."
          },
          {
            "name": "page_id",
            "in": "query",
            "required": false,
            "description": "Solo quizzes de esta página.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "quiz_id",
            "in": "query",
            "required": false,
            "description": "Id exacto del quiz.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Registros coincidentes. El cuerpo es un arreglo JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Quiz"
                  }
                },
                "example": [
                  {
                    "id": "quiz_123",
                    "name": "Main quiz",
                    "quiz_name": "Main quiz",
                    "page_id": "page_123",
                    "page_name": "Quiz page",
                    "site_id": null,
                    "project_id": "project_123",
                    "created_at": "2026-09-26T12:00:00.000Z",
                    "updated_at": "2026-09-26T12:00:00.000Z"
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      },
      "post": {
        "operationId": "createQuiz",
        "tags": [
          "Quizzes"
        ],
        "summary": "Crear una página de quiz",
        "description": "Alcance requerido: pages:write.",
        "responses": {
          "201": {
            "description": "La página de quiz creada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuizPage"
                },
                "example": {
                  "id": "page_123",
                  "name": "Main Offer",
                  "page_name": "Main Offer",
                  "status": "draft",
                  "is_quiz": true,
                  "project_id": "project_123",
                  "site_id": null,
                  "site_name": null,
                  "domain": null,
                  "slug": "",
                  "url": null,
                  "edit_url": "https://app.atomicat.com.br/builder/page_123",
                  "created_at": "2026-09-26T12:00:00.000Z",
                  "updated_at": "2026-09-26T12:00:00.000Z",
                  "published_at": null,
                  "quiz_id": "page_123"
                }
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QuizCreate"
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/search/quizzes": {
      "get": {
        "operationId": "searchQuizzes",
        "tags": [
          "Quizzes"
        ],
        "summary": "Buscar quizzes",
        "description": "Los mismos filtros y la misma respuesta que GET /quizzes.\n\nAlcance requerido: pages:read.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "description": "Cantidad máxima de registros. El valor predeterminado es 50 y el máximo es 100."
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            },
            "description": "Índice de página que empieza en cero. La API devuelve limit registros a partir de page × limit."
          },
          {
            "name": "query",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Texto sin distinción de mayúsculas que se compara con el nombre y los campos relacionados."
          },
          {
            "name": "page_id",
            "in": "query",
            "required": false,
            "description": "Id de la página.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "quiz_id",
            "in": "query",
            "required": false,
            "description": "Id del quiz.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Registros coincidentes. El cuerpo es un arreglo JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Quiz"
                  }
                },
                "example": [
                  {
                    "id": "quiz_123",
                    "name": "Main quiz",
                    "quiz_name": "Main quiz",
                    "page_id": "page_123",
                    "page_name": "Quiz page",
                    "site_id": null,
                    "project_id": "project_123",
                    "created_at": null,
                    "updated_at": null
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/quizzes/{quizId}": {
      "get": {
        "operationId": "getQuiz",
        "tags": [
          "Quizzes"
        ],
        "summary": "Obtener un quiz",
        "description": "quizId puede ser el id del quiz (qid) o el id de una página marcada como quiz.\n\nAlcance requerido: pages:read.",
        "parameters": [
          {
            "name": "quizId",
            "in": "path",
            "required": true,
            "description": "Id del quiz o de la página quiz.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "El quiz.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Quiz"
                },
                "example": {
                  "id": "quiz_123",
                  "name": "Main quiz",
                  "quiz_name": "Main quiz",
                  "page_id": "page_123",
                  "page_name": "Quiz page",
                  "site_id": null,
                  "project_id": "project_123",
                  "created_at": null,
                  "updated_at": null
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "El registro no existe o pertenece a otra cuenta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/quizzes/from-template": {
      "post": {
        "operationId": "createQuizFromTemplate",
        "tags": [
          "Quizzes"
        ],
        "summary": "Crear un quiz desde una plantilla",
        "description": "Alcance requerido: pages:write.",
        "responses": {
          "201": {
            "description": "La página de quiz creada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuizPage"
                },
                "example": {
                  "id": "page_123",
                  "name": "Main Offer",
                  "page_name": "Main Offer",
                  "status": "draft",
                  "is_quiz": true,
                  "project_id": "project_123",
                  "site_id": null,
                  "site_name": null,
                  "domain": null,
                  "slug": "",
                  "url": null,
                  "edit_url": "https://app.atomicat.com.br/builder/page_123",
                  "created_at": "2026-09-26T12:00:00.000Z",
                  "updated_at": "2026-09-26T12:00:00.000Z",
                  "published_at": null,
                  "quiz_id": "page_123",
                  "from_template": true,
                  "template_id": "template_123"
                }
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PageFromTemplate"
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/funnels": {
      "get": {
        "operationId": "listFunnels",
        "tags": [
          "Funnels"
        ],
        "summary": "Listar embudos",
        "description": "Esta API no elimina embudos.\n\nAlcance requerido: funnels:read.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "description": "Cantidad máxima de registros. El valor predeterminado es 50 y el máximo es 100."
          },
          {
            "name": "project_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Solo registros de este proyecto."
          }
        ],
        "responses": {
          "200": {
            "description": "Registros coincidentes. El cuerpo es un arreglo JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Funnel"
                  }
                },
                "example": [
                  {
                    "id": "funnel_123",
                    "name": "Main funnel",
                    "site_id": "site_123",
                    "project_id": "project_123",
                    "status": "active",
                    "pages": [
                      "page_123"
                    ],
                    "page_ids": "page_123",
                    "steps": [],
                    "created_at": "2026-09-26T12:00:00.000Z",
                    "updated_at": "2026-09-26T12:00:00.000Z"
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      },
      "post": {
        "operationId": "createFunnel",
        "tags": [
          "Funnels"
        ],
        "summary": "Crear un embudo",
        "description": "Cada página necesita pageId o url, y pageType.\n\nAlcance requerido: funnels:write.",
        "responses": {
          "201": {
            "description": "El embudo creado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Funnel"
                },
                "example": {
                  "id": "funnel_123",
                  "name": "Main funnel",
                  "site_id": null,
                  "project_id": "project_123",
                  "status": null,
                  "pages": [],
                  "page_ids": "",
                  "steps": [],
                  "created_at": null,
                  "updated_at": null
                }
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FunnelCreate"
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      },
      "patch": {
        "operationId": "updateFunnel",
        "tags": [
          "Funnels"
        ],
        "summary": "Actualizar un embudo",
        "description": "funnel_id es obligatorio. pages reemplaza la lista de pasos cuando lo envías.\n\nAlcance requerido: funnels:write.",
        "responses": {
          "200": {
            "description": "El embudo actualizado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Funnel"
                },
                "example": {
                  "id": "funnel_123",
                  "name": "Main funnel",
                  "site_id": null,
                  "project_id": null,
                  "status": null,
                  "pages": [],
                  "page_ids": "",
                  "steps": [],
                  "created_at": null,
                  "updated_at": null
                }
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FunnelUpdate"
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/search/funnels": {
      "get": {
        "operationId": "searchFunnels",
        "tags": [
          "Funnels"
        ],
        "summary": "Buscar embudos",
        "description": "Alcance requerido: funnels:read.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "description": "Cantidad máxima de registros. El valor predeterminado es 50 y el máximo es 100."
          },
          {
            "name": "query",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Texto sin distinción de mayúsculas que se compara con el nombre y los campos relacionados."
          },
          {
            "name": "project_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Solo registros de este proyecto."
          },
          {
            "name": "funnel_id",
            "in": "query",
            "required": false,
            "description": "Id exacto.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Registros coincidentes. El cuerpo es un arreglo JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Funnel"
                  }
                },
                "example": [
                  {
                    "id": "funnel_123",
                    "name": "Main funnel",
                    "site_id": null,
                    "project_id": null,
                    "status": null,
                    "pages": [],
                    "page_ids": "",
                    "steps": [],
                    "created_at": null,
                    "updated_at": null
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/funnels/{funnelId}": {
      "get": {
        "operationId": "getFunnel",
        "tags": [
          "Funnels"
        ],
        "summary": "Obtener un embudo",
        "description": "Alcance requerido: funnels:read.",
        "parameters": [
          {
            "name": "funnelId",
            "in": "path",
            "required": true,
            "description": "Id del embudo.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "El embudo.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Funnel"
                },
                "example": {
                  "id": "funnel_123",
                  "name": "Main funnel",
                  "site_id": null,
                  "project_id": null,
                  "status": null,
                  "pages": [],
                  "page_ids": "",
                  "steps": [],
                  "created_at": null,
                  "updated_at": null
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "El registro no existe o pertenece a otra cuenta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/videos": {
      "get": {
        "operationId": "listVideos",
        "tags": [
          "Videos"
        ],
        "summary": "Listar videos",
        "description": "Usa skip en lugar de page. Esta API no sube ni elimina videos. Consulta este endpoint después de una carga; no hay webhook video.uploaded.\n\nAlcance requerido: videos:read.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Máximo de videos. Predeterminado 50, máximo 100.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "skip",
            "in": "query",
            "required": false,
            "description": "Cantidad de videos a omitir. Predeterminado 0.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Registros coincidentes. El cuerpo es un arreglo JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Video"
                  }
                },
                "example": [
                  {
                    "id": "video_123",
                    "video_id": "video_123",
                    "name": "Lesson 1",
                    "title": "Lesson 1",
                    "status": "ready",
                    "duration": 120,
                    "thumbnail_url": null,
                    "project_id": "project_123",
                    "created_at": "2026-09-26T12:00:00.000Z",
                    "updated_at": null
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      },
      "patch": {
        "operationId": "updateVideo",
        "tags": [
          "Videos"
        ],
        "summary": "Actualizar el reproductor",
        "description": "video_id es obligatorio. Envía solo los ajustes que quieres cambiar.\n\nAlcance requerido: videos:write.",
        "responses": {
          "200": {
            "description": "El video actualizado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Video"
                },
                "example": {
                  "id": "video_123",
                  "video_id": "video_123",
                  "name": "Lesson 1",
                  "title": "Lesson 1",
                  "status": "ready",
                  "duration": 120,
                  "thumbnail_url": null,
                  "project_id": "project_123",
                  "created_at": null,
                  "updated_at": null
                }
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VideoUpdate"
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/search/videos": {
      "get": {
        "operationId": "searchVideos",
        "tags": [
          "Videos"
        ],
        "summary": "Buscar videos",
        "description": "Alcance requerido: videos:read.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "description": "Cantidad máxima de registros. El valor predeterminado es 50 y el máximo es 100."
          },
          {
            "name": "query",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Texto sin distinción de mayúsculas que se compara con el nombre y los campos relacionados."
          },
          {
            "name": "video_id",
            "in": "query",
            "required": false,
            "description": "Id exacto. Devuelve un arreglo de un elemento.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "skip",
            "in": "query",
            "required": false,
            "description": "Videos a omitir al buscar en la lista.",
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Registros coincidentes. El cuerpo es un arreglo JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Video"
                  }
                },
                "example": [
                  {
                    "id": "video_123",
                    "video_id": "video_123",
                    "name": "Lesson 1",
                    "title": "Lesson 1",
                    "status": "ready",
                    "duration": null,
                    "thumbnail_url": null,
                    "project_id": null,
                    "created_at": null,
                    "updated_at": null
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/videos/{videoId}": {
      "get": {
        "operationId": "getVideo",
        "tags": [
          "Videos"
        ],
        "summary": "Obtener un video",
        "description": "Alcance requerido: videos:read.",
        "parameters": [
          {
            "name": "videoId",
            "in": "path",
            "required": true,
            "description": "Id del video.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "El video.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Video"
                },
                "example": {
                  "id": "video_123",
                  "video_id": "video_123",
                  "name": "Lesson 1",
                  "title": "Lesson 1",
                  "status": "ready",
                  "duration": 120,
                  "thumbnail_url": null,
                  "project_id": null,
                  "created_at": null,
                  "updated_at": null
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "El registro no existe o pertenece a otra cuenta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/products": {
      "get": {
        "operationId": "listProducts",
        "tags": [
          "Products"
        ],
        "summary": "Listar productos",
        "description": "Alcance requerido: products:read.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "description": "Cantidad máxima de registros. El valor predeterminado es 50 y el máximo es 100."
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            },
            "description": "Índice de página que empieza en cero. La API devuelve limit registros a partir de page × limit."
          },
          {
            "name": "project_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Solo registros de este proyecto."
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "simple o bundle.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Registros coincidentes. El cuerpo es un arreglo JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Product"
                  }
                },
                "example": [
                  {
                    "id": "product_123",
                    "name": "Starter kit",
                    "type": "simple",
                    "sku": "KIT-1",
                    "description": "Example product",
                    "image": null,
                    "show_full_product": false,
                    "price": 97,
                    "compare_price": 197,
                    "rating": "4.9",
                    "rating_count": "10K+",
                    "project_id": "project_123",
                    "cta_text": "Buy now",
                    "cta_url": "https://example.com/checkout",
                    "cta_target": false,
                    "use_single_cta_link": false,
                    "bundle_discount": 0,
                    "bundle_item_count": 0,
                    "tiers_enabled": false,
                    "subscription_enabled": false,
                    "created_at": "2026-09-26T12:00:00.000Z",
                    "updated_at": "2026-09-26T12:00:00.000Z"
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      },
      "post": {
        "operationId": "createProduct",
        "tags": [
          "Products"
        ],
        "summary": "Crear un producto",
        "description": "name es obligatorio. type es simple o bundle. Un bundle requiere bundle_items_json.\n\nAlcance requerido: products:write.",
        "responses": {
          "201": {
            "description": "El producto creado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                },
                "example": {
                  "id": "product_123",
                  "name": "Starter kit",
                  "type": "simple",
                  "sku": "KIT-1",
                  "description": "Example product",
                  "image": null,
                  "show_full_product": false,
                  "price": 97,
                  "compare_price": 197,
                  "rating": "4.9",
                  "rating_count": "10K+",
                  "project_id": "project_123",
                  "cta_text": "Buy now",
                  "cta_url": "https://example.com/checkout",
                  "cta_target": false,
                  "use_single_cta_link": false,
                  "bundle_discount": 0,
                  "bundle_item_count": 0,
                  "tiers_enabled": false,
                  "subscription_enabled": false,
                  "created_at": "2026-09-26T12:00:00.000Z",
                  "updated_at": "2026-09-26T12:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProductWrite"
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      },
      "patch": {
        "operationId": "updateProduct",
        "tags": [
          "Products"
        ],
        "summary": "Actualizar un producto",
        "description": "product_id es obligatorio. Envía solo los campos que quieres cambiar.\n\nAlcance requerido: products:write.",
        "responses": {
          "200": {
            "description": "El producto actualizado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                },
                "example": {
                  "id": "product_123",
                  "name": "Starter kit",
                  "type": "simple",
                  "sku": "KIT-1",
                  "description": "Example product",
                  "image": null,
                  "show_full_product": false,
                  "price": 97,
                  "compare_price": 197,
                  "rating": "4.9",
                  "rating_count": "10K+",
                  "project_id": "project_123",
                  "cta_text": "Buy now",
                  "cta_url": "https://example.com/checkout",
                  "cta_target": false,
                  "use_single_cta_link": false,
                  "bundle_discount": 0,
                  "bundle_item_count": 0,
                  "tiers_enabled": false,
                  "subscription_enabled": false,
                  "created_at": "2026-09-26T12:00:00.000Z",
                  "updated_at": "2026-09-26T12:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProductUpdate"
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/search/products": {
      "get": {
        "operationId": "searchProducts",
        "tags": [
          "Products"
        ],
        "summary": "Buscar productos",
        "description": "Alcance requerido: products:read.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "description": "Cantidad máxima de registros. El valor predeterminado es 50 y el máximo es 100."
          },
          {
            "name": "query",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Texto sin distinción de mayúsculas que se compara con el nombre y los campos relacionados."
          },
          {
            "name": "project_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Solo registros de este proyecto."
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "simple o bundle.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "product_id",
            "in": "query",
            "required": false,
            "description": "Id exacto.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Registros coincidentes. El cuerpo es un arreglo JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Product"
                  }
                },
                "example": [
                  {
                    "id": "product_123",
                    "name": "Starter kit",
                    "type": "simple",
                    "sku": "KIT-1",
                    "description": "Example product",
                    "image": null,
                    "show_full_product": false,
                    "price": 97,
                    "compare_price": 197,
                    "rating": "4.9",
                    "rating_count": "10K+",
                    "project_id": "project_123",
                    "cta_text": "Buy now",
                    "cta_url": "https://example.com/checkout",
                    "cta_target": false,
                    "use_single_cta_link": false,
                    "bundle_discount": 0,
                    "bundle_item_count": 0,
                    "tiers_enabled": false,
                    "subscription_enabled": false,
                    "created_at": "2026-09-26T12:00:00.000Z",
                    "updated_at": "2026-09-26T12:00:00.000Z"
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/products/{productId}": {
      "get": {
        "operationId": "getProduct",
        "tags": [
          "Products"
        ],
        "summary": "Obtener un producto",
        "description": "Alcance requerido: products:read.",
        "parameters": [
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "description": "Id del producto.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "El producto.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                },
                "example": {
                  "id": "product_123",
                  "name": "Starter kit",
                  "type": "simple",
                  "sku": "KIT-1",
                  "description": "Example product",
                  "image": null,
                  "show_full_product": false,
                  "price": 97,
                  "compare_price": 197,
                  "rating": "4.9",
                  "rating_count": "10K+",
                  "project_id": "project_123",
                  "cta_text": "Buy now",
                  "cta_url": "https://example.com/checkout",
                  "cta_target": false,
                  "use_single_cta_link": false,
                  "bundle_discount": 0,
                  "bundle_item_count": 0,
                  "tiers_enabled": false,
                  "subscription_enabled": false,
                  "created_at": "2026-09-26T12:00:00.000Z",
                  "updated_at": "2026-09-26T12:00:00.000Z"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "El registro no existe o pertenece a otra cuenta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      },
      "delete": {
        "operationId": "deleteProduct",
        "tags": [
          "Products"
        ],
        "summary": "Eliminar un producto",
        "description": "Alcance requerido: products:write.",
        "parameters": [
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "description": "Id del producto.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "El registro fue eliminado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                },
                "example": {
                  "success": true,
                  "id": "record_123",
                  "deleted": true
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "El registro no existe o pertenece a otra cuenta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/search/leads": {
      "get": {
        "operationId": "searchLeads",
        "tags": [
          "Leads"
        ],
        "summary": "Buscar leads",
        "description": "type es form, quiz, o se omite para ambos. El límite predeterminado es 25 y el máximo es 50. No hay endpoint para crear o eliminar leads.\n\nAlcance requerido: leads:read.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Máximo de leads. Predeterminado 25, máximo 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 25
            }
          },
          {
            "name": "query",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Texto sin distinción de mayúsculas que se compara con el nombre y los campos relacionados."
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "form o quiz.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lead_id",
            "in": "query",
            "required": false,
            "description": "Id exacto.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page_id",
            "in": "query",
            "required": false,
            "description": "Solo leads de esta página.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "email",
            "in": "query",
            "required": false,
            "description": "Coincidencia exacta de email.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Registros coincidentes. El cuerpo es un arreglo JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Lead"
                  }
                },
                "example": [
                  {
                    "id": "lead_123",
                    "lead_id": "lead_123",
                    "type": "form",
                    "name": "Jane Example",
                    "first_name": "Jane",
                    "last_name": "Example",
                    "email": "jane@example.com",
                    "phone": "+15555550123",
                    "form_id": "form_123",
                    "form_name": "Checkout",
                    "page_id": "page_123",
                    "page_url": "https://example.com/offer",
                    "project_id": "project_123",
                    "site_id": "site_123",
                    "abandoned": false,
                    "fields": {},
                    "created_at": "2026-09-26T12:00:00.000Z"
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/analytics": {
      "get": {
        "operationId": "getAnalytics",
        "tags": [
          "Analytics"
        ],
        "summary": "Obtener conteos de la cuenta",
        "description": "Conteos de la cuenta. No es un informe de visitas, conversiones o ingresos.\n\nAlcance requerido: analytics:read.",
        "responses": {
          "200": {
            "description": "Los conteos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Analytics"
                },
                "example": {
                  "pages": 12,
                  "sites": 2,
                  "funnels": 3,
                  "products": 4,
                  "projects": 1,
                  "form_leads": 80,
                  "quiz_leads": 20
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/hooks": {
      "post": {
        "operationId": "createHook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Suscribirse a un evento",
        "description": "target_url debe ser HTTPS público. Se rechazan localhost, IPs privadas y hostnames que resuelven a ellas. La URL se vuelve a comprobar antes de cada entrega. Basta uno de los alcances listados.\n\nAlcance requerido: cualquiera de leads:read, pages:read, products:read, funnels:read, sites:read, projects:read.",
        "responses": {
          "201": {
            "description": "La suscripción. La URL de destino no se devuelve.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HookSubscription"
                },
                "example": {
                  "id": "sub_123",
                  "event_type": "form_lead.created",
                  "active": true,
                  "created_at": "2026-09-26T12:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/HookCreate"
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/hooks/{subscriptionId}": {
      "delete": {
        "operationId": "deleteHook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Desactivar una suscripción",
        "description": "Marca la suscripción como inactiva. Las entregas se detienen. La respuesta es { success: true }.\n\nAlcance requerido: cualquiera de leads:read, pages:read, products:read, funnels:read, sites:read, projects:read.",
        "parameters": [
          {
            "name": "subscriptionId",
            "in": "path",
            "required": true,
            "description": "Id devuelto por POST /hooks.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "La suscripción fue desactivada.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "success"
                  ]
                },
                "example": {
                  "success": true
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/hooks/sample/{eventType}": {
      "get": {
        "operationId": "getHookSample",
        "tags": [
          "Webhooks"
        ],
        "summary": "Obtener un payload de ejemplo",
        "description": "Devuelve un arreglo con un objeto de ejemplo. eventType es form_lead.created, quiz_lead.created, page.published, page.created, product.created, funnel.created, site.created o project.created. Un tipo desconocido devuelve el ejemplo de lead de formulario.\n\nAlcance requerido: cualquiera de leads:read, pages:read, products:read, funnels:read, sites:read, projects:read.",
        "parameters": [
          {
            "name": "eventType",
            "in": "path",
            "required": true,
            "description": "Nombre del evento, por ejemplo form_lead.created.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Un evento de ejemplo en un arreglo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object"
                  }
                },
                "example": [
                  {
                    "id": "sample_123",
                    "event_type": "form_lead.created",
                    "email": "jane@example.com"
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Falta un campo o hay un valor inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "El token Bearer falta, es inválido, expiró o fue revocado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "El token es válido, pero no incluye el alcance requerido o la IP no está en la lista permitida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "El token superó 5.000 solicitudes en 10 minutos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    }
  }
}
