codigo0/docs/API_ENDPOINTS_ESPECIFICACION.md

11 KiB

🔌 ESPECIFICACIÓN API REST - SERVIDOR DE CONTENIDO TES

Versión: 1.0.0
Fecha: 2025-01-06
Base URL: https://servidor-tes.com/api (ejemplo)


📋 ÍNDICE

  1. API Pública (App PWA)
  2. API Admin (Panel Admin)
  3. Códigos de Estado
  4. Formato de Respuestas
  5. Rate Limiting

API PÚBLICA (APP PWA)

Endpoints de Solo Lectura

1. Health Check

GET /api/health

Descripción: Verifica estado del servidor y base de datos.

Autenticación: No requerida

Respuesta 200:

{
  "status": "ok",
  "timestamp": "2025-01-06T12:00:00Z",
  "database": "connected",
  "latest_pack_version": "1.0.0",
  "latest_pack_hash": "sha256:abc123...",
  "server_version": "1.0.0"
}

Respuesta 503 (si BD desconectada):

{
  "status": "error",
  "timestamp": "2025-01-06T12:00:00Z",
  "database": "disconnected",
  "message": "Base de datos no disponible"
}

2. Content Pack Latest

GET /api/content/pack/latest

Descripción: Obtiene el Content Pack más reciente (solo contenido publicado).

Autenticación: No requerida

Headers:

  • If-None-Match: <hash> - Si el hash coincide, retorna 304 Not Modified

Respuesta 200:

{
  "metadata": {
    "version": "1.0.0",
    "generated_at": "2025-01-06T12:00:00Z",
    "hash": "sha256:abc123...",
    "total_items": 45,
    "total_resources": 120
  },
  "content": { ... },
  "media": { ... },
  "links": { ... }
}

Headers de Respuesta:

  • ETag: <hash> - Hash del pack
  • Content-Type: application/json
  • Cache-Control: public, max-age=3600 - Cache 1 hora

Respuesta 304: Not Modified (si If-None-Match coincide)

Respuesta 404: No hay pack disponible


3. Content Pack por Versión

GET /api/content/pack/:version

Descripción: Obtiene un Content Pack específico por versión.

Parámetros:

  • version (path) - Versión semántica (ej: "1.0.0")

Ejemplo:

GET /api/content/pack/1.0.0

Respuesta 200: Igual que /pack/latest

Respuesta 404: Versión no encontrada


4. Protocolo Individual

GET /api/content/protocol/:slug

Descripción: Obtiene un protocolo específico con sus recursos asociados.

Parámetros:

  • slug (path) - Slug del protocolo (ej: "rcp-adulto-svb")

Ejemplo:

GET /api/content/protocol/rcp-adulto-svb

Respuesta 200:

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "type": "protocol",
  "slug": "rcp-adulto-svb",
  "title": "RCP Adulto - Soporte Vital Básico",
  "short_title": "RCP Adulto SVB",
  "description": "Protocolo de reanimación cardiopulmonar básica en adultos",
  "clinical_context": "RCP",
  "level": "operativo",
  "priority": "critica",
  "status": "published",
  "version": "1.0.0",
  "content": {
    "steps": [...],
    "checklist": {...},
    "warnings": [...],
    "key_points": [...]
  },
  "resources": {
    "images": [
      {
        "id": "...",
        "title": "Posición de Manos - RCP Adulto",
        "url": "https://servidor-tes.com/media/images/rcp/...",
        "alt_text": "...",
        "section": "pasos",
        "position": 7
      }
    ],
    "videos": [
      {
        "id": "...",
        "title": "RCP Adulto SVB - Técnica Completa",
        "url": "https://servidor-tes.com/media/videos/rcp/...",
        "duration_seconds": 45,
        "section": "pasos",
        "position": 0
      }
    ]
  },
  "related": {
    "guide_id": "550e8400-...",
    "guide_slug": "rcp-adulto-svb-formativo",
    "manual_ids": ["..."],
    "related_protocol_ids": ["..."]
  }
}

Respuesta 404: Protocolo no encontrado o no publicado


5. Guía Individual

GET /api/content/guide/:slug

Descripción: Obtiene una guía formativa completa con sus 8 secciones.

Parámetros:

  • slug (path) - Slug de la guía (ej: "abcde-operativo")

Respuesta 200:

{
  "id": "...",
  "type": "guide",
  "slug": "abcde-operativo",
  "title": "ABCDE Operativo",
  "level": "formativo",
  "content": {
    "sections": [
      {
        "numero": 1,
        "titulo": "Introducción y Contexto",
        "markdown": "# Introducción...",
        "resources": {
          "images": [...],
          "videos": [...]
        }
      },
      // ... 7 secciones más
    ],
    "related_protocol_id": "...",
    "related_manual_ids": [...]
  },
  "resources": {
    "images": [...],
    "videos": [...]
  }
}

6. Recurso Multimedia

GET /api/content/media/:id

Descripción: Obtiene información de un recurso multimedia o redirige al archivo.

Parámetros:

  • id (path) - UUID del recurso

Query Params:

  • download (boolean) - Si true, fuerza descarga

Respuesta 200 (JSON si no download):

{
  "id": "...",
  "type": "image",
  "title": "Posición de Manos - RCP Adulto",
  "url": "https://servidor-tes.com/media/images/rcp/rcp_posicion_manos_adulto.png",
  "alt_text": "...",
  "width": 1200,
  "height": 800,
  "file_size": 245678
}

Respuesta 302 (Redirect si download):

  • Redirige a URL del archivo

Respuesta 404: Recurso no encontrado


API ADMIN (PANEL ADMIN)

Autenticación

Login

POST /api/admin/auth/login

Body:

{
  "email": "admin@emerges-tes.local",
  "password": "Admin123!"
}

Respuesta 200:

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "user": {
    "id": "...",
    "email": "admin@emerges-tes.local",
    "username": "admin",
    "role": "super_admin"
  },
  "expiresIn": 86400
}

Respuesta 401: Credenciales inválidas


Me (Usuario Actual)

GET /api/admin/auth/me

Autenticación: Requerida (Bearer Token)

Respuesta 200:

{
  "user": {
    "id": "...",
    "email": "...",
    "username": "...",
    "role": "...",
    "is_active": true
  }
}

Contenido

Listar Contenido

GET /api/admin/content

Query Params:

  • type - Filtrar por tipo (protocol, guide, manual, drug, checklist)
  • status - Filtrar por estado (draft, in_review, approved, published)
  • priority - Filtrar por prioridad (critica, alta, media, baja)
  • search - Búsqueda de texto
  • page - Número de página (default: 1)
  • limit - Items por página (default: 20)

Respuesta 200:

{
  "items": [...],
  "total": 45,
  "page": 1,
  "limit": 20,
  "totalPages": 3
}

Obtener Contenido

GET /api/admin/content/:id

Respuesta 200: ContentItem completo


Crear Contenido

POST /api/admin/content

Body:

{
  "type": "protocol",
  "slug": "rcp-adulto-svb",
  "title": "RCP Adulto - Soporte Vital Básico",
  "clinical_context": "RCP",
  "level": "operativo",
  "priority": "critica",
  "source_guideline": "ERC",
  "content": {
    "steps": [...],
    "checklist": {...}
  },
  "tags": ["rcp", "svb", "adulto"]
}

Respuesta 201:

{
  "id": "...",
  "message": "Contenido creado correctamente"
}

Actualizar Contenido

PUT /api/admin/content/:id

Body: Mismo formato que crear

Respuesta 200:

{
  "id": "...",
  "message": "Contenido actualizado correctamente",
  "version": "1.1.0"
}

Publicar Contenido

POST /api/admin/content/:id/publish

Descripción: Cambia status a 'published' y genera nueva versión.

Respuesta 200:

{
  "id": "...",
  "status": "published",
  "version": "1.0.0",
  "message": "Contenido publicado correctamente"
}

Solicitar Validación

POST /api/admin/content/:id/validate

Body:

{
  "comments": "Revisado y aprobado",
  "validator_role": "tes"
}

Respuesta 200:

{
  "id": "...",
  "status": "approved",
  "validated_by": "...",
  "validated_at": "2025-01-06T12:00:00Z"
}

Recursos Multimedia

Listar Recursos

GET /api/admin/media

Query Params:

  • type - image | video
  • status - draft | approved | published
  • block - Filtrar por bloque
  • search - Búsqueda

Upload Recurso

POST /api/admin/media/upload

Content-Type: multipart/form-data

Body:

  • file - Archivo (imagen o vídeo)
  • title - Título
  • alt_text - Texto alternativo
  • description - Descripción
  • tags - Tags (JSON array)
  • block - Bloque temático
  • priority - critica | alta | media | baja
  • usage_type - operativo | formativo | referencia (puede ser array)

Respuesta 201:

{
  "id": "...",
  "filename": "rcp_posicion_manos_adulto.png",
  "path": "/media/images/rcp/rcp_posicion_manos_adulto.png",
  "url": "https://servidor-tes.com/media/images/rcp/...",
  "file_size": 245678,
  "message": "Recurso subido correctamente"
}

Asociar Recurso a Contenido

POST /api/admin/media/:id/associate

Body:

{
  "content_item_id": "...",
  "section": "pasos",
  "position": 7,
  "placement": "inline",
  "caption": "Posición correcta de manos",
  "is_critical": true,
  "priority": "critica"
}

Content Pack

Generar Pack

POST /api/admin/pack/generate

Body:

{
  "version": "1.0.0",
  "include_draft": false,
  "notes": "Primera versión del pack"
}

Respuesta 200:

{
  "version": "1.0.0",
  "file_path": "/storage/packs/pack-v1.0.0.json",
  "file_url": "https://servidor-tes.com/api/content/pack/1.0.0",
  "hash": "sha256:abc123...",
  "size_bytes": 5242880,
  "total_items": 45,
  "total_resources": 120,
  "generated_at": "2025-01-06T12:00:00Z"
}

Listar Versiones

GET /api/admin/pack/versions

Respuesta 200:

{
  "versions": [
    {
      "version": "1.0.0",
      "generated_at": "2025-01-06T12:00:00Z",
      "size_bytes": 5242880,
      "total_items": 45,
      "is_latest": true
    },
    {
      "version": "0.9.0",
      "generated_at": "2025-01-05T10:00:00Z",
      "size_bytes": 4890123,
      "total_items": 42,
      "is_latest": false
    }
  ]
}

CÓDIGOS DE ESTADO

Código Significado Uso
200 OK Operación exitosa
201 Created Recurso creado
304 Not Modified Pack sin cambios (If-None-Match)
400 Bad Request Datos inválidos
401 Unauthorized No autenticado o token inválido
403 Forbidden Sin permisos
404 Not Found Recurso no encontrado
409 Conflict Conflicto (ej: slug duplicado)
422 Unprocessable Entity Validación fallida
429 Too Many Requests Rate limit excedido
500 Internal Server Error Error del servidor
503 Service Unavailable Servicio no disponible (BD desconectada)

FORMATO DE RESPUESTAS

Respuesta Exitosa

{
  "data": { ... },
  "meta": {
    "timestamp": "2025-01-06T12:00:00Z"
  }
}

Respuesta de Error

{
  "error": {
    "code": "CONTENT_NOT_FOUND",
    "message": "Contenido no encontrado",
    "details": {
      "id": "...",
      "slug": "rcp-adulto-svb"
    }
  },
  "meta": {
    "timestamp": "2025-01-06T12:00:00Z"
  }
}

RATE LIMITING

API Pública (App)

  • Límite: 100 requests/minuto por IP
  • Headers:
    • X-RateLimit-Limit: 100
    • X-RateLimit-Remaining: 95
    • X-RateLimit-Reset: 1641475200

API Admin

  • Límite: 50 requests/minuto por usuario
  • Headers: Mismo formato

Respuesta 429:

{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Demasiadas solicitudes. Intenta de nuevo en 60 segundos."
  },
  "retryAfter": 60
}

Fin de la Especificación