Endpoints de Tickets

El módulo de ticketing expone una API REST bajo /tickets/api/ para gestión completa de soporte técnico, incluyendo tickets, departamentos, mensajes, notas internas, asignación de agentes y acciones de flujo de trabajo.

Tickets — /tickets/api/tickets/

Gestión principal de tickets de soporte. Los clientes solo ven sus propios tickets; los agentes (staff/superuser) ven todos.

Métodos

Método

Endpoint

Descripción

GET

/tickets/api/tickets/

Listar tickets (con filtros)

POST

/tickets/api/tickets/

Crear nuevo ticket

GET

/tickets/api/tickets/{id}/

Detalle de ticket con mensajes

PUT

/tickets/api/tickets/{id}/

Actualizar ticket

DELETE

/tickets/api/tickets/{id}/

Eliminar ticket

Acciones de Ticket

Método

Endpoint

Descripción

POST

/tickets/api/tickets/{id}/reply/

Añadir respuesta al ticket

POST

/tickets/api/tickets/{id}/note/

Añadir nota interna (solo agentes)

POST

/tickets/api/tickets/{id}/assign/

Asignar ticket a un agente

POST

/tickets/api/tickets/{id}/resolve/

Marcar como resuelto

POST

/tickets/api/tickets/{id}/close/

Cerrar ticket

POST

/tickets/api/tickets/{id}/reopen/

Reabrir ticket cerrado/resuelto

Filtros disponibles

  • ?status=open — Filtrar por estado (new, open, pending, on_hold, resolved, closed)

  • ?priority=high — Filtrar por prioridad (low, medium, high, urgent, critical)

  • ?department=soporte — Filtrar por slug de departamento

  • ?assigned_to=me — Tickets asignados al usuario actual

  • ?assigned_to=unassigned — Tickets sin asignar

Ejemplo — Crear ticket:

curl -X POST https://panel.example.com/tickets/api/tickets/ \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "subject": "No puedo acceder a mi sitio web",
    "priority": "high",
    "department": 1
  }'

Respuesta (201 Created):

{
  "id": "e5f6a7b8-c9d0-1234-5678-9abcdef01234",
  "number": "TK-000042",
  "subject": "No puedo acceder a mi sitio web",
  "tenant": 1,
  "requester": 5,
  "requester_email": "cliente@example.com",
  "requester_name": "Juan Perez",
  "assigned_to": null,
  "department": 1,
  "status": "new",
  "priority": "high",
  "source": "api",
  "tags": [],
  "sla_policy": null,
  "sla_first_response_due": null,
  "sla_resolution_due": null,
  "first_responded_at": null,
  "resolved_at": null,
  "closed_at": null,
  "messages": [],
  "created_at": "2026-02-08T10:00:00Z",
  "updated_at": "2026-02-08T10:00:00Z"
}

Ejemplo — Listar tickets abiertos:

curl -X GET "https://panel.example.com/tickets/api/tickets/?status=open" \
  -H "Authorization: Bearer $TOKEN"

Ejemplo — Responder a un ticket:

curl -X POST https://panel.example.com/tickets/api/tickets/e5f6a7b8-c9d0-1234-5678-9abcdef01234/reply/ \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "body": "Hemos revisado el servidor y el problema era un error de DNS. Ya está corregido. Por favor, verifica si puedes acceder ahora."
  }'

Respuesta (201):

{
  "id": 15,
  "ticket": "e5f6a7b8-c9d0-1234-5678-9abcdef01234",
  "author": 1,
  "author_email": "agente@noxpanel.com",
  "author_name": "Admin NoxPanel",
  "message_type": "reply",
  "body": "Hemos revisado el servidor y el problema era un error de DNS. Ya está corregido. Por favor, verifica si puedes acceder ahora.",
  "body_html": "",
  "is_from_agent": true,
  "created_at": "2026-02-08T10:15:00Z"
}

Ejemplo — Añadir nota interna:

curl -X POST https://panel.example.com/tickets/api/tickets/e5f6a7b8-c9d0-1234-5678-9abcdef01234/note/ \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "body": "El DNS apuntaba a la IP antigua. Actualizado registro A a 203.0.113.10."
  }'

Ejemplo — Asignar ticket:

# Asignar a uno mismo
curl -X POST https://panel.example.com/tickets/api/tickets/{id}/assign/ \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json"

# Asignar a otro agente
curl -X POST https://panel.example.com/tickets/api/tickets/{id}/assign/ \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"agent_id": 3}'

Ejemplo — Resolver y cerrar:

# Resolver
curl -X POST https://panel.example.com/tickets/api/tickets/{id}/resolve/ \
  -H "Authorization: Bearer $TOKEN"

# Cerrar
curl -X POST https://panel.example.com/tickets/api/tickets/{id}/close/ \
  -H "Authorization: Bearer $TOKEN"

Departamentos — /tickets/api/departments/

Gestión de departamentos de soporte. Lectura para todos los autenticados, escritura solo para agentes (staff/superuser).

Métodos

Método

Endpoint

Descripción

GET

/tickets/api/departments/

Listar departamentos

POST

/tickets/api/departments/

Crear departamento (agente)

GET

/tickets/api/departments/{slug}/

Detalle por slug

PUT

/tickets/api/departments/{slug}/

Actualizar departamento

DELETE

/tickets/api/departments/{slug}/

Eliminar departamento

Respuesta:

{
  "id": 1,
  "name": "Soporte Técnico",
  "slug": "soporte-tecnico",
  "description": "Problemas técnicos con hosting, DNS, email y servidores",
  "email": "soporte@noxpanel.com",
  "manager": 1,
  "is_active": true
}

Estados de Ticket

Un ticket pasa por los siguientes estados durante su ciclo de vida:

Estado

Descripción

new

Recién creado, sin primera respuesta

open

Abierto y en proceso de atención

pending

Pendiente de respuesta del cliente

on_hold

En espera (dependencia externa)

resolved

Resuelto, pendiente de confirmación

closed

Cerrado definitivamente

Prioridades

Prioridad

Valor

Uso recomendado

low

Baja

Consultas generales, mejoras

medium

Media

Problemas que no afectan producción

high

Alta

Problemas que afectan a la operativa

urgent

Urgente

Servicio degradado en producción

critical

Crítica

Servicio caído, pérdida de datos

Orígenes del Ticket

Los tickets pueden crearse desde diferentes fuentes:

  • web — Panel web de NoxPanel

  • email — Email recibido (IMAP/OAuth2) procesado automáticamente

  • api — Creado vía API REST

  • phone — Registrado manualmente desde llamada telefónica

SLA (Service Level Agreement)

El sistema de SLA permite definir tiempos máximos de respuesta y resolución según la prioridad. Las políticas SLA se asignan automáticamente al ticket según su prioridad.

Las tareas de Celery verifican periódicamente si hay incumplimientos de SLA:

  • check-sla-breaches: Cada 15 minutos

  • auto-close-resolved-tickets: Diariamente (cierra tickets resueltos tras X días)