# Guía de Usuario - API Tresipunt Manager

## Introducción

Esta guía explica cómo usar la API de Tresipunt Manager de forma práctica y sencilla. Está dirigida a desarrolladores que necesitan integrar plugins de Moodle con el sistema de gestión.

## ¿Qué es la API?

La API de Tresipunt Manager es un sistema centralizado que permite a los plugins de Moodle:
- Verificar licencias
- Obtener configuraciones personalizadas
- Recibir archivos SCSS y JavaScript para personalización
- Obtener funcionalidades (features) del producto
- Enviar datos de telemetría
- Sincronizar información del entorno

## Conceptos Básicos

### Autenticación

Todas las peticiones requieren un **Bearer Token** que se obtiene del panel de administración. Este token identifica tu entorno y valida tus permisos.

**Ejemplo de uso:**
```
Authorization: Bearer tu_token_aqui
```

### Estructura de Peticiones

Todas las peticiones van al mismo endpoint (`/api/v1/`) y se diferencian por el campo `action` en el cuerpo de la petición.

### Versiones

Las versiones se expresan en formato `YYYYMMDDXX` (10 dígitos):
- `2025110401` = 4 de noviembre de 2025, versión 01
- `2025081101` = 11 de agosto de 2025, versión 01

## Flujo de Trabajo Típico

### 1. Sincronización de Datos (Sync)

Actualiza la información de tu entorno en el Manager. **IMPORTANTE**: Esta acción NO crea nuevos entornos, solo actualiza entornos que ya existen.

```json
{
  "action": "sync",
  "plugin": "local_tresipunt",
  "host": "https://tu-moodle.com",
  "version": "2025110401",
  "environment": {
    "version": "2025081101",
    "release": "4.5.1",
    "type": "moodle",
    "env": "pro"
  }
  // Nota: También se acepta "site" para compatibilidad con versiones anteriores
}
```

**¿Cuándo usar?**
- Para actualizar información del entorno (versión, entorno, etc.)
- Periódicamente para mantener los datos sincronizados
- Después de actualizar Moodle

**⚠️ IMPORTANTE:**
- El entorno DEBE estar previamente creado en el Manager desde el panel de administración
- Si el entorno no existe, recibirás un error 404
- Esta acción NO registra nuevos entornos

**Respuesta exitosa:**
```json
{
  "success": true,
  "data": {
    "id": 1,
    "name": "tu-moodle.com",
    "version": "2025081101",
    "env": "pro",
    "active": true
  }
}
```

**Si el entorno no existe:**
```json
{
  "success": false,
  "error": "Environment not found for this host",
  "code": 404
}
```

**Si el entorno está vinculado a otro token:**
```json
{
  "success": false,
  "error": "El host proporcionado no está vinculado a este token",
  "code": 401
}
```

### 2. Verificación de Licencia

Antes de usar funcionalidades premium, verifica la licencia:

```json
{
  "action": "licence",
  "plugin": "theme_fresk",
  "host": "https://tu-moodle.com",
  "version": "2025110401",
  "environment": {
    "version": "2025081101",
    "release": "4.5.1"
  }
  // Nota: También se acepta "site" para compatibilidad
}
```

**¿Cuándo usar?**
- Al iniciar el plugin
- Antes de activar funcionalidades premium
- Periódicamente para validar que la licencia sigue activa

**Respuesta exitosa:**
```json
{
  "success": true,
  "data": {
    "expires_at": "2025-12-01",
    "product": "theme_fresk",
    "products": ["theme_fresk", "block_tresipuntsepe"],
    "support_active": false
  }
}
```

**Si no tienes licencia:**
```json
{
  "success": false,
  "error": "Licence does not include this plugin",
  "code": 2001
}
```

### 2.1. Obtener Todos los Productos del Entorno

Obtén todos los productos activos asociados a tu entorno sin necesidad de especificar un plugin:

```json
{
  "action": "products",
  "host": "https://tu-moodle.com",
  "environment": {
    "version": "2025100601.03",
    "release": "5.1.1+ (Build: 20251219)",
    "env": "pro"
  }
  // Nota: También se acepta "site" para compatibilidad
}
```

**¿Cuándo usar?**
- Para listar todos los productos disponibles en tu entorno
- Para verificar qué productos están activos sin validar uno específico
- Para mostrar un catálogo de productos disponibles

**Respuesta exitosa:**
```json
{
  "success": true,
  "error": "",
  "code": 0,
  "action": "products",
  "data": {
    "products": ["theme_fresk", "block_tresipuntsepe"],
    "environmentid": 3,
    // Nota: También se devuelve "siteid" para compatibilidad
    "support_active": false,
    "warnings": []
  }
}
```

**Si el entorno no existe:**
```json
{
  "success": false,
  "error": "Environment not found for this host",
  "code": 2002
}
```

**Nota:** Esta acción no requiere los parámetros `plugin` ni `version`, a diferencia de otras acciones.

### 3. Obtener Configuración (Setup)

Obtén la configuración recomendada para tu versión del plugin:

```json
{
  "action": "setup",
  "plugin": "theme_fresk",
  "host": "https://tu-moodle.com",
  "version": "2025110401",
  "environment": {
    "version": "2025081101",
    "release": "4.5.1"
  }
  // Nota: También se acepta "site" para compatibilidad
}
```

**¿Cuándo usar?**
- Al instalar el plugin
- Al actualizar el plugin
- Para aplicar configuraciones recomendadas

**Respuesta exitosa:**
```json
{
  "success": true,
  "data": {
    "rules": {
      "enable_custom_css": true,
      "enable_analytics": false
    },
    "defaults": {
      "theme_color": "#007bff",
      "font_size": "14px"
    }
  }
}
```

**¿Cómo funciona la compatibilidad de versiones?**
- Si tu plugin es versión `2025110401` y existe configuración para `2025110401`, obtienes esa
- Si no existe exacta, obtienes la configuración de la versión compatible más alta (≤ tu versión)
- Ejemplo: Plugin `2025110501` puede usar configuración de `2025110401` si es la más alta disponible

### 4. Obtener Archivos SCSS

Obtén archivos SCSS para personalizar estilos (sistema tradicional):

```json
{
  "action": "scss",
  "plugin": "theme_fresk",
  "host": "https://tu-moodle.com",
  "version": "2025110401",
  "environment": {
    "version": "2025081101",
    "release": "4.5.1"
  }
  // Nota: También se acepta "site" para compatibilidad
}
```

**Obtener archivos específicos:**
```json
{
  "action": "scss",
  "plugin": "theme_fresk",
  "host": "https://tu-moodle.com",
  "version": "2025110401",
  "environment": {
    "version": "2025081101",
    "release": "4.5.1"
  }
  // Nota: También se acepta "site" para compatibilidad,
  "data": {
    "files": ["variables", "mixins"]
  }
}
```

**¿Cuándo usar?**
- Al cargar estilos personalizados
- Cuando el administrador modifica estilos desde el panel
- Para aplicar cambios de diseño

**Respuesta exitosa:**
```json
{
  "success": true,
  "data": {
    "files": [
      {
        "filename": "variables",
        "found": true,
        "content": "$primary-color: #007bff;\n$secondary-color: #6c757d;"
      },
      {
        "filename": "mixins",
        "found": true,
        "content": "@mixin button-style {\n  padding: 10px 20px;\n}"
      }
    ]
  }
}
```

**Procesamiento:**
1. Si no especificas `data.files`, obtienes TODOS los archivos de la versión compatible
2. Si especificas archivos, obtienes solo esos (incluso si no existen, con `found: false`)
3. Los archivos se buscan por nombre sin extensión (ej: `variables` busca `variables.scss`)

### 4.1. Obtener Archivos SCSS CDN

Obtén archivos SCSS CDN marcados como servibles con imports procesados automáticamente:

```json
{
  "action": "scss-cdn",
  "plugin": "theme_fresk",
  "host": "https://tu-moodle.com",
  "version": "2025110401",
  "environment": {
    "version": "2025081101",
    "release": "4.5.1"
  }
  // Nota: También se acepta "site" para compatibilidad
}
```

**¿Cuándo usar?**
- Para obtener archivos SCSS con estructura de carpetas compleja
- Cuando necesitas que los imports se procesen automáticamente con URLs firmadas
- Para archivos que se sirven como CDN con URLs temporales

**Respuesta exitosa:**
```json
{
  "success": true,
  "data": {
    "files": [
      {
        "filename": "main",
        "found": true,
        "content": "@import url('https://tu-dominio.com/api/cdn/scss/TOKEN_1H/variables.scss?signature=...');\n$primary-color: #007bff;"
      }
    ]
  }
}
```

**Características especiales:**
- Siempre devuelve todos los archivos marcados como servibles (no se pueden especificar archivos individuales)
- Los imports se procesan dinámicamente: cada `@import` se reemplaza por `@import url('URL_FIRMADA')`
- Las URLs firmadas tienen expiración de 1 hora
- El contenido procesado se genera en cada request (no se cachea)

**Diferencias con `scss`:**
- `scss`: Sistema tradicional, archivos individuales, sin procesamiento de imports
- `scss-cdn`: Sistema CDN, archivos con estructura de carpetas, imports procesados automáticamente

### 5. Obtener Archivos JavaScript

Obtén archivos JavaScript para funcionalidades adicionales:

```json
{
  "action": "js",
  "plugin": "theme_fresk",
  "host": "https://tu-moodle.com",
  "version": "2025110401",
  "environment": {
    "version": "2025081101",
    "release": "4.5.1"
  }
  // Nota: También se acepta "site" para compatibilidad
}
```

**Obtener archivos específicos:**
```json
{
  "action": "js",
  "plugin": "theme_fresk",
  "host": "https://tu-moodle.com",
  "version": "2025110401",
  "environment": {
    "version": "2025081101",
    "release": "4.5.1"
  }
  // Nota: También se acepta "site" para compatibilidad,
  "data": {
    "files": ["main", "utils"]
  }
}
```

**¿Cuándo usar?**
- Al cargar scripts personalizados
- Para funcionalidades JavaScript dinámicas
- Cuando se necesitan utilidades específicas

**Respuesta exitosa:**
```json
{
  "success": true,
  "data": {
    "files": [
      {
        "filename": "main",
        "found": true,
        "content": "console.log('Plugin loaded');\nfunction initTheme() {\n  // código\n}"
      }
    ]
  }
}
```

**Nota:** El funcionamiento es idéntico a SCSS, pero para archivos JavaScript.

### 5.1. Obtener Features (Funcionalidades)

Obtén las funcionalidades (features) publicadas de un producto. El sistema busca automáticamente la versión compatible de features (versión exacta o la más alta compatible menor o igual a la versión del plugin):

```json
{
  "action": "features",
  "plugin": "theme_fresk",
  "host": "https://tu-moodle.com",
  "version": "2025110401",
  "environment": {
    "version": "2025081101",
    "release": "4.5.1"
  }
  // Nota: También se acepta "site" para compatibilidad
}
```

**¿Cuándo usar?**
- Para mostrar funcionalidades del producto en Moodle
- Para crear páginas de características o documentación
- Cuando necesites información estructurada sobre las capacidades del producto

**Respuesta exitosa:**
```json
{
  "success": true,
  "error": "",
  "code": 0,
  "action": "features",
  "data": [
    {
      "title": "Apariencia del curso",
      "description": "Configuración visual del curso",
      "content_html": "<p>Contenido HTML de la funcionalidad...</p>",
      "thumbnail_url": "https://tu-dominio.com/storage/features/1/thumbnail_xxx.jpg",
      "header_url": "https://tu-dominio.com/storage/features/1/header_xxx.jpg",
      "sort_order": 1,
      "updated_at": "2026-01-13T10:30:00Z"
    },
    {
      "title": "Personalización avanzada",
      "description": "Opciones de personalización",
      "content_html": "<p>Más contenido...</p>",
      "thumbnail_url": null,
      "header_url": null,
      "sort_order": 2,
      "updated_at": "2026-01-14T15:45:00Z"
    }
  ]
}
```

**Características:**
- Busca automáticamente la versión compatible de features: primero versión exacta, luego la más alta compatible (≤ versión del plugin)
- Solo devuelve features con `status = published`
- Las features se ordenan automáticamente por `sort_order` (ascendente)
- Si la versión compatible no tiene features publicadas, devuelve `data: []` con `success: true`
- Las URLs de imágenes (`thumbnail_url`, `header_url`) son públicas y accesibles directamente
- El campo `content_html` contiene HTML sanitizado (sin iframes ni scripts)

**¿Cómo funciona la compatibilidad de versiones?**
- Si tu plugin es versión `2025110401` y existe versión de features `2025110401`, obtienes esa
- Si no existe exacta, obtienes la versión de features compatible más alta (≤ tu versión)
- Ejemplo: Plugin `2025110501` puede usar features de `2025110401` si es la más alta disponible

**Si la versión compatible no tiene features publicadas:**
```json
{
  "success": true,
  "error": "",
  "code": 0,
  "action": "features",
  "data": []
}
```

**Si no existe versión compatible de features:**
```json
{
  "success": false,
  "error": "No compatible features version found for this product version",
  "code": 3002,
  "action": "features",
  "data": {}
}
```

**Si el plugin no corresponde a ningún producto:**
```json
{
  "success": false,
  "error": "Product not validated",
  "code": 3000,
  "action": "features",
  "data": {}
}
```

### 5.2. Obtener Tutoriales (Vídeos)

Obtén los tutoriales (vídeos) publicados de un producto. El sistema busca automáticamente la versión compatible de tutoriales (versión exacta o la más alta compatible menor o igual a la versión del plugin):

```json
{
  "action": "tutorials",
  "plugin": "theme_fresk",
  "host": "https://tu-moodle.com",
  "version": "2025110401",
  "environment": {
    "version": "2025081101",
    "release": "4.5.1"
  }
  // Nota: También se acepta "site" para compatibilidad
}
```

**¿Cuándo usar?**
- Para mostrar tutoriales en vídeo del producto en Moodle
- Para crear secciones de ayuda o documentación con vídeos
- Cuando necesites mostrar guías visuales paso a paso

**Respuesta exitosa:**
```json
{
  "success": true,
  "error": "",
  "code": 0,
  "action": "tutorials",
  "data": [
    {
      "title": "Configuración inicial del tema",
      "desc": "Aprende a configurar el tema desde cero",
      "platform": "youtube",
      "videoid": "dQw4w9WgXcQ",
      "video_url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
      "embed_url": "https://www.youtube.com/embed/dQw4w9WgXcQ",
      "sort_order": 1,
      "updated_at": "2026-01-13T10:30:00Z"
    },
    {
      "title": "Personalización avanzada",
      "desc": "Tutorial sobre opciones avanzadas",
      "platform": "vimeo",
      "videoid": "123456789",
      "video_url": "https://vimeo.com/123456789",
      "embed_url": "https://player.vimeo.com/video/123456789",
      "sort_order": 2,
      "updated_at": "2026-01-14T15:45:00Z"
    }
  ]
}
```

**Características:**
- Busca automáticamente la versión compatible de tutoriales: primero versión exacta, luego la más alta compatible (≤ versión del plugin)
- Solo devuelve tutoriales con `status = published`
- Los tutoriales se ordenan automáticamente por `sort_order` (ascendente)
- Si la versión compatible no tiene tutoriales publicados, devuelve `data: []` con `success: true`
- Plataformas soportadas: `youtube` y `vimeo`
- Se proporcionan dos URLs:
  - `video_url`: URL completa para enlaces directos (abrir en nueva pestaña)
  - `embed_url`: URL para reproducir el vídeo embebido en un iframe

**¿Cómo funciona la compatibilidad de versiones?**
- Si tu plugin es versión `2025110401` y existe versión de tutoriales `2025110401`, obtienes esa
- Si no existe exacta, obtienes la versión de tutoriales compatible más alta (≤ tu versión)
- Ejemplo: Plugin `2025110501` puede usar tutoriales de `2025110401` si es la más alta disponible

**Si la versión compatible no tiene tutoriales publicados:**
```json
{
  "success": true,
  "error": "",
  "code": 0,
  "action": "tutorials",
  "data": []
}
```

**Si no existe versión compatible de tutoriales:**
```json
{
  "success": false,
  "error": "No compatible tutorials version found for this product version",
  "code": 4002,
  "action": "tutorials",
  "data": {}
}
```

**Si el plugin no corresponde a ningún producto:**
```json
{
  "success": false,
  "error": "Product not validated",
  "code": 4000,
  "action": "tutorials",
  "data": {}
}
```

**Ejemplo de uso con iframe:**
```html
<iframe src="{{tutorial.embed_url}}" frameborder="0" allowfullscreen></iframe>
```

**Ejemplo de uso con enlace:**
```html
<a href="{{tutorial.video_url}}" target="_blank">Ver tutorial en {{tutorial.platform}}</a>
```

### 5.3. Obtener Recursos (Material relacionado)

Obtén los recursos (material relacionado) publicados y públicos de un producto. El sistema busca automáticamente la versión compatible de recursos (versión exacta o la más alta compatible menor o igual a la versión del plugin):

```json
{
  "action": "resources",
  "plugin": "theme_fresk",
  "host": "https://tu-moodle.com",
  "version": "2025110401",
  "environment": {
    "version": "2025081101",
    "release": "4.5.1"
  }
  // Nota: También se acepta "site" para compatibilidad
}
```

**¿Cuándo usar?**
- Para mostrar material relacionado del producto en Moodle (PDFs, documentos, enlaces)
- Para crear secciones de recursos o documentación adicional
- Cuando necesites proporcionar archivos descargables o enlaces externos relacionados con el producto

**Respuesta exitosa:**
```json
{
  "success": true,
  "error": "",
  "code": 0,
  "action": "resources",
  "data": [
    {
      "title": "Guía de instalación",
      "description": "Documento PDF con instrucciones detalladas",
      "type": "file",
      "file_url": "https://tu-dominio.com/storage/resources/1/guia_instalacion_20260116115000_abc123.pdf",
      "original_filename": "guia_instalacion.pdf",
      "size": 524288,
      "mime": "application/pdf",
      "read_time": 300,
      "sort_order": 1,
      "updated_at": "2026-01-13T10:30:00Z"
    },
    {
      "title": "Documentación oficial",
      "description": "Enlace a la documentación completa",
      "type": "external",
      "url": "https://docs.ejemplo.com/theme_fresk",
      "read_time": 600,
      "sort_order": 2,
      "updated_at": "2026-01-14T15:45:00Z"
    }
  ]
}
```

**Características:**
- Busca automáticamente la versión compatible de recursos: primero versión exacta, luego la más alta compatible (≤ versión del plugin)
- Solo devuelve recursos con `status = published` y `is_public = true`
- Los recursos se ordenan automáticamente por `sort_order` (ascendente)
- Si la versión compatible no tiene recursos publicados, devuelve `data: []` con `success: true`
- Tipos de recurso soportados:
  - `file`: Archivos alojados en Laravel (PDF, DOC, DOCX, XLS, XLSX, PPT, PPTX, máx. 10MB)
  - `external`: Enlaces externos (URLs web)
- Para recursos tipo `file`: se incluye `file_url` (solo si `is_public = true`), `original_filename`, `size`, `mime`
- Para recursos tipo `external`: se incluye `url` directamente

**¿Cómo funciona la compatibilidad de versiones?**
- Si tu plugin es versión `2025110401` y existe versión de recursos `2025110401`, obtienes esa
- Si no existe exacta, obtienes la versión de recursos compatible más alta (≤ tu versión)
- Ejemplo: Plugin `2025110501` puede usar recursos de `2025110401` si es la más alta disponible

**Si la versión compatible no tiene recursos publicados:**
```json
{
  "success": true,
  "error": "",
  "code": 0,
  "action": "resources",
  "data": []
}
```

**Si no existe versión compatible de recursos:**
```json
{
  "success": false,
  "error": "No compatible resources version found for this product version",
  "code": 5002,
  "action": "resources",
  "data": {}
}
```

**Si el plugin no corresponde a ningún producto:**
```json
{
  "success": false,
  "error": "Product not validated",
  "code": 5000,
  "action": "resources",
  "data": {}
}
```

**Ejemplo de uso con archivo:**
```html
@if($resource['type'] === 'file' && $resource['file_url'])
    <a href="{{$resource['file_url']}}" target="_blank" download>
        Descargar: {{$resource['original_filename']}}
        @if($resource['size'])
            ({{number_format($resource['size'] / 1024, 2)}} KB)
        @endif
    </a>
@endif
```

**Ejemplo de uso con enlace externo:**
```html
@if($resource['type'] === 'external' && $resource['url'])
    <a href="{{$resource['url']}}" target="_blank">
        {{$resource['title']}} →
    </a>
@endif
```

### 6. Enviar Datos de Telemetría (Data)

Envía información sobre tu instalación de Moodle:

```json
{
  "action": "data",
  "plugin": "local_tresipunt",
  "host": "https://tu-moodle.com",
  "version": "2025110401",
  "environment": {
    "version": "2025081101",
    "release": "4.5.1"
  }
  // Nota: También se acepta "site" para compatibilidad,
  "data": {
    "courses": 150,
    "users": 5000,
    "activeusers": 3200,
    "enrolments": 12000,
    "moodlerelease": "4.5.1",
    "language": "es",
    "countrycode": "ES"
  }
}
```

**¿Cuándo usar?**
- Periódicamente (ej: diariamente o semanalmente)
- Para estadísticas y análisis
- Para soporte técnico

**Respuesta exitosa:**
```json
{
  "success": true,
  "data": {
    "received": true,
    "site_id": 3
  }
}
```

### 7. Enviar Información de Plugins

Informa sobre plugins instalados en tu Moodle:

```json
{
  "action": "plugins",
  "plugin": "local_tresipunt",
  "host": "https://tu-moodle.com",
  "version": "2025110401",
  "environment": {
    "version": "2025081101",
    "release": "4.5.1"
  }
  // Nota: También se acepta "site" para compatibilidad,
  "data": {
    "plugins": [
      {
        "name": "theme_fresk",
        "component": "theme_fresk",
        "type": "theme",
        "version": "2025110401",
        "release": "1.0.0"
      }
    ]
  }
}
```

**¿Cuándo usar?**
- Al instalar o actualizar plugins
- Para inventario de plugins
- Para compatibilidad y soporte

**Respuesta exitosa:**
```json
{
  "success": true,
  "data": {
    "processed": 1,
    "total": 1,
    "errors": []
  }
}
```

## Manejo de Errores

### Errores Comunes

#### Token No Válido (401)
```json
{
  "success": false,
  "error": "Token no válido",
  "code": 401
}
```
**Solución:** Verifica que el token sea correcto y esté activo en el panel.

#### Token Expirado (403)
```json
{
  "success": false,
  "error": "Token expirado. Fecha de expiración: 2025-01-01 00:00:00",
  "code": 403
}
```
**Solución:** Renueva el token desde el panel de administración.

#### Sin Licencia (401)
```json
{
  "success": false,
  "error": "Licence does not include this plugin",
  "code": 2001
}
```
**Solución:** Verifica que el plugin esté incluido en la licencia del token.

#### Versión No Compatible (404)
```json
{
  "success": false,
  "error": "No compatible SCSS version found for this product version",
  "code": 3002
}
```
**Solución:** 
- Verifica que exista una versión de archivos/configuración/features para tu versión del plugin
- O usa una versión del plugin que tenga archivos/configuración/features disponibles
- El sistema busca automáticamente la versión compatible más alta (≤ tu versión)

#### Límite de Peticiones Excedido (429)
```json
{
  "success": false,
  "error": "Límite de peticiones excedido. Intente nuevamente en 5 minuto(s)",
  "code": 429
}
```
**Solución:** Espera el tiempo indicado antes de volver a intentar.

## Mejores Prácticas

### 1. Caché de Respuestas

- **Licencia:** Cachea la respuesta por 1-24 horas (según tu política)
- **Setup:** Cachea hasta que se actualice el plugin
- **SCSS/JS:** Cachea pero verifica periódicamente si hay actualizaciones
- **Features:** Cachea pero verifica periódicamente si hay nuevas features o actualizaciones (ten en cuenta que las features están versionadas, así que cambian según la versión del plugin)
- **Tutoriales:** Cachea pero verifica periódicamente si hay nuevos tutoriales o actualizaciones (ten en cuenta que los tutoriales están versionadas, así que cambian según la versión del plugin)
- **Resources:** Cachea pero verifica periódicamente si hay nuevos recursos o actualizaciones (ten en cuenta que los recursos están versionados, así que cambian según la versión del plugin)
- **Data/Plugins:** No cachear, siempre enviar datos actuales

### 2. Manejo de Versiones

- Siempre envía la versión real de tu plugin
- El sistema buscará automáticamente la versión compatible
- No intentes "engañar" al sistema con versiones falsas

### 3. Manejo de Errores

- Implementa reintentos con backoff exponencial para errores temporales (429, 500)
- No reintentes errores de autorización (401, 403) sin intervención del usuario
- Registra errores para diagnóstico

### 4. Seguridad

- **Nunca** expongas el token en código del lado del cliente
- Usa HTTPS siempre
- Valida las respuestas antes de procesarlas
- No confíes ciegamente en los datos recibidos

### 5. Performance

- Haz peticiones asíncronas cuando sea posible
- Agrupa peticiones cuando puedas
- No hagas peticiones en cada carga de página si no es necesario

## Ejemplo de Implementación Completa

```php
// 1. Verificar licencia al iniciar
$licence = $api->call('licence', [
    'plugin' => 'theme_fresk',
    'version' => '2025110401',
    // ... otros campos
]);

if (!$licence['success']) {
    // Desactivar funcionalidades premium
    return;
}

// 2. Obtener configuración
$setup = $api->call('setup', [
    'plugin' => 'theme_fresk',
    'version' => '2025110401',
    // ...
]);

// Aplicar configuración
applyConfiguration($setup['data']);

// 3. Obtener archivos SCSS
$scss = $api->call('scss', [
    'plugin' => 'theme_fresk',
    'version' => '2025110401',
    'data' => ['files' => ['variables', 'custom']]
]);

// Procesar archivos SCSS
foreach ($scss['data']['files'] as $file) {
    if ($file['found']) {
        compileScss($file['filename'], $file['content']);
    }
}

// 4. Obtener archivos JS
$js = $api->call('js', [
    'plugin' => 'theme_fresk',
    'version' => '2025110401',
]);

// Cargar archivos JS
foreach ($js['data']['files'] as $file) {
    if ($file['found']) {
        loadJavaScript($file['filename'], $file['content']);
    }
}

// 4.1. Obtener features (funcionalidades)
$features = $api->call('features', [
    'plugin' => 'theme_fresk',
    'version' => '2025110401',
]);

// Mostrar features en la interfaz
foreach ($features['data'] as $feature) {
    displayFeature($feature);
}

// 4.2. Obtener tutoriales (vídeos)
$tutorials = $api->call('tutorials', [
    'plugin' => 'theme_fresk',
    'version' => '2025110401',
]);

// Mostrar tutoriales en la interfaz
foreach ($tutorials['data'] as $tutorial) {
    displayTutorial($tutorial); // Usar $tutorial['embed_url'] para iframe o $tutorial['video_url'] para enlace
}

// 4.3. Obtener recursos (material relacionado)
$resources = $api->call('resources', [
    'plugin' => 'theme_fresk',
    'version' => '2025110401',
]);

// Mostrar recursos en la interfaz
foreach ($resources['data'] as $resource) {
    if ($resource['type'] === 'file' && isset($resource['file_url'])) {
        displayFileResource($resource); // Mostrar enlace de descarga
    } elseif ($resource['type'] === 'external' && isset($resource['url'])) {
        displayExternalResource($resource); // Mostrar enlace externo
    }
}

// 5. Enviar telemetría (en tarea programada)
$api->call('data', [
    'plugin' => 'local_tresipunt',
    'data' => [
        'courses' => get_course_count(),
        'users' => get_user_count(),
        // ...
    ]
]);
```

## Preguntas Frecuentes

### ¿Qué pasa si no hay versión exacta de archivos?

El sistema busca automáticamente la versión compatible más alta que sea menor o igual a tu versión del plugin. Por ejemplo:
- Plugin versión `2025110501`
- Archivos disponibles: `2025110401`, `2025110301`, `2025100101`
- Obtendrás los archivos de `2025110401` (la más alta compatible)

### ¿Puedo obtener archivos de una versión específica?

No directamente. El sistema siempre busca la versión compatible. Si necesitas una versión específica, debes usar esa versión del plugin.

### ¿Qué pasa si un archivo no existe?

Si solicitas archivos específicos y uno no existe, recibirás:
```json
{
  "filename": "archivo_inexistente",
  "found": false,
  "content": null
}
```

El sistema no falla, simplemente indica que el archivo no se encontró.

### ¿Con qué frecuencia debo verificar la licencia?

Recomendamos:
- Al iniciar el plugin: siempre
- Durante el uso: cada 24 horas (cacheado)
- Antes de funcionalidades premium: siempre

### ¿Cómo se crea un entorno nuevo?

Los entornos NO se crean mediante la API. Deben ser creados previamente desde el panel de administración del Manager. Una vez creado, puedes usar la acción `sync` para actualizar su información.

### ¿Puedo usar la API sin token?

No. Todas las peticiones requieren un token válido excepto algunas acciones específicas que pueden tener validaciones diferentes.

## Soporte

Para problemas o dudas:
1. Revisa los códigos de error en la documentación técnica
2. Verifica que tu token esté activo y no expirado
3. Contacta al equipo de soporte con:
   - El código de error recibido
   - El `action` que estabas ejecutando
   - La versión de tu plugin

---

**Última actualización:** Diciembre 2025

