Files
service_manager/docs/api-contract.md
2026-01-12 08:17:17 -07:00

11 KiB

API Contract - ServiceManagerWeb

Mesa de Ayuda B2B - Especificación de Endpoints

Base URL

  • Desarrollo: http://localhost:8000
  • Producción: https://api.servicemanager.aduanasoft.com

Versionado

  • Todos los endpoints tienen prefijo /v1/
  • Versionado en URL path (no headers)

Autenticación

  • JWT Bearer Token en header Authorization: Bearer <token>
  • Refresh token para renovación automática

Headers Estándar

Authorization: Bearer <jwt_token>
Content-Type: application/json
X-Tenant-ID: <tenant_uuid>  # Requerido para endpoints multi-tenant
X-Correlation-ID: <uuid>    # Opcional para tracking
Accept-Language: es-ES      # Para internacionalización

Responses Estándar

Éxito (2xx)

{
  "success": true,
  "data": { ... },
  "message": "Operación exitosa",
  "metadata": {
    "page": 1,
    "per_page": 20,
    "total": 150,
    "total_pages": 8
  }
}

Error (4xx/5xx)

{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Datos inválidos",
    "details": [
      {
        "field": "email",
        "message": "Email inválido"
      }
    ]
  },
  "correlation_id": "uuid"
}

DOMINIO: AUTH

POST /v1/auth/login

Descripción: Autenticación de usuario
Público: Sí

Request Body:

{
  "email": "user@example.com",
  "password": "password123",
  "tenant_slug": "aduanasoft-demo",
  "totp_code": "123456"  // opcional, solo si 2FA activado
}

Response 200:

{
  "success": true,
  "data": {
    "access_token": "jwt_token",
    "refresh_token": "refresh_token",
    "expires_in": 3600,
    "user": {
      "id": "uuid",
      "email": "user@example.com",
      "first_name": "Juan",
      "last_name": "Pérez",
      "role": "AGENT",
      "tenant": {
        "id": "uuid",
        "name": "Aduanasoft Demo",
        "slug": "aduanasoft-demo"
      }
    }
  }
}

POST /v1/auth/refresh

Descripción: Renovar access token
Público: Sí

Request Body:

{
  "refresh_token": "refresh_token"
}

POST /v1/auth/logout

Descripción: Cerrar sesión (revoca refresh token)
Autenticado: Sí

GET /v1/auth/me

Descripción: Información del usuario actual
Autenticado: Sí

PUT /v1/auth/me

Descripción: Actualizar perfil propio
Autenticado: Sí

Request Body:

{
  "first_name": "Juan",
  "last_name": "Pérez",
  "language": "es",
  "timezone": "America/Mexico_City",
  "notifications_email": true
}

POST /v1/auth/change-password

Descripción: Cambiar contraseña
Autenticado: Sí

POST /v1/auth/2fa/setup

Descripción: Configurar 2FA (solo roles internos)
Autenticado: Sí, Roles: ADMIN, SUPPORT_MANAGER, AGENT, AUDITOR

POST /v1/auth/2fa/verify

Descripción: Verificar código 2FA durante setup
Autenticado: Sí


DOMINIO: TENANTS

GET /v1/tenants/current

Descripción: Información del tenant actual
Autenticado: Sí

PUT /v1/tenants/current

Descripción: Actualizar tenant (solo CLIENT_ADMIN/ADMIN)
Autenticado: Sí, Roles: CLIENT_ADMIN, ADMIN

GET /v1/tenants (solo ADMIN)

Descripción: Listar todos los tenants
Autenticado: Sí, Roles: ADMIN

POST /v1/tenants (solo ADMIN)

Descripción: Crear nuevo tenant
Autenticado: Sí, Roles: ADMIN


DOMINIO: USERS

GET /v1/users

Descripción: Listar usuarios del tenant
Autenticado: Sí
Roles: Todos (filtros por rol)

Query Params:

?page=1&per_page=20&role=AGENT&is_active=true&search=juan

Response 200:

{
  "success": true,
  "data": [
    {
      "id": "uuid",
      "email": "agent@example.com",
      "first_name": "Juan",
      "last_name": "Agente",
      "role": "AGENT",
      "is_active": true,
      "email_verified": true,
      "last_login": "2024-01-15T10:30:00Z",
      "created_at": "2024-01-01T00:00:00Z"
    }
  ],
  "metadata": {
    "page": 1,
    "per_page": 20,
    "total": 150,
    "total_pages": 8
  }
}

POST /v1/users

Descripción: Crear usuario
Autenticado: Sí, Roles: ADMIN, SUPPORT_MANAGER, CLIENT_ADMIN

Request Body:

{
  "email": "nuevo@example.com",
  "first_name": "Nuevo",
  "last_name": "Usuario",
  "role": "AGENT",
  "password": "temporal123",  // opcional, se genera automáticamente
  "send_welcome_email": true
}

GET /v1/users/{user_id}

Descripción: Obtener usuario específico
Autenticado: Sí

PUT /v1/users/{user_id}

Descripción: Actualizar usuario
Autenticado: Sí, Roles: ADMIN, SUPPORT_MANAGER, CLIENT_ADMIN

DELETE /v1/users/{user_id}

Descripción: Desactivar usuario (soft delete)
Autenticado: Sí, Roles: ADMIN, SUPPORT_MANAGER, CLIENT_ADMIN


DOMINIO: TICKETS

GET /v1/tickets

Descripción: Listar tickets con filtros
Autenticado: Sí

Query Params:

?page=1&per_page=20
&status=NEW,IN_PROGRESS
&priority=HIGH,URGENT
&assigned_to=uuid
&created_by=uuid
&category_id=uuid
&search=problema+conexion
&sort=created_at_desc
&date_from=2024-01-01
&date_to=2024-01-31

Response 200:

{
  "success": true,
  "data": [
    {
      "id": "uuid",
      "ticket_number": "TKT-2024-000001",
      "subject": "Problema de conexión",
      "status": "IN_PROGRESS",
      "priority": "HIGH",
      "category": {
        "id": "uuid",
        "name": "Soporte Técnico"
      },
      "created_by": {
        "id": "uuid",
        "first_name": "Juan",
        "last_name": "Cliente"
      },
      "assigned_to": {
        "id": "uuid",
        "first_name": "Ana",
        "last_name": "Soporte"
      },
      "sla_response_due": "2024-01-15T12:00:00Z",
      "sla_resolution_due": "2024-01-16T10:00:00Z",
      "created_at": "2024-01-15T10:00:00Z",
      "updated_at": "2024-01-15T11:30:00Z"
    }
  ],
  "metadata": {
    "page": 1,
    "per_page": 20,
    "total": 150,
    "total_pages": 8
  }
}

POST /v1/tickets

Descripción: Crear nuevo ticket
Autenticado: Sí

Request Body:

{
  "subject": "Problema de conexión con el sistema",
  "description": "Descripción detallada del problema...",
  "priority": "HIGH",
  "category_id": "uuid",
  "affected_system_id": "uuid",
  "attachments": [
    {
      "filename": "screenshot.png",
      "content_type": "image/png",
      "content_base64": "base64_data"
    }
  ]
}

Response 201:

{
  "success": true,
  "data": {
    "id": "uuid",
    "ticket_number": "TKT-2024-000001",
    "subject": "Problema de conexión con el sistema",
    "status": "NEW",
    "sla_response_due": "2024-01-15T12:00:00Z",
    "created_at": "2024-01-15T10:00:00Z"
  }
}

GET /v1/tickets/{ticket_id}

Descripción: Obtener ticket completo con comentarios
Autenticado: Sí

Response 200:

{
  "success": true,
  "data": {
    "id": "uuid",
    "ticket_number": "TKT-2024-000001",
    "subject": "Problema de conexión",
    "description": "Descripción completa...",
    "status": "IN_PROGRESS",
    "priority": "HIGH",
    "category": {...},
    "affected_system": {...},
    "created_by": {...},
    "assigned_to": {...},
    "attachments": [...],
    "comments": [
      {
        "id": "uuid",
        "content": "Comentario del ticket...",
        "author": {...},
        "is_internal": false,
        "attachments": [...],
        "created_at": "2024-01-15T11:00:00Z"
      }
    ],
    "status_history": [...],
    "sla_metrics": {
      "response_due": "2024-01-15T12:00:00Z",
      "resolution_due": "2024-01-16T10:00:00Z",
      "first_response_at": "2024-01-15T11:15:00Z",
      "response_sla_met": true,
      "resolution_sla_met": null
    },
    "created_at": "2024-01-15T10:00:00Z",
    "updated_at": "2024-01-15T11:30:00Z"
  }
}

PUT /v1/tickets/{ticket_id}

Descripción: Actualizar ticket (estado, asignación, etc.)
Autenticado: Sí

Request Body:

{
  "status": "IN_PROGRESS",
  "assigned_to": "uuid",
  "priority": "URGENT",
  "comment": "Escalando por alta prioridad"
}

POST /v1/tickets/{ticket_id}/comments

Descripción: Agregar comentario al ticket
Autenticado: Sí

Request Body:

{
  "content": "Comentario con solución propuesta...",
  "is_internal": false,
  "attachments": [
    {
      "filename": "solution.pdf",
      "content_type": "application/pdf",
      "content_base64": "base64_data"
    }
  ]
}

PUT /v1/tickets/{ticket_id}/rating

Descripción: Calificar ticket resuelto (solo cliente)
Autenticado: Sí, Roles: CLIENT_ADMIN, CLIENT_USER

Request Body:

{
  "rating": 5,
  "comment": "Excelente atención y resolución rápida"
}

DOMINIO: CATEGORIES & SYSTEMS

GET /v1/categories

Descripción: Listar categorías del tenant
Autenticado: Sí

POST /v1/categories (solo staff interno)

Descripción: Crear categoría
Autenticado: Sí, Roles: ADMIN, SUPPORT_MANAGER

GET /v1/affected-systems

Descripción: Listar sistemas afectados
Autenticado: Sí


DOMINIO: NOTIFICATIONS

GET /v1/notifications/templates (solo staff interno)

Descripción: Listar templates de email
Autenticado: Sí, Roles: ADMIN, SUPPORT_MANAGER

POST /v1/notifications/test-email (solo ADMIN)

Descripción: Enviar email de prueba
Autenticado: Sí, Roles: ADMIN


DOMINIO: REPORTS & ANALYTICS

GET /v1/reports/dashboard

Descripción: Métricas del dashboard
Autenticado: Sí

Response 200:

{
  "success": true,
  "data": {
    "tickets": {
      "total": 150,
      "new": 12,
      "in_progress": 45,
      "waiting_customer": 8,
      "resolved_today": 15
    },
    "sla": {
      "response_rate": 95.5,
      "resolution_rate": 87.2
    },
    "agents": {
      "active": 8,
      "avg_load": 5.6
    },
    "csat": {
      "average": 4.2,
      "total_responses": 89
    }
  }
}

GET /v1/reports/tickets

Descripción: Reporte de tickets con filtros
Autenticado: Sí


DOMINIO: AUDIT

GET /v1/audit/logs (solo AUDITOR/ADMIN)

Descripción: Consultar logs de auditoría
Autenticado: Sí, Roles: AUDITOR, ADMIN

Query Params:

?page=1&per_page=50
&action=ticket.create,ticket.assign
&user_id=uuid
&resource_type=ticket
&date_from=2024-01-01
&date_to=2024-01-31

CÓDIGOS DE ERROR ESTÁNDAR

  • 400 - Bad Request (datos inválidos)
  • 401 - Unauthorized (no autenticado)
  • 403 - Forbidden (sin permisos)
  • 404 - Not Found (recurso no encontrado)
  • 409 - Conflict (recurso duplicado)
  • 422 - Unprocessable Entity (validación fallida)
  • 429 - Too Many Requests (rate limit)
  • 500 - Internal Server Error

RATE LIMITING

  • Auth endpoints: 10 req/min por IP
  • API endpoints: 100 req/min por usuario
  • File uploads: 5 req/min por usuario

PAGINACIÓN

  • Default: per_page=20, max=100
  • Links de navegación en metadata
  • Total count incluido cuando sea eficiente

ORDENAMIENTO

Formato: ?sort=field_direction

  • created_at_desc (default)
  • updated_at_desc
  • priority_desc
  • status_asc

BÚSQUEDA

  • Full-text search en subject y description
  • Búsqueda por número de ticket exacto
  • Filtros combinables con AND lógico