Diferencia entre revisiones de «API Modulo Forms»

De WikiSerpi
Ir a la navegación Ir a la búsqueda
Página creada con « = API Módulo Forms = == Introducción == El API del Módulo Forms permite la consulta, creación y gestión de los formularios dentro del sistema. * '''URL Base:''' <code>https://api.tudominio.com/v1/</code> * '''Formato de respuesta:''' <code>JSON</code> == Autenticación == Todas las peticiones a los endpoints protegidos deben incluir un token JWT en las cabeceras (headers) de la petición.<source lang="http"> Authorization: Bearer TU_TOKEN_AQUI </source>---…»
 
v1
Línea 1: Línea 1:


= API Módulo Forms =
= SERPI Forms Core API (v1) =


== Introducción ==
== Categorías y Roles ==
El API del Módulo Forms permite la consulta, creación y gestión de los formularios dentro del sistema.


* '''URL Base:''' <code>https://api.tudominio.com/v1/</code>
=== GET /api/v1/categories ===
* '''Formato de respuesta:''' <code>JSON</code>
'''Ruta y Método HTTP:'''<source lang="http">
GET /api/v1/categories HTTP/1.1
Host: api.serpi.com.co
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).


== Autenticación ==
'''Parámetros esperados:'''
Todas las peticiones a los endpoints protegidos deben incluir un token JWT en las cabeceras (headers) de la petición.<source lang="http">
{| class="wikitable"
Authorization: Bearer TU_TOKEN_AQUI
!Nombre del Parámetro
</source>---
!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">
[
  {
    "categoriaId": 1,
    "nombre": "Encuestas de Satisfacción",
    "color": "#3B82F6",
    "roleIds": [101, 102]
  },
  {
    "categoriaId": 2,
    "nombre": "Auditorías de Visitas",
    "color": "#10B981",
    "roleIds": []
  }
]
</source>'''Códigos de Error Posibles:'''
 
* '''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.


== Endpoints ==
----


=== 1. Obtener lista de formularios ===
=== POST /api/v1/categories ===
Retorna una lista paginada de los formularios disponibles.
'''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.


* '''Endpoint:''' <code>/forms</code>
'''Parámetros esperados:'''
* '''Método:''' <code>GET</code>
{| 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:'''


==== Parámetros de Consulta (Query Params) ====
* '''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"
{| class="wikitable"
!Parámetro
!Nombre del Parámetro
!Tipo
!Tipo
!Obligatorio
!Obligatorio
!Descripción
!Descripción
|-
|-
|limit
|id
|Integer
|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
|Cantidad máxima de registros a devolver (por defecto: 20).
|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 ===
'''Ruta y Método HTTP:'''<source lang="http">
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:'''
{| 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">
[
  {
    "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
|-
|-
|status
|''Body''
|Object
|Sí
|Datos para la creación de la carpeta.
|}
'''Ejemplo de Payload / Body:'''<source lang="json">
{
  "name": "Encuestas Region Andina",
  "parentId": "folder_10",
  "categoriaId": 1
}
</source>'''Ejemplo de Respuesta Exitosa (Código 201 Created):'''<source lang="json">
{
  "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.
* '''401 Unauthorized''': No autenticado.
 
----
 
=== 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"
!Nombre del Parámetro
!Tipo
!Obligatorio
!Descripción
|-
|id
|Integer
|Sí (Path)
|ID numérico de la carpeta a modificar.
|-
|''Body''
|Object
|Sí
|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
|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.
 
----
 
=== DELETE /api/v1/folders/{id} ===
'''Ruta y Método HTTP:'''<source lang="http">
DELETE /api/v1/folders/25 HTTP/1.1
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"
!Nombre del Parámetro
!Tipo
!Obligatorio
!Descripción
|-
|id
|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''
|Object
|Sí
|Datos requeridos para la plantilla de formulario.
|}
'''Ejemplo de Payload / Body:'''<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,
  "uuid": "d3b07384-d113-4f4a-a62e-336712345678",
  "titulo": "Encuesta de Satisfacción en Visita",
  "urlPublica": "/f/15/d3b07384-d113-4f4a-a62e-336712345678"
}
</source>'''Códigos de Error Posibles:'''
 
* '''400 Bad Request''': Esquema JSON o campos obligatorios faltantes/mal formateados.
* '''401 Unauthorized''': No autenticado.
 
----
 
=== 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
|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",
  "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">
HTTP/1.1 204 No Content
</source>'''Códigos de Error Posibles:'''
* '''400 Bad Request''': Errores estructurales en el JSON enviado.
* '''401 Unauthorized''': No autenticado.
* '''404 Not Found''': Formulario no encontrado por el UUID.
----
=== DELETE /api/v1/forms/{uuid} ===
'''Ruta y Método HTTP:'''<source lang="http">
DELETE /api/v1/forms/d3b07384-d113-4f4a-a62e-336712345678 HTTP/1.1
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:'''
{| class="wikitable"
!Nombre del Parámetro
!Tipo
!Obligatorio
!Descripción
|-
|uuid
|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
|String
|Sí (Path)
|UUID del formulario a modificar.
|-
|''Body''
|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.
* '''404 Not Found''': Formulario no encontrado.
----
=== PUT /api/v1/forms/{uuid}/move ===
'''Ruta y Método HTTP:'''<source lang="http">
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.
* '''404 Not Found''': Formulario o carpeta destino no encontrados.
----
=== GET /api/v1/forms/{uuid}/history ===
'''Ruta y Método HTTP:'''<source lang="http">
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:'''
{| class="wikitable"
!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.
----
=== GET /api/v1/forms/stats ===
'''Ruta y Método HTTP:'''<source lang="http">
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
|Filtra por estado (ej. <code>active</code>, <code>archived</code>).
|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:'''


==== Respuesta Exitosa ====
* '''401 Unauthorized''': No autenticado.
* '''404 Not Found''': El formulario no existe en la papelera.


* '''Código:''' <code>200 OK</code>
----
* '''Cuerpo:'''
 
<source lang="json">
=== 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">
{
{
   "success": true,
   "titulo": "Encuesta de Satisfacción en Visita",
   "data": [
   "descripcion": "Por favor responda las siguientes preguntas",
    {
  "esquemaJson": "{\"branding\":{\"theme\":\"light\"},\"components\":[{\"id\":\"q1\",\"type\":\"radio\",\"label\":\"¿Cómo fue la atención?\"}]}",
      "_id": "60d5ecb8b392d7",
  "requiereSesionOnline": false,
      "title": "Inspección de Calidad",
  "sesionValida": false,
      "createdAt": "2026-08-21T10:00:00Z"
  "usuarioIdentificador": null,
    }
   "defaultCompanyLogo": "https://cdn.serpi.com.co/logos/empresa15.png"
   ]
}
}
</source>
</source>'''Códigos de Error Posibles:'''


=== 2. Crear un nuevo formulario ===
* '''404 Not Found''': Formulario inactivo o UUID inexistente.
Permite registrar la estructura de un nuevo formulario.


* '''Endpoint:''' <code>/forms</code>
----
* '''Método:''' <code>POST</code>


==== Cuerpo de la Petición (Payload) ====
=== POST /api/v1/forms/public/{empresaid}/{uuid}/responses ===
<source lang="json">
'''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">
{
{
   "title": "Formulario de Novedades",
   "respuestaJson": "{\"idtercero\":1502,\"idsucursal\":1,\"respuestas\":[{\"pregunta_id\":\"q1\",\"tipo\":\"radio\",\"valor\":\"Excelente\"}]}"
  "fields": ["empleado_id", "fecha", "descripcion"]
}
}
</source>
</source>'''Ejemplo de Respuesta Exitosa (Código 200 OK):'''<source lang="json">
{
  "respId": 2048,
  "billing_error": null
}
</source>'''Códigos de Error Posibles:'''


==== Respuesta Exitosa ====
* '''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.


* '''Código:''' <code>201 Created</code>
----


---
== SaaS Billing ==


== Códigos de Error Frecuentes ==
=== 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"
{| class="wikitable"
!Código HTTP
!Nombre del Parámetro
!Mensaje
!Tipo
!Obligatorio
!Descripción
!Descripción
|-
|-
|400
|X-Secret-Key
|Bad Request
|String
|La petición está mal formada o faltan campos obligatorios.
|Sí (Header)
|Clave secreta enviada en la cabecera HTTP.
|-
|-
|401
|''Body''
|Unauthorized
|Object
|El token de acceso es inválido o ha expirado.
|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
|-
|-
|500
|''Ninguno''
|Internal Server Error
|N/A
|Error interno en el servidor de la aplicación.
|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.

Revisión del 08:19 21 ago 2026

SERPI Forms Core API (v1)

Categorías y Roles

GET /api/v1/categories

Ruta y Método HTTP:

GET /api/v1/categories HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>

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:

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):

[
  {
    "categoriaId": 1,
    "nombre": "Encuestas de Satisfacción",
    "color": "#3B82F6",
    "roleIds": [101, 102]
  },
  {
    "categoriaId": 2,
    "nombre": "Auditorías de Visitas",
    "color": "#10B981",
    "roleIds": []
  }
]

Códigos de Error Posibles:

  • 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:

GET /api/v1/categories/1 HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>

Descripción: Busca y devuelve los detalles de una categoría específica utilizando su identificador único numérico.

Parámetros esperados:

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):

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

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:

POST /api/v1/categories HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>
Content-Type: application/json

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:

Nombre del Parámetro Tipo Obligatorio Descripción
Body Object Objeto JSON con los datos de creación de la categoría.

Ejemplo de Payload / Body:

{
  "nombre": "Control de Calidad",
  "color": "#F59E0B",
  "roleIds": [105, 108]
}

Ejemplo de Respuesta Exitosa (Código 201 Created):

{
  "categoriaId": 3,
  "nombre": "Control de Calidad",
  "color": "#F59E0B",
  "roleIds": [105, 108]
}

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:

PUT /api/v1/categories/3 HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>
Content-Type: application/json

Descripción: Actualiza las propiedades de una categoría existente (nombre, color representativo o lista de roles autorizados).

Parámetros esperados:

Nombre del Parámetro Tipo Obligatorio Descripción
id Integer Sí (Path) ID numérico de la categoría a actualizar.
Body Object Objeto JSON con los nuevos valores de la categoría.

Ejemplo de Payload / Body:

{
  "nombre": "Control de Calidad y Procesos",
  "color": "#EF4444",
  "roleIds": [105, 108, 110]
}

Ejemplo de Respuesta Exitosa (Código 204 No Content):

HTTP/1.1 204 No Content

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:

DELETE /api/v1/categories/3 HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>

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:

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):

HTTP/1.1 204 No Content

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:

GET /api/v1/categories/roles HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>

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:

Nombre del Parámetro Tipo Obligatorio Descripción
Ninguno N/A No No requiere parámetros.

Ejemplo de Respuesta Exitosa (Código 200 OK):

[
  {
    "rolId": 101,
    "nombre": "Administrador de Ventas"
  },
  {
    "rolId": 102,
    "nombre": "Asesor Comercial"
  }
]

Códigos de Error Posibles:

  • 401 Unauthorized: No autenticado.
  • 403 Forbidden: Sin acceso a configuraciones de seguridad.

Carpetas y Workspace

GET /api/v1/folders

Ruta y Método HTTP:

GET /api/v1/folders HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>

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:

Nombre del Parámetro Tipo Obligatorio Descripción
Ninguno N/A No No requiere parámetros.

Ejemplo de Respuesta Exitosa (Código 200 OK):

[
  {
    "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
      }
    ]
  }
]

Códigos de Error Posibles:

  • 401 Unauthorized: Se requiere sesión activa.

POST /api/v1/folders

Ruta y Método HTTP:

POST /api/v1/folders HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>
Content-Type: application/json

Descripción: Crea una nueva carpeta en la raíz del entorno o como subcarpeta (indicando parentId). Requiere estar vinculada a una categoría existente.

Parámetros esperados:

Nombre del Parámetro Tipo Obligatorio Descripción
Body Object Datos para la creación de la carpeta.

Ejemplo de Payload / Body:

{
  "name": "Encuestas Region Andina",
  "parentId": "folder_10",
  "categoriaId": 1
}

Ejemplo de Respuesta Exitosa (Código 201 Created):

{
  "id": "folder_25",
  "name": "Encuestas Region Andina",
  "parentId": "folder_10",
  "categoriaId": 1,
  "color": "#3B82F6",
  "children": [],
  "forms": []
}

Códigos de Error Posibles:

  • 400 Bad Request: Nombre inválido o categoría inexistente.
  • 401 Unauthorized: No autenticado.

PUT /api/v1/folders/{id}

Ruta y Método HTTP:

PUT /api/v1/folders/25 HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>
Content-Type: application/json

Descripción: Renombra o mueve una carpeta existente dentro del árbol del Workspace.

Parámetros esperados:

Nombre del Parámetro Tipo Obligatorio Descripción
id Integer Sí (Path) ID numérico de la carpeta a modificar.
Body Object Datos actualizados de la carpeta.

Ejemplo de Payload / Body:

{
  "nombre": "Encuestas Región Andina y Centro",
  "parentId": null
}

Ejemplo de Respuesta Exitosa (Código 204 No Content):

HTTP/1.1 204 No Content

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:

GET /api/v1/folders/25/history HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>

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:

Nombre del Parámetro Tipo Obligatorio Descripción
id Integer Sí (Path) ID numérico de la carpeta a consultar.

Ejemplo de Respuesta Exitosa (Código 200 OK):

[
  {
    "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"
  }
]

Códigos de Error Posibles:

  • 401 Unauthorized: No autorizado.

DELETE /api/v1/folders/{id}

Ruta y Método HTTP:

DELETE /api/v1/folders/25 HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>

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

Parámetros esperados:

Nombre del Parámetro Tipo Obligatorio Descripción
id Integer Sí (Path) ID de la carpeta a eliminar.

Ejemplo de Respuesta Exitosa (Código 204 No Content):

HTTP/1.1 204 No Content

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:

POST /api/v1/forms HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>
Content-Type: application/json

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:

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

Ejemplo de Payload / Body:

{
  "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\":[]}"
}

Ejemplo de Respuesta Exitosa (Código 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"
}

Códigos de Error Posibles:

  • 400 Bad Request: Esquema JSON o campos obligatorios faltantes/mal formateados.
  • 401 Unauthorized: No autenticado.

PUT /api/v1/forms/{uuid}

Ruta y Método 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

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

Parámetros esperados:

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

Ejemplo de Payload / Body:

{
  "nombre": "Encuesta Visita Cliente v2",
  "titulo": "Encuesta de Satisfacción Comercial v2",
  "descripcion": "Formulario actualizado para atención a clientes.",
  "esquemaJson": "{\"settings\":{\"contexto\":\"Cliente\",\"repeatFrequency\":\"1d\"},\"components\":[]}"
}

Ejemplo de Respuesta Exitosa (Código 204 No Content):

HTTP/1.1 204 No Content

Códigos de Error Posibles:

  • 400 Bad Request: Errores estructurales en el JSON enviado.
  • 401 Unauthorized: No autenticado.
  • 404 Not Found: Formulario no encontrado por el UUID.

DELETE /api/v1/forms/{uuid}

Ruta y Método HTTP:

DELETE /api/v1/forms/d3b07384-d113-4f4a-a62e-336712345678 HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>

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:

Nombre del Parámetro Tipo Obligatorio Descripción
uuid String Sí (Path) UUID del formulario a enviar a la papelera.

Ejemplo de Respuesta Exitosa (Código 204 No Content):

HTTP/1.1 204 No Content

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:

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

Descripción: Alterna el estado de un formulario entre Activo (disponible públicamente) e Inactivo (bloquea la recepción de respuestas).

Parámetros esperados:

Nombre del Parámetro Tipo Obligatorio Descripción
uuid String Sí (Path) UUID del formulario a modificar.
Body Object Indicador de estado (activo: true/false).

Ejemplo de Payload / Body:

{
  "activo": false
}

Ejemplo de Respuesta Exitosa (Código 204 No Content):

HTTP/1.1 204 No Content

Códigos de Error Posibles:

  • 401 Unauthorized: Sin autorización.
  • 404 Not Found: Formulario no encontrado.

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

Ruta y Método HTTP:

PUT /api/v1/forms/d3b07384-d113-4f4a-a62e-336712345678/move?carpetaId=25 HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>

Descripción: Reubica un formulario en otra carpeta contenedora o en la raíz del Workspace (si se omite el parámetro carpetaId).

Parámetros esperados:

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):

HTTP/1.1 204 No Content

Códigos de Error Posibles:

  • 401 Unauthorized: No autenticado.
  • 404 Not Found: Formulario o carpeta destino no encontrados.

GET /api/v1/forms/{uuid}/history

Ruta y Método HTTP:

GET /api/v1/forms/d3b07384-d113-4f4a-a62e-336712345678/history HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>

Descripción: Retorna el historial cronológico de auditoría con todas las modificaciones realizadas sobre el formulario.

Parámetros esperados:

Nombre del Parámetro Tipo Obligatorio Descripción
uuid String Sí (Path) UUID del formulario.

Ejemplo de Respuesta Exitosa (Código 200 OK):

[
  {
    "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"
  }
]

Códigos de Error Posibles:

  • 401 Unauthorized: Token inválido.

GET /api/v1/forms/stats

Ruta y Método HTTP:

GET /api/v1/forms/stats HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>

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

Parámetros esperados:

Nombre del Parámetro Tipo Obligatorio Descripción
Ninguno N/A No No requiere parámetros.

Ejemplo de Respuesta Exitosa (Código 200 OK):

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

Códigos de Error Posibles:

  • 401 Unauthorized: No autenticado.

GET /api/v1/forms/{formId}/responses

Ruta y Método 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>

Descripción: Recupera el listado detallado de respuestas capturadas para un formulario específico dentro de un rango de fechas.

Parámetros esperados:

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):

[
  {
    "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\"}]}"
  }
]

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:

GET /api/v1/forms/45/responses/count HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>

Descripción: Retorna el conteo total numérico de respuestas acumuladas por un formulario.

Parámetros esperados:

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):

1024

Códigos de Error Posibles:

  • 401 Unauthorized: No autorizado.

GET /api/v1/forms/trash

Ruta y Método HTTP:

GET /api/v1/forms/trash HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>

Descripción: Devuelve el listado de formularios que se encuentran actualmente desactivados en la papelera de reciclaje.

Parámetros esperados:

Nombre del Parámetro Tipo Obligatorio Descripción
Ninguno N/A No No requiere parámetros.

Ejemplo de Respuesta Exitosa (Código 200 OK):

[
  {
    "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"
  }
]

Códigos de Error Posibles:

  • 401 Unauthorized: No autenticado.

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

Ruta y Método HTTP:

PUT /api/v1/forms/a1b2c3d4-e5f6-7a8b-9c0d-1e2f3a4b5c6d/restore HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>

Descripción: Restaura un formulario de la papelera, reintegrándolo a la lista activa y reactivando la recepción de respuestas.

Parámetros esperados:

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):

HTTP/1.1 204 No Content

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:

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>

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 (repeatFrequency / repeatDays).

Parámetros esperados:

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):

[
  {
    "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
  }
]

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:

POST /api/v1/forms/terceros/verificar?empresaid=15 HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>
Content-Type: application/json

Descripción: Recibe una lista de NITs o cédulas y valida cuáles de ellos tienen registros activos en la tabla gdttercero de la empresa.

Parámetros esperados:

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 Arreglo de strings con los NITs a consultar.

Ejemplo de Payload / Body:

[
  "900123456",
  "800987654",
  "1098765432"
]

Ejemplo de Respuesta Exitosa (Código 200 OK):

{
  "900123456": 1502,
  "800987654": 1509
}

Códigos de Error Posibles:

  • 401 Unauthorized: Sin sesión activa.

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

Ruta y Método HTTP:

GET /api/v1/forms/public/15/d3b07384-d113-4f4a-a62e-336712345678 HTTP/1.1
Host: api.serpi.com.co

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:

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):

{
  "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"
}

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:

POST /api/v1/forms/public/15/d3b07384-d113-4f4a-a62e-336712345678/responses HTTP/1.1
Host: api.serpi.com.co
Content-Type: application/json

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:

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 Payload JSON con la estructura de respuestas en arreglo plano.

Ejemplo de Payload / Body:

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

Ejemplo de Respuesta Exitosa (Código 200 OK):

{
  "respId": 2048,
  "billing_error": null
}

Códigos de Error Posibles:

  • 400 Bad Request: Formato JSON inválido o estructura no cumple con el esquema plano respuestas.
  • 404 Not Found: Formulario inactivo o no encontrado.

SaaS Billing

POST /api/v1/billing/process

Ruta y Método 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

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

Parámetros esperados:

Nombre del Parámetro Tipo Obligatorio Descripción
X-Secret-Key String Sí (Header) Clave secreta enviada en la cabecera HTTP.
Body Object Datos del consumo de folio SaaS.

Ejemplo de Payload / Body:

{
  "empresaId": 15,
  "gdtProductoFolioId": 8,
  "referencia": "2048"
}

Ejemplo de Respuesta Exitosa (Código 200 OK):

{
  "message": "Cobro de folio registrado correctamente."
}

Códigos de Error Posibles:

  • 400 Bad Request: Configuración de pricing no encontrada o inactiva para la empresa.
  • 401 Unauthorized: Header X-Secret-Key ausente o incorrecto.

Empresa

Ruta y Método HTTP:

GET /api/v1/companies/logo HTTP/1.1
Host: api.serpi.com.co
Authorization: Bearer <TOKEN_JWT>

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:

Nombre del Parámetro Tipo Obligatorio Descripción
Ninguno N/A No No requiere parámetros.

Ejemplo de Respuesta Exitosa (Código 200 OK):

{
  "logo": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..."
}

Códigos de Error Posibles:

  • 401 Unauthorized: Requiere sesión activa.