Saltar al contenido

Verificación de firmas ​

Cada documento firmado en Panteum (líneas del PAA, certificados de disponibilidad CDP, registros presupuestales RP y sus movimientos) lleva un código QR. Quien escanea el QR —o tu sistema— puede comprobar con este endpoint que la firma existe, está vigente y a qué documento pertenece, sin iniciar sesión.

  • Autenticación: ninguna. El código del QR es un identificador aleatorio (UUID) imposible de adivinar.
  • URL base: https://presupuesto.tu-entidad.example (marcador; ver Conceptos).
  • Límite de uso: 60 consultas por minuto.
  • Qué expone: firmante, rol, fecha de la firma y un resumen del documento (número de radicado, objeto recortado y estado). Nunca expone la imagen de la firma, claves ni datos personales adicionales.

GET /api/v1/firmas/verificar/{token} ​

Alias histórico equivalente: GET /api/v1/paa/firmas/verificar/{token} (misma respuesta; úsalo solo si ya lo tienes integrado).

Parámetros de ruta ​

ParámetroDescripción
tokenCódigo de verificación impreso en el QR (formato UUID, p. ej. 00000000-0000-4000-8000-000000000000).

Ejemplos ​

curl

bash
curl -s https://presupuesto.tu-entidad.example/api/v1/firmas/verificar/00000000-0000-4000-8000-000000000000 \
  -H "Accept: application/json"

JavaScript (fetch)

js
const token = new URLSearchParams(location.search).get("codigo");
const res = await fetch(`https://presupuesto.tu-entidad.example/api/v1/firmas/verificar/${encodeURIComponent(token)}`, {
  headers: { Accept: "application/json" },
});
const cuerpo = await res.json();
if (res.ok && cuerpo.data.valido) {
  console.log(`Firma válida de ${cuerpo.data.firmante} (${cuerpo.data.rol})`);
} else if (res.status === 404) {
  console.log("Código de verificación inexistente");
}

Python (requests)

python
import requests

token = "00000000-0000-4000-8000-000000000000"
r = requests.get(
    f"https://presupuesto.tu-entidad.example/api/v1/firmas/verificar/{token}",
    headers={"Accept": "application/json"},
    timeout=10,
)
if r.status_code == 200:
    d = r.json()["data"]
    print("válida" if d["valido"] else "anulada", d["firmante"], d["documento"]["radicado"])
elif r.status_code == 404:
    print("no existe esa firma")

Respuesta de ejemplo (200) — línea del PAA ​

json
{
  "success": true,
  "data": {
    "valido": true,
    "anulada": false,
    "firmante": "María Pérez",
    "rol": "Subdirector",
    "firmado_en": "2026-09-29 15:02:11",
    "documento": {
      "tipo": "paa",
      "linea": 41,
      "radicado": "PAA-2026-000029",
      "objeto": "Adquisición de equipos de cómputo para la oficina asesora…",
      "estado": "aprobada"
    },
    "total_firmas": 3
  },
  "message": "Firma válida."
}
CampoDescripción
valido / anuladavalido es false y anulada es true cuando la firma fue anulada (p. ej. porque el trámite se rechazó y se reinició). En ese caso message es «La firma fue anulada.».
firmante, rolPersona y rol con que firmó.
firmado_enFecha y hora de la firma (hora local del servidor).
documento.tipopaa, cdp, rp o un movimiento (cdp_<tipo>, rp_<tipo>).
documento.*Identificadores y resumen del documento. Los campos varían según el tipo (numero_cdp, numero_rp, radicado, objeto, estado, …); trata los que no conozcas como opcionales.
total_firmasFirmas vigentes del documento (o del movimiento).

Errores ​

HTTPerror.codeCuándo
404FIRMA_NO_ENCONTRADANo existe una firma con ese código.
429RATE_LIMITMás de 60 consultas por minuto. Respeta Retry-After.
json
{
  "success": false,
  "error": {
    "code": "FIRMA_NO_ENCONTRADA",
    "detalle": "No existe una firma con ese código de verificación."
  },
  "message": "No existe una firma con ese código de verificación."
}