Diferencia entre revisiones de «API Modulo Forms»

De WikiSerpi
Ir a la navegación Ir a la búsqueda
v1
Sin resumen de edición
 
(No se muestra una edición intermedia del mismo usuario)
Línea 1: Línea 1:
== ⚡ Referencia de Endpoints ==


= SERPI Forms Core API (v1) =
A continuación, los servicios expuestos organizados por método HTTP. Haz clic en cada bloque para expandir la documentación.


== Categorías y Roles ==
<div class="mw-collapsible mw-collapsed" style="border: 1px solid #c8e6c9; background-color: #f1f8e9; padding: 10px; margin-bottom: 10px; border-radius: 4px;">
<div style="font-weight: bold; font-size: 1.1em; color: #2e7d32;">🟩 GET (Consultas y Lecturas)</div>
<div class="mw-collapsible-content" style="background-color: #ffffff; padding: 15px; margin-top: 10px; border: 1px solid #c8e6c9;">


=== GET /api/v1/categories ===
=== GET /api/v1/categories ===
'''Ruta y Método HTTP:'''<source lang="http">
Devuelve un listado completo de todas las categorías configuradas en el sistema para la empresa del usuario autenticado.
GET /api/v1/categories HTTP/1.1
==== Respuesta Exitosa (200 OK) ====
Host: api.serpi.com.co
<source lang="json">
Authorization: Bearer <TOKEN_JWT>
</source>'''Descripción:''' Devuelve un listado completo de todas las categorías configuradas en el sistema para la empresa del usuario autenticado. Las categorías permiten organizar formularios y establecer políticas de aislamiento y acceso basado en roles (RBAC).
 
'''Parámetros esperados:'''
{| class="wikitable"
!Nombre del Parámetro
!Tipo
!Obligatorio
!Descripción
|-
|''Ninguno''
|N/A
|No
|Este endpoint no requiere parámetros de consulta (Query) ni de ruta (Path).
|}
'''Ejemplo de Respuesta Exitosa (Código 200 OK):'''<source lang="json">
[
[
   {
   {
Línea 30: Línea 17:
     "color": "#3B82F6",
     "color": "#3B82F6",
     "roleIds": [101, 102]
     "roleIds": [101, 102]
  },
  {
    "categoriaId": 2,
    "nombre": "Auditorías de Visitas",
    "color": "#10B981",
    "roleIds": []
   }
   }
]
]
</source>'''Códigos de Error Posibles:'''
</source>
 
* '''401 Unauthorized''': Token JWT ausente, expirado o inválido.
* '''403 Forbidden''': El rol del usuario no tiene permisos para consultar categorías.
 
----
 
=== GET /api/v1/categories/{id} ===
'''Ruta y Método HTTP:'''<source lang="http">
GET /api/v1/categories/1 HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>
</source>'''Descripción:''' Busca y devuelve los detalles de una categoría específica utilizando su identificador único numérico.
 
'''Parámetros esperados:'''
{| class="wikitable"
!Nombre del Parámetro
!Tipo
!Obligatorio
!Descripción
|-
|id
|Integer
|Sí (Path)
|Identificador único numérico de la categoría a consultar.
|}
'''Ejemplo de Respuesta Exitosa (Código 200 OK):'''<source lang="json">
{
  "categoriaId": 1,
  "nombre": "Encuestas de Satisfacción",
  "color": "#3B82F6",
  "roleIds": [101, 102]
}
</source>'''Códigos de Error Posibles:'''
 
* '''401 Unauthorized''': No autenticado.
* '''403 Forbidden''': Permisos insuficientes.
* '''404 Not Found''': El ID especificado no corresponde a ninguna categoría activa.
 
----
 
=== POST /api/v1/categories ===
'''Ruta y Método HTTP:'''<source lang="http">
POST /api/v1/categories HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>
Content-Type: application/json
</source>'''Descripción:''' Registra una nueva categoría en el sistema especificando su nombre, color representativo en formato hexadecimal y de forma opcional los roles permitidos.
 
'''Parámetros esperados:'''
{| class="wikitable"
!Nombre del Parámetro
!Tipo
!Obligatorio
!Descripción
|-
|''Body''
|Object
|Sí
|Objeto JSON con los datos de creación de la categoría.
|}
'''Ejemplo de Payload / Body:'''<source lang="json">
{
  "nombre": "Control de Calidad",
  "color": "#F59E0B",
  "roleIds": [105, 108]
}
</source>'''Ejemplo de Respuesta Exitosa (Código 201 Created):'''<source lang="json">
{
  "categoriaId": 3,
  "nombre": "Control de Calidad",
  "color": "#F59E0B",
  "roleIds": [105, 108]
}
</source>'''Códigos de Error Posibles:'''
 
* '''400 Bad Request''': Error de validación en el payload (nombre vacío o color hexadecimal inválido).
* '''401 Unauthorized''': No autenticado.
* '''403 Forbidden''': El perfil del usuario no permite crear categorías.
 
----
 
=== PUT /api/v1/categories/{id} ===
'''Ruta y Método HTTP:'''<source lang="http">
PUT /api/v1/categories/3 HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>
Content-Type: application/json
</source>'''Descripción:''' Actualiza las propiedades de una categoría existente (nombre, color representativo o lista de roles autorizados).
 
'''Parámetros esperados:'''
{| class="wikitable"
!Nombre del Parámetro
!Tipo
!Obligatorio
!Descripción
|-
|id
|Integer
|Sí (Path)
|ID numérico de la categoría a actualizar.
|-
|''Body''
|Object
|Sí
|Objeto JSON con los nuevos valores de la categoría.
|}
'''Ejemplo de Payload / Body:'''<source lang="json">
{
  "nombre": "Control de Calidad y Procesos",
  "color": "#EF4444",
  "roleIds": [105, 108, 110]
}
</source>'''Ejemplo de Respuesta Exitosa (Código 204 No Content):'''<source lang="http">
HTTP/1.1 204 No Content
</source>'''Códigos de Error Posibles:'''
 
* '''400 Bad Request''': Datos de entrada no cumplen los criterios de validación.
* '''401 Unauthorized''': No autenticado.
* '''403 Forbidden''': Permisos insuficientes.
* '''404 Not Found''': Categoría no encontrada.
 
----
 
=== DELETE /api/v1/categories/{id} ===
'''Ruta y Método HTTP:'''<source lang="http">
DELETE /api/v1/categories/3 HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>
</source>'''Descripción:''' Elimina de forma física y permanente una categoría. La operación fallará si la categoría posee carpetas activas para proteger la integridad estructural.
 
'''Parámetros esperados:'''
{| class="wikitable"
!Nombre del Parámetro
!Tipo
!Obligatorio
!Descripción
|-
|id
|Integer
|Sí (Path)
|ID numérico de la categoría a eliminar.
|}
'''Ejemplo de Respuesta Exitosa (Código 204 No Content):'''<source lang="http">
HTTP/1.1 204 No Content
</source>'''Códigos de Error Posibles:'''
 
* '''401 Unauthorized''': No autenticado.
* '''403 Forbidden''': Permisos insuficientes.
* '''404 Not Found''': La categoría no existe o ya fue eliminada.
 
----
 
=== GET /api/v1/categories/roles ===
'''Ruta y Método HTTP:'''<source lang="http">
GET /api/v1/categories/roles HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>
</source>'''Descripción:''' Recupera todos los roles y perfiles configurados en la base de datos maestra del ERP (MvcSERPI) para la empresa actual, facilitando la asignación granular de permisos.
 
'''Parámetros esperados:'''
{| class="wikitable"
!Nombre del Parámetro
!Tipo
!Obligatorio
!Descripción
|-
|''Ninguno''
|N/A
|No
|No requiere parámetros.
|}
'''Ejemplo de Respuesta Exitosa (Código 200 OK):'''<source lang="json">
[
  {
    "rolId": 101,
    "nombre": "Administrador de Ventas"
  },
  {
    "rolId": 102,
    "nombre": "Asesor Comercial"
  }
]
</source>'''Códigos de Error Posibles:'''
 
* '''401 Unauthorized''': No autenticado.
* '''403 Forbidden''': Sin acceso a configuraciones de seguridad.
 
----
 
== Carpetas y Workspace ==


=== GET /api/v1/folders ===
=== GET /api/v1/folders ===
'''Ruta y Método HTTP:'''<source lang="http">
Retorna la estructura jerárquica completa de carpetas, subcarpetas y formularios, filtrada automáticamente por los roles del usuario.
GET /api/v1/folders HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>
</source>'''Descripción:''' Retorna la estructura jerárquica completa de carpetas, subcarpetas y formularios contenidos dentro del Workspace, filtrada de forma automática por los roles del usuario.


'''Parámetros esperados:'''
=== GET /api/v1/forms/stats ===
{| class="wikitable"
Calcula y devuelve los indicadores clave (KPIs) globales del Workspace para la empresa.
!Nombre del Parámetro
==== Respuesta Exitosa (200 OK) ====
!Tipo
<source lang="json">
!Obligatorio
!Descripción
|-
|''Ninguno''
|N/A
|No
|No requiere parámetros.
|}
'''Ejemplo de Respuesta Exitosa (Código 200 OK):'''<source lang="json">
[
  {
    "id": "folder_10",
    "name": "Comercial 2026",
    "parentId": null,
    "categoriaId": 1,
    "color": "#3B82F6",
    "children": [
      {
        "id": "folder_12",
        "name": "Zonales",
        "parentId": "folder_10",
        "categoriaId": 1,
        "color": "#3B82F6"
      }
    ],
    "forms": [
      {
        "uuid": "8f3b2a1c-9e4d-4c8a-b5f6-7d8e9f0a1b2c",
        "titulo": "Evaluación de Servicio en Tienda",
        "activo": true
      }
    ]
  }
]
</source>'''Códigos de Error Posibles:'''
 
* '''401 Unauthorized''': Se requiere sesión activa.
 
----
 
=== POST /api/v1/folders ===
'''Ruta y Método HTTP:'''<source lang="http">
POST /api/v1/folders HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>
Content-Type: application/json
</source>'''Descripción:''' Crea una nueva carpeta en la raíz del entorno o como subcarpeta (indicando <code>parentId</code>). Requiere estar vinculada a una categoría existente.
 
'''Parámetros esperados:'''
{| class="wikitable"
!Nombre del Parámetro
!Tipo
!Obligatorio
!Descripción
|-
|''Body''
|Object
|Sí
|Datos para la creación de la carpeta.
|}
'''Ejemplo de Payload / Body:'''<source lang="json">
{
{
   "name": "Encuestas Region Andina",
   "respuestasHoy": 142,
   "parentId": "folder_10",
   "respuestasTotal": 12850,
   "categoriaId": 1
   "formulariosActivos": 18
}
}
</source>'''Ejemplo de Respuesta Exitosa (Código 201 Created):'''<source lang="json">
</source>
{
  "id": "folder_25",
  "name": "Encuestas Region Andina",
  "parentId": "folder_10",
  "categoriaId": 1,
  "color": "#3B82F6",
  "children": [],
  "forms": []
}
</source>'''Códigos de Error Posibles:'''


* '''400 Bad Request''': Nombre inválido o categoría inexistente.
=== GET /api/v1/forms/public/{empresaid}/{uuid} ===
* '''401 Unauthorized''': No autenticado.
Devuelve el esquema y diseño público de un formulario para renderizarse en el frontend (No requiere JWT).
 
==== Parámetros ====
----
 
=== PUT /api/v1/folders/{id} ===
'''Ruta y Método HTTP:'''<source lang="http">
PUT /api/v1/folders/25 HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>
Content-Type: application/json
</source>'''Descripción:''' Renombra o mueve una carpeta existente dentro del árbol del Workspace.
 
'''Parámetros esperados:'''
{| class="wikitable"
{| class="wikitable"
!Nombre del Parámetro
!Tipo
!Obligatorio
!Descripción
|-
|-
|id
! Parámetro !! Tipo !! Obligatorio !! Descripción
|Integer
|Sí (Path)
|ID numérico de la carpeta a modificar.
|-
|-
|''Body''
| empresaid || Integer || (Path) || ID de la empresa o 0 para resolver automáticamente.
|Object
|
|Datos actualizados de la carpeta.
|}
'''Ejemplo de Payload / Body:'''<source lang="json">
{
  "nombre": "Encuestas Región Andina y Centro",
  "parentId": null
}
</source>'''Ejemplo de Respuesta Exitosa (Código 204 No Content):'''<source lang="http">
HTTP/1.1 204 No Content
</source>'''Códigos de Error Posibles:'''
 
* '''400 Bad Request''': Intento de mover una carpeta dentro de sí misma o nombre nulo.
* '''401 Unauthorized''': Sin sesión activa.
* '''404 Not Found''': Carpeta no encontrada.
 
----
 
=== GET /api/v1/folders/{id}/history ===
'''Ruta y Método HTTP:'''<source lang="http">
GET /api/v1/folders/25/history HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>
</source>'''Descripción:''' Obtiene la bitácora de auditoría histórica de eventos sobre la carpeta especificada (creación, cambio de nombre, movimientos).
 
'''Parámetros esperados:'''
{| class="wikitable"
!Nombre del Parámetro
!Tipo
!Obligatorio
!Descripción
|-
|-
|id
| uuid || String || Sí (Path) || UUID público del formulario.
|Integer
|Sí (Path)
|ID numérico de la carpeta a consultar.
|}
|}
'''Ejemplo de Respuesta Exitosa (Código 200 OK):'''<source lang="json">
[
  {
    "auditoriaId": 501,
    "entidad": "carpeta",
    "entidadId": "25",
    "accion": "crear",
    "detalle": "Carpeta creada con nombre 'Encuestas Region Andina'",
    "usuarioId": 12,
    "fecha": "2026-08-21T07:00:00Z"
  },
  {
    "auditoriaId": 508,
    "entidad": "carpeta",
    "entidadId": "25",
    "accion": "renombrar",
    "detalle": "Carpeta renombrada a 'Encuestas Región Andina y Centro'",
    "usuarioId": 12,
    "fecha": "2026-08-21T07:10:00Z"
  }
]
</source>'''Códigos de Error Posibles:'''


* '''401 Unauthorized''': No autorizado.
</div>
</div>


----
<div class="mw-collapsible mw-collapsed" style="border: 1px solid #bbdefb; background-color: #e3f2fd; padding: 10px; margin-bottom: 10px; border-radius: 4px;">
<div style="font-weight: bold; font-size: 1.1em; color: #1565c0;">🟦 POST (Creación y Procesos)</div>
<div class="mw-collapsible-content" style="background-color: #ffffff; padding: 15px; margin-top: 10px; border: 1px solid #bbdefb;">


=== DELETE /api/v1/folders/{id} ===
=== POST /api/v1/forms ===
'''Ruta y Método HTTP:'''<source lang="http">
Crea un nuevo formulario dinámico asociando su esquema JSON y retornando un UUID para la URL pública.
DELETE /api/v1/folders/25 HTTP/1.1
==== Parámetros ====
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>
</source>'''Descripción:''' Realiza un borrado lógico en cascada de una carpeta y de todas sus subcarpetas y formularios dependientes.
 
'''Parámetros esperados:'''
{| class="wikitable"
{| class="wikitable"
!Nombre del Parámetro
!Tipo
!Obligatorio
!Descripción
|-
|-
|id
! Parámetro !! Tipo !! Obligatorio !! Descripción
|Integer
|Sí (Path)
|ID de la carpeta a eliminar.
|}
'''Ejemplo de Respuesta Exitosa (Código 204 No Content):'''<source lang="http">
HTTP/1.1 204 No Content
</source>'''Códigos de Error Posibles:'''
 
* '''400 Bad Request''': Error en el proceso de eliminación lógica.
* '''401 Unauthorized''': No autorizado.
* '''404 Not Found''': Carpeta no encontrada.
 
----
 
== Formularios Dinámicos ==
 
=== POST /api/v1/forms ===
'''Ruta y Método HTTP:'''<source lang="http">
POST /api/v1/forms HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>
Content-Type: application/json
</source>'''Descripción:''' Crea un nuevo formulario dinámico asociando su esquema JSON y retornando un UUID no secuencial para la URL pública.
 
'''Parámetros esperados:'''
{| class="wikitable"
!Nombre del Parámetro
!Tipo
!Obligatorio
!Descripción
|-
|-
|''Body''
| Body || Object || Sí || Datos requeridos para la plantilla de formulario.
|Object
|Sí
|Datos requeridos para la plantilla de formulario.
|}
|}
'''Ejemplo de Payload / Body:'''<source lang="json">
==== Respuesta Exitosa (201 Created) ====
{
<source lang="json">
  "nombre": "Encuesta Visita Cliente",
  "titulo": "Encuesta de Satisfacción en Visita",
  "descripcion": "Formulario diligenciado en visitas comerciales.",
  "carpetaId": 25,
  "esquemaJson": "{\"settings\":{\"contexto\":\"Cliente\",\"repeatFrequency\":\"1w\"},\"components\":[]}"
}
</source>'''Ejemplo de Respuesta Exitosa (Código 201 Created):'''<source lang="json">
{
{
   "formId": 45,
   "formId": 45,
Línea 476: Línea 71:
   "urlPublica": "/f/15/d3b07384-d113-4f4a-a62e-336712345678"
   "urlPublica": "/f/15/d3b07384-d113-4f4a-a62e-336712345678"
}
}
</source>'''Códigos de Error Posibles:'''
</source>


* '''400 Bad Request''': Esquema JSON o campos obligatorios faltantes/mal formateados.
=== POST /api/v1/forms/public/{empresaid}/{uuid}/responses ===
* '''401 Unauthorized''': No autenticado.
Endpoint público para registrar la respuesta diligenciada por un encuestado. Garantiza inmutabilidad y orquesta el cobro de folio SaaS.
 
==== Payload Esperado ====
----
<source lang="json">
 
=== PUT /api/v1/forms/{uuid} ===
'''Ruta y Método HTTP:'''<source lang="http">
PUT /api/v1/forms/d3b07384-d113-4f4a-a62e-336712345678 HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>
Content-Type: application/json
</source>'''Descripción:''' Actualiza el título, descripción y estructura de preguntas (Esquema JSON) de un formulario existente.
 
'''Parámetros esperados:'''
{| class="wikitable"
!Nombre del Parámetro
!Tipo
!Obligatorio
!Descripción
|-
|uuid
|String
|Sí (Path)
|UUID del formulario a actualizar.
|-
|''Body''
|Object
|Sí
|Datos actualizados del formulario.
|}
'''Ejemplo de Payload / Body:'''<source lang="json">
{
{
   "nombre": "Encuesta Visita Cliente v2",
   "respuestaJson": "{\"idtercero\":1502,\"idsucursal\":1,\"respuestas\":[{\"pregunta_id\":\"q1\",\"valor\":\"Excelente\"}]}"
  "titulo": "Encuesta de Satisfacción Comercial v2",
  "descripcion": "Formulario actualizado para atención a clientes.",
  "esquemaJson": "{\"settings\":{\"contexto\":\"Cliente\",\"repeatFrequency\":\"1d\"},\"components\":[]}"
}
}
</source>'''Ejemplo de Respuesta Exitosa (Código 204 No Content):'''<source lang="http">
</source>
HTTP/1.1 204 No Content
</source>'''Códigos de Error Posibles:'''


* '''400 Bad Request''': Errores estructurales en el JSON enviado.
=== POST /api/v1/billing/process ===
* '''401 Unauthorized''': No autenticado.
Orquestación interna SaaS para debitar folios transaccionales (Zero-Trust). No utiliza JWT, sino el encabezado HTTP <code>X-Secret-Key</code>.
* '''404 Not Found''': Formulario no encontrado por el UUID.


----
</div>
</div>


=== DELETE /api/v1/forms/{uuid} ===
<div class="mw-collapsible mw-collapsed" style="border: 1px solid #ffe0b2; background-color: #fff3e0; padding: 10px; margin-bottom: 10px; border-radius: 4px;">
'''Ruta y Método HTTP:'''<source lang="http">
<div style="font-weight: bold; font-size: 1.1em; color: #e65100;">🟧 PUT (Actualizaciones)</div>
DELETE /api/v1/forms/d3b07384-d113-4f4a-a62e-336712345678 HTTP/1.1
<div class="mw-collapsible-content" style="background-color: #ffffff; padding: 15px; margin-top: 10px; border: 1px solid #ffe0b2;">
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>
</source>'''Descripción:''' Ejecuta un borrado lógico (Soft Delete) del formulario, desactivándolo y moviéndolo a la papelera sin perder respuestas históricas. Requiere estar apagado previamente.


'''Parámetros esperados:'''
=== PUT /api/v1/forms/{uuid} ===
Actualiza el título, descripción y estructura de preguntas (Esquema JSON) de un formulario existente.
==== Parámetros ====
{| class="wikitable"
{| class="wikitable"
!Nombre del Parámetro
!Tipo
!Obligatorio
!Descripción
|-
|-
|uuid
! Parámetro !! Tipo !! Obligatorio !! Descripción
|String
|Sí (Path)
|UUID del formulario a enviar a la papelera.
|}
'''Ejemplo de Respuesta Exitosa (Código 204 No Content):'''<source lang="http">
HTTP/1.1 204 No Content
</source>'''Códigos de Error Posibles:'''
 
* '''400 Bad Request''': El formulario está Activo. Debe desactivarse antes de eliminarse.
* '''401 Unauthorized''': No autenticado.
* '''404 Not Found''': Formulario inexistente.
 
----
 
=== PUT /api/v1/forms/{uuid}/toggle-status ===
'''Ruta y Método HTTP:'''<source lang="http">
PUT /api/v1/forms/d3b07384-d113-4f4a-a62e-336712345678/toggle-status HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>
Content-Type: application/json
</source>'''Descripción:''' Alterna el estado de un formulario entre Activo (disponible públicamente) e Inactivo (bloquea la recepción de respuestas).
 
'''Parámetros esperados:'''
{| class="wikitable"
!Nombre del Parámetro
!Tipo
!Obligatorio
!Descripción
|-
|-
|uuid
| uuid || String || Sí (Path) || UUID del formulario a actualizar.
|String
|Sí (Path)
|UUID del formulario a modificar.
|-
|-
|''Body''
| Body || Object || Sí || Datos actualizados del formulario.
|Object
|Sí
|Indicador de estado (<code>activo</code>: true/false).
|}
|}
'''Ejemplo de Payload / Body:'''<source lang="json">
{
  "activo": false
}
</source>'''Ejemplo de Respuesta Exitosa (Código 204 No Content):'''<source lang="http">
HTTP/1.1 204 No Content
</source>'''Códigos de Error Posibles:'''


* '''401 Unauthorized''': Sin autorización.
=== PUT /api/v1/forms/{uuid}/toggle-status ===
* '''404 Not Found''': Formulario no encontrado.
Alterna el estado de un formulario entre Activo e Inactivo (bloquea la recepción de respuestas).
 
----


=== PUT /api/v1/forms/{uuid}/move ===
=== PUT /api/v1/forms/{uuid}/move ===
'''Ruta y Método HTTP:'''<source lang="http">
Reubica un formulario en otra carpeta contenedora o en la raíz del Workspace enviando <code>?carpetaId=25</code>.
PUT /api/v1/forms/d3b07384-d113-4f4a-a62e-336712345678/move?carpetaId=25 HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>
</source>'''Descripción:''' Reubica un formulario en otra carpeta contenedora o en la raíz del Workspace (si se omite el parámetro <code>carpetaId</code>).
 
'''Parámetros esperados:'''
{| class="wikitable"
!Nombre del Parámetro
!Tipo
!Obligatorio
!Descripción
|-
|uuid
|String
|Sí (Path)
|UUID del formulario a mover.
|-
|carpetaId
|Integer
|No (Query)
|ID de la carpeta destino (omitir para mover a la raíz).
|}
'''Ejemplo de Respuesta Exitosa (Código 204 No Content):'''<source lang="http">
HTTP/1.1 204 No Content
</source>'''Códigos de Error Posibles:'''


* '''401 Unauthorized''': No autenticado.
</div>
* '''404 Not Found''': Formulario o carpeta destino no encontrados.
</div>


----
<div class="mw-collapsible mw-collapsed" style="border: 1px solid #ffcdd2; background-color: #ffebee; padding: 10px; margin-bottom: 10px; border-radius: 4px;">
<div style="font-weight: bold; font-size: 1.1em; color: #c62828;">🟥 DELETE (Eliminaciones)</div>
<div class="mw-collapsible-content" style="background-color: #ffffff; padding: 15px; margin-top: 10px; border: 1px solid #ffcdd2;">


=== GET /api/v1/forms/{uuid}/history ===
=== DELETE /api/v1/categories/{id} ===
'''Ruta y Método HTTP:'''<source lang="http">
Elimina de forma física y permanente una categoría. Fallará si la categoría posee carpetas activas.
GET /api/v1/forms/d3b07384-d113-4f4a-a62e-336712345678/history HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>
</source>'''Descripción:''' Retorna el historial cronológico de auditoría con todas las modificaciones realizadas sobre el formulario.


'''Parámetros esperados:'''
=== DELETE /api/v1/folders/{id} ===
{| class="wikitable"
Realiza un borrado lógico en cascada de una carpeta y de todas sus subcarpetas y formularios dependientes.
!Nombre del Parámetro
!Tipo
!Obligatorio
!Descripción
|-
|uuid
|String
|Sí (Path)
|UUID del formulario.
|}
'''Ejemplo de Respuesta Exitosa (Código 200 OK):'''<source lang="json">
[
  {
    "auditoriaId": 801,
    "entidad": "formulario",
    "entidadId": "d3b07384-d113-4f4a-a62e-336712345678",
    "accion": "crear",
    "detalle": "Formulario creado con título 'Encuesta de Satisfacción en Visita'",
    "usuarioId": 5,
    "fecha": "2026-08-21T06:30:00Z"
  }
]
</source>'''Códigos de Error Posibles:'''


* '''401 Unauthorized''': Token inválido.
=== DELETE /api/v1/forms/{uuid} ===
 
Ejecuta un borrado lógico (Soft Delete) del formulario, desactivándolo y moviéndolo a la papelera sin perder respuestas históricas. Requiere estar apagado previamente.
----
==== Códigos de Error Posibles ====
 
* <code>400 Bad Request:</code> El formulario está Activo. Debe desactivarse antes de eliminarse.
=== GET /api/v1/forms/stats ===
* <code>401 Unauthorized:</code> No autenticado.
'''Ruta y Método HTTP:'''<source lang="http">
* <code>404 Not Found:</code> Formulario inexistente.
GET /api/v1/forms/stats HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>
</source>'''Descripción:''' Calcula y devuelve los indicadores clave (KPIs) globales del Workspace para la empresa.
 
'''Parámetros esperados:'''
{| class="wikitable"
!Nombre del Parámetro
!Tipo
!Obligatorio
!Descripción
|-
|''Ninguno''
|N/A
|No
|No requiere parámetros.
|}
'''Ejemplo de Respuesta Exitosa (Código 200 OK):'''<source lang="json">
{
  "respuestasHoy": 142,
  "respuestasTotal": 12850,
  "formulariosActivos": 18
}
</source>'''Códigos de Error Posibles:'''
 
* '''401 Unauthorized''': No autenticado.
 
----
 
=== GET /api/v1/forms/{formId}/responses ===
'''Ruta y Método HTTP:'''<source lang="http">
GET /api/v1/forms/45/responses?startDate=2026-08-01T00:00:00Z&endDate=2026-08-21T23:59:59Z HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>
</source>'''Descripción:''' Recupera el listado detallado de respuestas capturadas para un formulario específico dentro de un rango de fechas.
 
'''Parámetros esperados:'''
{| class="wikitable"
!Nombre del Parámetro
!Tipo
!Obligatorio
!Descripción
|-
|formId
|Integer
|Sí (Path)
|ID numérico interno del formulario.
|-
|startDate
|DateTime
|No (Query)
|Fecha inicial para filtrar respuestas.
|-
|endDate
|DateTime
|No (Query)
|Fecha final para filtrar respuestas.
|}
'''Ejemplo de Respuesta Exitosa (Código 200 OK):'''<source lang="json">
[
  {
    "respuestaId": 1024,
    "formId": 45,
    "fechaEnvio": "2026-08-21T07:05:00Z",
    "ipOrigen": "190.150.10.5",
    "payloadJson": "{\"idtercero\":1502,\"idsucursal\":1,\"respuestas\":[{\"pregunta_id\":\"q1\",\"valor\":\"Excelente\"}]}"
  }
]
</source>'''Códigos de Error Posibles:'''
 
* '''401 Unauthorized''': No autorizado.
* '''404 Not Found''': Formulario no encontrado.
 
----
 
=== GET /api/v1/forms/{formId}/responses/count ===
'''Ruta y Método HTTP:'''<source lang="http">
GET /api/v1/forms/45/responses/count HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>
</source>'''Descripción:''' Retorna el conteo total numérico de respuestas acumuladas por un formulario.
 
'''Parámetros esperados:'''
{| class="wikitable"
!Nombre del Parámetro
!Tipo
!Obligatorio
!Descripción
|-
|formId
|Integer
|Sí (Path)
|ID numérico interno del formulario.
|}
'''Ejemplo de Respuesta Exitosa (Código 200 OK):'''<source lang="json">
1024
</source>'''Códigos de Error Posibles:'''
 
* '''401 Unauthorized''': No autorizado.
 
----
 
=== GET /api/v1/forms/trash ===
'''Ruta y Método HTTP:'''<source lang="http">
GET /api/v1/forms/trash HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>
</source>'''Descripción:''' Devuelve el listado de formularios que se encuentran actualmente desactivados en la papelera de reciclaje.
 
'''Parámetros esperados:'''
{| class="wikitable"
!Nombre del Parámetro
!Tipo
!Obligatorio
!Descripción
|-
|''Ninguno''
|N/A
|No
|No requiere parámetros.
|}
'''Ejemplo de Respuesta Exitosa (Código 200 OK):'''<source lang="json">
[
  {
    "formId": 32,
    "uuid": "a1b2c3d4-e5f6-7a8b-9c0d-1e2f3a4b5c6d",
    "nombre": "Encuesta Prueba Papelera",
    "titulo": "Prueba de Concepto Antigua",
    "activo": false,
    "fechaEliminacion": "2026-08-15T10:00:00Z"
  }
]
</source>'''Códigos de Error Posibles:'''
 
* '''401 Unauthorized''': No autenticado.
 
----
 
=== PUT /api/v1/forms/{uuid}/restore ===
'''Ruta y Método HTTP:'''<source lang="http">
PUT /api/v1/forms/a1b2c3d4-e5f6-7a8b-9c0d-1e2f3a4b5c6d/restore HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>
</source>'''Descripción:''' Restaura un formulario de la papelera, reintegrándolo a la lista activa y reactivando la recepción de respuestas.
 
'''Parámetros esperados:'''
{| class="wikitable"
!Nombre del Parámetro
!Tipo
!Obligatorio
!Descripción
|-
|uuid
|String
|Sí (Path)
|UUID del formulario a restaurar.
|}
'''Ejemplo de Respuesta Exitosa (Código 204 No Content):'''<source lang="http">
HTTP/1.1 204 No Content
</source>'''Códigos de Error Posibles:'''
 
* '''401 Unauthorized''': No autenticado.
* '''404 Not Found''': El formulario no existe en la papelera.
 
----
 
=== GET /api/v1/forms/surveys/available ===
'''Ruta y Método HTTP:'''<source lang="http">
GET /api/v1/forms/surveys/available?contextos=Cliente,Proveedor&nittercero=900123456&usuarioid=10 HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>
</source>'''Descripción:''' Evalúa la disponibilidad de encuestas para un tercero o usuario en tiempo real en el ERP durante una visita comercial, aplicando reglas anti-spam y ventanas de frecuencia (<code>repeatFrequency</code> / <code>repeatDays</code>).
 
'''Parámetros esperados:'''
{| class="wikitable"
!Nombre del Parámetro
!Tipo
!Obligatorio
!Descripción
|-
|contextos
|String
|No (Query)
|Lista de contextos separados por coma (ej. 'Cliente,Proveedor,Visita').
|-
|nittercero
|String
|No (Query)
|NIT o cédula del tercero visitado para evaluar ventanas de tiempo.
|-
|usuarioid
|Integer
|No (Query)
|ID del usuario o asesor que realiza la atención.
|}
'''Ejemplo de Respuesta Exitosa (Código 200 OK):'''<source lang="json">
[
  {
    "formId": 45,
    "uuid": "d3b07384-d113-4f4a-a62e-336712345678",
    "nombre": "Encuesta Visita Cliente",
    "titulo": "Encuesta de Satisfacción en Visita",
    "contexto": "Cliente",
    "repeatFrequency": "1w",
    "repeatDays": 7,
    "ultimaRespuestaFecha": "2026-08-10T14:20:00Z",
    "permiteResponder": true,
    "publicUrl": "/f/15/d3b07384-d113-4f4a-a62e-336712345678",
    "encuestaDeVisita": true
  }
]
</source>'''Códigos de Error Posibles:'''
 
* '''401 Unauthorized''': Sin autenticación válida de la empresa.
 
----
 
=== POST /api/v1/forms/terceros/verificar ===
'''Ruta y Método HTTP:'''<source lang="http">
POST /api/v1/forms/terceros/verificar?empresaid=15 HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>
Content-Type: application/json
</source>'''Descripción:''' Recibe una lista de NITs o cédulas y valida cuáles de ellos tienen registros activos en la tabla <code>gdttercero</code> de la empresa.
 
'''Parámetros esperados:'''
{| class="wikitable"
!Nombre del Parámetro
!Tipo
!Obligatorio
!Descripción
|-
|empresaid
|Integer
|No (Query)
|ID de la empresa (si se omite, se usa el del token JWT).
|-
|''Body''
|Array
|Sí
|Arreglo de strings con los NITs a consultar.
|}
'''Ejemplo de Payload / Body:'''<source lang="json">
[
  "900123456",
  "800987654",
  "1098765432"
]
</source>'''Ejemplo de Respuesta Exitosa (Código 200 OK):'''<source lang="json">
{
  "900123456": 1502,
  "800987654": 1509
}
</source>'''Códigos de Error Posibles:'''
 
* '''401 Unauthorized''': Sin sesión activa.
 
----
 
=== GET /api/v1/forms/public/{empresaid}/{uuid} ===
'''Ruta y Método HTTP:'''<source lang="http">
GET /api/v1/forms/public/15/d3b07384-d113-4f4a-a62e-336712345678 HTTP/1.1
Host: api.serpi.com.co
</source>'''Descripción:''' Devuelve el esquema y diseño público de un formulario para renderizarse en el frontend. Endpoint de acceso público sin requerir token JWT.
 
'''Parámetros esperados:'''
{| class="wikitable"
!Nombre del Parámetro
!Tipo
!Obligatorio
!Descripción
|-
|empresaid
|Integer
|Sí (Path)
|ID de la empresa o 0 para resolver automáticamente por UUID.
|-
|uuid
|String
|Sí (Path)
|UUID público del formulario a consultar.
|}
'''Ejemplo de Respuesta Exitosa (Código 200 OK):'''<source lang="json">
{
  "titulo": "Encuesta de Satisfacción en Visita",
  "descripcion": "Por favor responda las siguientes preguntas",
  "esquemaJson": "{\"branding\":{\"theme\":\"light\"},\"components\":[{\"id\":\"q1\",\"type\":\"radio\",\"label\":\"¿Cómo fue la atención?\"}]}",
  "requiereSesionOnline": false,
  "sesionValida": false,
  "usuarioIdentificador": null,
  "defaultCompanyLogo": "https://cdn.serpi.com.co/logos/empresa15.png"
}
</source>'''Códigos de Error Posibles:'''
 
* '''404 Not Found''': Formulario inactivo o UUID inexistente.
 
----
 
=== POST /api/v1/forms/public/{empresaid}/{uuid}/responses ===
'''Ruta y Método HTTP:'''<source lang="http">
POST /api/v1/forms/public/15/d3b07384-d113-4f4a-a62e-336712345678/responses HTTP/1.1
Host: api.serpi.com.co
Content-Type: application/json
</source>'''Descripción:''' Endpoint público para registrar la respuesta diligenciada por un encuestado. Garantiza inmutabilidad, captura la IP de origen y efectúa el cobro de folio SaaS.
 
'''Parámetros esperados:'''
{| class="wikitable"
!Nombre del Parámetro
!Tipo
!Obligatorio
!Descripción
|-
|empresaid
|Integer
|Sí (Path)
|ID de la empresa receptora.
|-
|uuid
|String
|Sí (Path)
|UUID del formulario a responder.
|-
|''Body''
|Object
|Sí
|Payload JSON con la estructura de respuestas en arreglo plano.
|}
'''Ejemplo de Payload / Body:'''<source lang="json">
{
  "respuestaJson": "{\"idtercero\":1502,\"idsucursal\":1,\"respuestas\":[{\"pregunta_id\":\"q1\",\"tipo\":\"radio\",\"valor\":\"Excelente\"}]}"
}
</source>'''Ejemplo de Respuesta Exitosa (Código 200 OK):'''<source lang="json">
{
  "respId": 2048,
  "billing_error": null
}
</source>'''Códigos de Error Posibles:'''
 
* '''400 Bad Request''': Formato JSON inválido o estructura no cumple con el esquema plano <code>respuestas</code>.
* '''404 Not Found''': Formulario inactivo o no encontrado.
 
----
 
== SaaS Billing ==
 
=== POST /api/v1/billing/process ===
'''Ruta y Método HTTP:'''<source lang="http">
POST /api/v1/billing/process HTTP/1.1
Host: api.serpi.com.co
X-Secret-Key: Serpi-Dev-SaaS-Key-2026!
Content-Type: application/json
</source>'''Descripción:''' Endpoint de orquestación interna SaaS para debitar folios transaccionales (Zero-Trust). No utiliza JWT, sino el encabezado HTTP <code>X-Secret-Key</code>.
 
'''Parámetros esperados:'''
{| class="wikitable"
!Nombre del Parámetro
!Tipo
!Obligatorio
!Descripción
|-
|X-Secret-Key
|String
|Sí (Header)
|Clave secreta enviada en la cabecera HTTP.
|-
|''Body''
|Object
|Sí
|Datos del consumo de folio SaaS.
|}
'''Ejemplo de Payload / Body:'''<source lang="json">
{
  "empresaId": 15,
  "gdtProductoFolioId": 8,
  "referencia": "2048"
}
</source>'''Ejemplo de Respuesta Exitosa (Código 200 OK):'''<source lang="json">
{
  "message": "Cobro de folio registrado correctamente."
}
</source>'''Códigos de Error Posibles:'''
 
* '''400 Bad Request''': Configuración de pricing no encontrada o inactiva para la empresa.
* '''401 Unauthorized''': Header <code>X-Secret-Key</code> ausente o incorrecto.
 
----
 
== Empresa ==
 
=== GET /api/v1/companies/logo ===
'''Ruta y Método HTTP:'''<source lang="http">
GET /api/v1/companies/logo HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>
</source>'''Descripción:''' Obtiene el logotipo corporativo configurado en la base de datos maestra para la empresa del usuario autenticado (retornado en Base64 o URL).
 
'''Parámetros esperados:'''
{| class="wikitable"
!Nombre del Parámetro
!Tipo
!Obligatorio
!Descripción
|-
|''Ninguno''
|N/A
|No
|No requiere parámetros.
|}
'''Ejemplo de Respuesta Exitosa (Código 200 OK):'''<source lang="json">
{
  "logo": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..."
}
</source>'''Códigos de Error Posibles:'''


* '''401 Unauthorized''': Requiere sesión activa.
</div>
</div>

Revisión actual - 10:09 21 ago 2026

⚡ Referencia de Endpoints

A continuación, los servicios expuestos organizados por método HTTP. Haz clic en cada bloque para expandir la documentación.

🟩 GET (Consultas y Lecturas)

GET /api/v1/categories

Devuelve un listado completo de todas las categorías configuradas en el sistema para la empresa del usuario autenticado.

Respuesta Exitosa (200 OK)

[
  {
    "categoriaId": 1,
    "nombre": "Encuestas de Satisfacción",
    "color": "#3B82F6",
    "roleIds": [101, 102]
  }
]

GET /api/v1/folders

Retorna la estructura jerárquica completa de carpetas, subcarpetas y formularios, filtrada automáticamente por los roles del usuario.

GET /api/v1/forms/stats

Calcula y devuelve los indicadores clave (KPIs) globales del Workspace para la empresa.

Respuesta Exitosa (200 OK)

{
  "respuestasHoy": 142,
  "respuestasTotal": 12850,
  "formulariosActivos": 18
}

GET /api/v1/forms/public/{empresaid}/{uuid}

Devuelve el esquema y diseño público de un formulario para renderizarse en el frontend (No requiere JWT).

Parámetros

Parámetro Tipo Obligatorio Descripción
empresaid Integer Sí (Path) ID de la empresa o 0 para resolver automáticamente.
uuid String Sí (Path) UUID público del formulario.
🟦 POST (Creación y Procesos)

POST /api/v1/forms

Crea un nuevo formulario dinámico asociando su esquema JSON y retornando un UUID para la URL pública.

Parámetros

Parámetro Tipo Obligatorio Descripción
Body Object Datos requeridos para la plantilla de formulario.

Respuesta Exitosa (201 Created)

{
  "formId": 45,
  "uuid": "d3b07384-d113-4f4a-a62e-336712345678",
  "titulo": "Encuesta de Satisfacción en Visita",
  "urlPublica": "/f/15/d3b07384-d113-4f4a-a62e-336712345678"
}

POST /api/v1/forms/public/{empresaid}/{uuid}/responses

Endpoint público para registrar la respuesta diligenciada por un encuestado. Garantiza inmutabilidad y orquesta el cobro de folio SaaS.

Payload Esperado

{
  "respuestaJson": "{\"idtercero\":1502,\"idsucursal\":1,\"respuestas\":[{\"pregunta_id\":\"q1\",\"valor\":\"Excelente\"}]}"
}

POST /api/v1/billing/process

Orquestación interna SaaS para debitar folios transaccionales (Zero-Trust). No utiliza JWT, sino el encabezado HTTP X-Secret-Key.

🟧 PUT (Actualizaciones)

PUT /api/v1/forms/{uuid}

Actualiza el título, descripción y estructura de preguntas (Esquema JSON) de un formulario existente.

Parámetros

Parámetro Tipo Obligatorio Descripción
uuid String Sí (Path) UUID del formulario a actualizar.
Body Object Datos actualizados del formulario.

PUT /api/v1/forms/{uuid}/toggle-status

Alterna el estado de un formulario entre Activo e Inactivo (bloquea la recepción de respuestas).

PUT /api/v1/forms/{uuid}/move

Reubica un formulario en otra carpeta contenedora o en la raíz del Workspace enviando ?carpetaId=25.

🟥 DELETE (Eliminaciones)

DELETE /api/v1/categories/{id}

Elimina de forma física y permanente una categoría. Fallará si la categoría posee carpetas activas.

DELETE /api/v1/folders/{id}

Realiza un borrado lógico en cascada de una carpeta y de todas sus subcarpetas y formularios dependientes.

DELETE /api/v1/forms/{uuid}

Ejecuta un borrado lógico (Soft Delete) del formulario, desactivándolo y moviéndolo a la papelera sin perder respuestas históricas. Requiere estar apagado previamente.

Códigos de Error Posibles

  • 400 Bad Request: El formulario está Activo. Debe desactivarse antes de eliminarse.
  • 401 Unauthorized: No autenticado.
  • 404 Not Found: Formulario inexistente.