Apariencia
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ámetro | Descripción |
|---|---|
token | Có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."
}| Campo | Descripción |
|---|---|
valido / anulada | valido 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, rol | Persona y rol con que firmó. |
firmado_en | Fecha y hora de la firma (hora local del servidor). |
documento.tipo | paa, 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_firmas | Firmas vigentes del documento (o del movimiento). |
Errores
| HTTP | error.code | Cuándo |
|---|---|---|
| 404 | FIRMA_NO_ENCONTRADA | No existe una firma con ese código. |
| 429 | RATE_LIMIT | Má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."
}